1

I had overridden default responding in devise which renders json instead of html template. It works fine when I test it with curl or postman, but when it comes to test it with rspec. I have read infos how to test controllers with devise from readme.md, so that it works fine with logging into, but does not work when I want to test unauthenticated request.

Response received:

<html><body>You are being <a href=\"http://test.host/users/sign_in\">redirected</a>.</body></html>

instead of:

{"error":"You need to sign in or sign up before continuing."}

app/controllers/playlists_controller.rb:

class PlaylistsController < ApplicationController
  before_action :authenticate_user!

  def index
    render json: Playlist.all
  end
end

app/controllers/sessions_controller.rb:

class SessionsController < Devise::SessionsController
  clear_respond_to
  respond_to :json
end

spec/controllers/playlists_controller_spec.rb:

require 'rails_helper'

describe PlaylistsController do
  context 'when user is not signed in' do
    it 'returns authorization error message' do
      get :index
      expect(response.body).to eq 'some message here'
    end
  end
end

spec/support/devise.rb

RSpec.configure do |config|
  config.include Devise::TestHelpers, type: :controller
end
Robs
  • 153
  • 2
  • 10

3 Answers3

1

The reason it doesn't work in your controller test and does work in curl is because you aren't hitting the :index with format of :json (which you've written logic to respond_to :json).

Change this

it 'returns authorization error message' do
  get :index
  ...
end

to this

it 'returns authorization error message' do
  get :index, format: :json
  ...
end
MilesStanfield
  • 4,571
  • 1
  • 21
  • 32
  • That worked. I am wondering why this works for curl without setting Content-Type or Accept headers and for rspec not... – Robs Sep 11 '16 at 16:42
  • Interesting. I assumed you used content type json in curl. I actually don't know why it would use json without content type set – MilesStanfield Sep 11 '16 at 16:51
  • Actually no header was set. It should respond to json by default as it was supposed in overridden controller. Anyway - thanks for answering me :) – Robs Sep 11 '16 at 18:08
1

In Rails 5, the only way I could get the controller action to process as JSON was :

get :action, params: { format: :json, ... }

Hope this can help !

V. Déhaye
  • 493
  • 6
  • 20
0

You can define FailureApp or use conditional filters, both suggested in the answer to similar question: https://stackoverflow.com/a/10042104/580346

Community
  • 1
  • 1
mrzasa
  • 22,895
  • 11
  • 56
  • 94
  • Fine, this is adding additional logic for tests. I already have this working with curl, but this is failing for tests. I don't think I should change app code only for tests. – Robs Sep 11 '16 at 15:16
  • You are right, I missed that it works with curl and fails in tests. Btw regarding the format and headers you may like this article: http://blog.iempire.ru/2016/09/05/rails-obstractions/ – mrzasa Sep 12 '16 at 07:46