Using Rspec to test that Authorization header is set on a sign up
toomanyjoes opened this issue · 3 comments
I am currently unable to get a JWT token in the response headers of a rspec test after a successful sign_up.
devise (4.7.3)
devise-jwt (0.8.0)
warden (1.2.9)
warden-jwt_auth (0.5.0)
I think my problem might be that I'm using a controller test in order to validate this. Is it even possible to test that an Authorization header is set on an rspec controller type test? The controller test needs to use the action #create
instead of the url path. Does this cause jwt dispatcher not to recognize that a jwt should be added to the header on this request?
on the other hand if I use a type: :request
I no longer have access to the request object to set request.env['devise.mapping'] = Devise.mappings[:api_v1_user]
What would be the recommended method for testing this? This is what my test looks like:
RSpec.describe Api::V1::RegistrationsController, type: :controller do
before :each do
request.env['devise.mapping'] = Devise.mappings[:api_v1_user]
end
describe '#create' do
let!(:valid_attributes) {
{
api_v1_user: {
first_name: 'Natalia',
last_name: 'Stanton',
email: 'natalia.stanton@gmail.com',
password: 'bogus1',
password_confirmation: 'bogus1'
}
}
}
it 'should create a new user' do
expect {
post :create, format: 'json', params: valid_attributes
}.to change(User, :count).by(1)
expect(response.headers).to include('Authorization')
end
end
routes.rb
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
devise_for :users, defaults: { format: :json }
end
end
end
devise.rb:
Devise.setup do |config|
.
.
.
config.jwt do |jwt|
jwt.secret = ENV.fetch('DEVISE_JWT_SECRET_KEY')
jwt.dispatch_requests = [
['POST', %r{api/v1/users}],
['POST', %r{api/v1/registrations}],
]
jwt.request_formats = {
user: [:json],
}
end
end
Expected
Authorization {JWT} header in response in rspec test
Actual
No authorization header is set
The token is added in a rack middleware. Controller tests don't go through them so, basically, you have no way. Acknowledging that everything is opinionated, I think it makes no sense to test in your application something that is already tested on warden-jwt_auth
& devise-jwt
. What I'd do is to add an integration test with your... well... integration, to check that all pieces are correctly glued.
Closing for now but feel free to add more comments if needed.
@toomanyjoes - @waiting-for-dev is right. You have to use Request level specs to test this. Here's one such spec from an app of mine.
require 'rails_helper'
RSpec.describe "API::V1::Sessions", type: :request do
describe "POST /api/v1/authenticate" do
it "returns a JWT token upon successful login" do
known_password = 'p@ssw0rd'
customer = create(:customer, password: known_password)
post '/api/v1/authenticate', as: :json, params: { customer: { email: customer.email, password: known_password } }
aggregate_failures do
expect(response).to have_http_status(:success)
expect(response.content_type).to eq("application/json; charset=utf-8")
expect(response.headers).to have_key('Authorization')
expect(response.headers['Authorization']).to be_starts_with('Bearer')
end
end
end
end