Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSPEC: How to test that a JSON Web Token is returned by controller action

I am using Devise and JWT's to authenticate users in a project I am writing. I am having a hard time figuring out how to write a useful test to expect a JWT response.body (since each is encrypted).

The only thing I can think of is to test that they are structured as a JWT should be (a 3 segment, '.' delimited string).

Has anyone encountered testing random/hashed returns and come up with a better solution?

describe SessionTokensController, type: :controller do
  let(:current_user) { FactoryGirl.create(:user) }

  before(:each) do
    sign_in current_user
  end

  describe '#create' do
    it 'responds with a JWT' do
      post :create
      token = JSON.parse(response.body)['token']

      expect(token).to be_kind_of(String)
      segments = token.split('.')
      expect(segments.size).to eql(3)
    end
  end
end
like image 937
Drew B Avatar asked May 30 '15 20:05

Drew B


2 Answers

It really depends on what exactly you want to test.

If you simply want to test if the returned token exists and is valid you can do the following:

it 'responds with a valid JWT' do
  post :create
  token = JSON.parse(response.body)['token']

  expect { JWT.decode(token, key) }.to_not raise_error(JWT::DecodeError)
end

Although it seems much more useful to validate the claims that the token includes:

let(:claims) { JWT.decode(JSON.parse(response.body)['token'], key) }

it 'returns a JWT with valid claims' do
  post :create
  expect(claims['user_id']).to eq(123)
end

In the latter example you can validate the exact claims you included in the JWT.

like image 93
mrstif Avatar answered Nov 05 '22 11:11

mrstif


    let(:user) { create(:user, password: "123456") }

      describe "POST authenticate_user" do
        context "with a valid password" do
          it "authenticates successfully" do
            post :authenticate_user, params:{email: user.email, password: "123456"}, format: :json
            parsed_body = JSON.parse(response.body)
            # binding.pry
            expect(parsed_body.keys).to match_array(["auth_token", "user"])
            expect(parsed_body['user']['email']).to eql("[email protected]")
            expect(parsed_body['user']['id']).to eql(user.id)
          end

          it "authentication fails" do
            post :authenticate_user, params:{email: user.email, password: "123456789"}, format: :json
            parsed_body = JSON.parse(response.body)
            expect(parsed_body['errors'][0]).to eql("Invalid Username/Password")
          end
        end
      end
like image 44
Haimeng Zhang Avatar answered Nov 05 '22 12:11

Haimeng Zhang