wardencommunity/warden

#logout isn't working in tests

Arepo opened this issue · 7 comments

Arepo commented

In my RSpec suite, I start out like this:

login_as(admin, scope: :admin)
visit new_admin_user_path
# fill_in various fields on a form
click_button('Create User')

All of which works fine. But when I then call #logout, either with no arguments or with :admin, and then #visit any page of the site, and insert a debugger in the controller, I can call warden.authenticate(scope: :user) and I get back an object along these lines:

#<User:0x007fd047239d98> {
  :id => 1,
  :email => "admin@fp.com", #etc }

I'm using Warden 1.2.6, with Devise 3.5.10 if relevant, Rspec-Rails (3.4.2) and Rails 4.2.6

Advice appreciated!

Thanks,

Sasha

@Arepo are you going to another page or another request before checking for logged out state? Those test helpers fire on "next_request" so you need to fire another request for them to take effect.

Arepo commented

@jsmestad I'm logging out and then going to a page that should redirect along one path if I'm logged out and another if I'm not - and going to the latter (which was what prompted me to check the state in the first first). I've tried throwing a random request to visit the root path between the #logout call and the redirecting path, but that didn't change anything.

I'm not sure if this is relevant, but doing a bit more digging, when the Proxy class receives the logout call, @users is empty, so user is set to nil.

@Arepo I would try calling the following like we do in rails_warden - https://github.com/wardencommunity/rails_warden/blob/opt-out-of-global-helpers/lib/rails_warden/authentication.rb#L34-L42

Some other questions are:

  • Are your tests capybara tests? If yes, what driver?
  • When you say you are calling #logout are you calling warden directly or through devise?
Arepo commented

@jsmestad (sorry about the ultra-slow follow-up), that link 404s for me

Re your questions:

  • Yes they're capybara tests, normally using RackTest (Poltergeist for JS tests, but most or all of these are vanilla)
  • As far as I know, I'm calling Warden directly. Pry's show-source command called on #logout returns the following:
From: /Users/mycomp/.rvm/gems/ruby-2.3.7/gems/warden-1.2.7/lib/warden/test/helpers.rb @ line 30:
Owner: Warden::Test::Helpers
Visibility: public
Number of lines: 5

def logout(*scopes)
  Warden.on_next_request do |proxy|
    proxy.logout(*scopes)
  end
end

Are there any updates on this? I ran into the same issue using:

  • warden 1.2.9
  • rails 6.0.3.3
  • selenium web driver version 85.0.4183.121

Expected behavior:

login_as user
visit "/"
logout

to actually logout the user

Actual behavior:

doesn't log out the user.

The only time it actually logs out correctly is:

login_as user
logout

Visiting any page creates a new Warden::Proxy for some reason:

   17:       # @api public
   18:       def login_as(user, opts = {})
   19:         Warden.on_next_request do |proxy|
   20:           opts[:event] ||= :authentication
   21:           byebug
=> 22:           proxy.set_user(user, opts)
   23:         end
   24:       end
   25: 
   26:       # Logs out a user from the session.
(byebug) proxy
Warden::Proxy:47173689385800 @config={:default_scope=>:user, :scope_defaults=>{}, :default_strategies=>{:user=>[:multiple_user_database_authenticatable, :rememberable], :partner=>[:multiple_user_database_authenticatable]}, :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x000055cef5ee45c0>}

and then after a page visit, calling logout and then another page visit:

   29:       # @see Warden::Proxy#logout
   30:       # @api public
   31:       def logout(*scopes)
   32:         Warden.on_next_request do |proxy|
   33:           byebug
=> 34:           proxy.logout(*scopes)
   35:         end
   36:       end
   37:     end
   38:   end
(byebug) proxy
Warden::Proxy:47173713479800 @config={:default_scope=>:user, :scope_defaults=>{}, :default_strategies=>{:user=>[:multiple_user_database_authenticatable, :rememberable], :partner=>[:multiple_user_database_authenticatable]}, :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x000055cef5ee45c0>}

and the second proxy has @users = {}

In order to track this down we are going to need someone to make a demo app that recreates the issue. There are too many variables at play to find the cause otherwise

rept commented

Actual behavior:

doesn't log out the user.

The only time it actually logs out correctly is:

login_as user
logout

We are seeing the exact same behavior. Doing a login_as user first is a workaround at the moment though.