РоР, Как я могу использовать контроллеры модульного тестирования с использованием RSPEC, которые защищены системой аутентификации JWT?

Я пытаюсь выполнить модульное тестирование контроллеров API RoR, используя гем rspec-rails.
Все мои контроллеры реализованы в этом классе ProtectedController, который перехватывает все запросы и проверяет заголовок авторизации.

      class V1::ProtectedController < V1::BaseController
  include JsonWebTokenAuthentication

  attr_reader :current_user
  before_action :validate_token!
  # Check if authorize has been called (Pundit gem)
  after_action :verify_authorized

  private

  def validate_token!
    authorization_header = request.headers['Authorization'] || ''
    puts "header: #{request.headers['Authorization']}"
    jwt = JsonWebToken.new(authorization_header.gsub('Bearer ', ''))
    if payload = jwt.verify
      account = Account.find_by(id: payload[:user][:id])
      if account.nil? || account.token_checksum == payload[:user][:token_checksum]
        # If no account found still authorize because it is likely an app token
        @current_user = Account.from_jwt_data(payload[:user])
      end
    end
    return if @current_user

    raise JsonWebTokenAuthentication::Unauthorized, 'invalid token'
  end
end

Чтобы смоделировать эту систему аутентификации для тестирования, я создаю этот модуль AuthHelper, который будет возвращать JWT администратора (позже я могу создать другие учетные записи для других ролей или передать учетные данные для входа в эту функцию)

      module AuthHelper
  include Rack::Test::Methods

  def app
    Rails.application # This assumes you're using a Rails application
  end
  def admin_login
    params = {
      grant_type: 'password',
      email: 'admin@arime.com',
      password: 'preci666'
    }
    post '/api/v1/auth/token', params
    expect(last_response.status).to eq(200)

    auth_response = JSON.parse(last_response.body)
    @access_token = auth_response['access_token']
  end

end

Теперь все, что мне нужно сделать, это передать JWT во все мои запросы. что я сделал, например, в своей Workers_controller_spec, как показано ниже.

      require 'rails_helper'

RSpec.describe V1::WorkersController, type: :request do
  include AuthHelper

  before { 
    admin_login 
    auth = "Bearer #{@access_token}"
  }


  describe "GET #index" do
    it 'assigns @workers' do
      worker1 = FactoryBot.create(:worker)
      worker2 = FactoryBot.create(:worker)
      #request.headers['Authorization'] = auth
      auth = "Bearer #{@access_token}"
      #request.headers['Authorization'] = auth
      get v1_workers_path , headers: {
        Authorization: auth
      }

      expect(response).to have_http_status(200)
    end
  end
end

Для меня все выглядит правильно, но не для rspec, статус ответа всегда 401. И самое странное, что когда я отлаживал request.headers['Authorization'] в своем защищенном контроллере, я обнаружил, что он пуст и находится в request.headers. проверить, я вижу свой заголовок авторизации:/
Когда я попытался передать заголовок, как в комментируемой части #request.headers['Authorization'] = auth, я получаю эту ошибку

      1) V1::WorkersController GET #index assigns @workers
 Failure/Error: request.headers['Authorization'] = auth
 
 ArgumentError:
   wrong number of arguments (given 0, expected 1..2)

помещает "header: #{request.headers['Authorization']}" в мой защищенный контроллер, возвращает

      header: 

помещает "запрос: #{request.inspect}" возвращает

      header: request: #<ActionDispatch::Request GET 
"http://example.org/api/v1/workers? 
 headers[Authorization]=Bearer+eyJhbGciOiJSUzI1NiJ9.eyJp..." for 
 127.0.0.1>

версия Ruby: 2.7.7 версия рельсов: 7.0.4.2 версия rspec-rails: 6.0.1

Кто-нибудь может помочь мне найти решение? или есть более правильный способ смоделировать мою систему аутентификации и вернуть current_user?

0 ответов

Другие вопросы по тегам