Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorator spec can't access current_user when nil #857

Open
jrochkind opened this issue Jul 2, 2019 · 2 comments
Open

Decorator spec can't access current_user when nil #857

jrochkind opened this issue Jul 2, 2019 · 2 comments

Comments

@jrochkind
Copy link
Contributor

jrochkind commented Jul 2, 2019

My decorators sometimes need to access the current_user? helper, from devise.

If I mock a current user using Devise::Test::ControllerHelpers sign_in, like so:

before do
  sign_in create(:user)
end

That works, no problem. My decorators that access current_user get back that specified user when run under the spec, all is good.

But my app has public facing pages that have no signed in user, current_user is nil.

If I run a spec that has not done a Devise::Test::ControllerHelpers sign_in with a user -- because I am trying to test the scenario where there is no logged_in user, current_user is nil -- and that spec tries to exersize a decorator which asks for current_user, I get the dreaded:

     Devise::MissingWarden:
       Devise could not find the `Warden::Proxy` instance on your request environment.
       Make sure that your application is loading Devise and Warden as expected and that the `Warden::Manager` middleware is present in your middleware stack.
       If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` module to inject the `request.env['warden']` object for you.

Very simple reproduction (Devise 4.6.2, Draper 3.1.0, Rails 5.2.3):

# app/decorators/test_decorator.rb
class TestDecorator < Draper::Decorator
  def has_current_user?
    h.current_user.present?
  end
end

# spec/decorators/test_decorator_spec.rb
require 'rails_helper'

describe TestDecorator do
  let(:decorator) { TestDecorator.new(Object.new) }
  it "can answer has_current_user?" do
    expect(decorator.has_current_user?).to be false
  end
end

That will raise the Devise::MissingWarden

Is there a way to set up my :decorator specs so h.current_user works, even when I am not mocking a logged in user, I want no logged in user?

Ideally it would be something I could set up globally that would Just Work, and then specs which do want a logged in user would use Devise::Test::ControllerHelpers#sign_in as ordinary. If I need to do completely different mutually exclusive set up for "a mocked logged in user" vs "no mocked logged in user, current_user should be nil", that would be unfortunate. But would still at least get my tests possible again!

@jrochkind
Copy link
Contributor Author

Ah, I see the sign_in method I am using in test setup in a decorator test, that I thought was coming from Devise::Test::ControllerHelpers, is actually coming from this gem, Draper::DeviseHelper.

Not sure what's going on, or how this changes things. But looking at what that does, to see if I can figure out how to make it set up a nil current_user instead... and if there's a way to do this in a global before block for decorator specs, that can still be overrridden by a specific sign_in.

@jrochkind
Copy link
Contributor Author

jrochkind commented Jul 2, 2019

This seems to work if I put it in my rails_helper.rb:

  config.before(:each, type: :decorator) do
    _stub_current_scope :user, nil
  end

Can't actually use the Draper::DeviseHelper#sign_in, because of the way nil short-circuits it, so do have to use the underscored (presumably not meant for public consumption) Draper::DeviseHelpers#_stub_current_user_scope.

This will of course define a singleton method current_user on the fly.

If I then have some tests that do want a non-nil current_user, and call sign_in with an argument... that will define a current_user on the singleton again, on top of the first one.

This does seem to work... but is all a bit hacky.

Should Draper document this better and/or support this better? It seems reasonable to want devise current_user to work for nil user in decorator tests, not just for when a particular user has been mocked as logged in with sign_in.

jrochkind added a commit to sciencehistory/scihist_digicoll that referenced this issue Jul 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant