Friday, July 1, 2016

Testing successful login with Devise

Leave a Comment

I'm trying to go through Michael Hartl's RoR tutorial, but it's my third time through the thing and now I'm trying to implement Devise instead of the home rolled authentication in the tutorial. As you can imagine, this is a little bit painful, mainly due to the test driven development in the RoR tutorial not mixing well with Devise. My current hang up is that I can't seem to successfully test a successful login. I have the website up on localhost, so I know the login works, but my test is still failing for some reason. Here's the integration test snippet

def setup   @user = users(:michael) end  ...  test "login with valid information" do   get user_session_path   assert_equal 200, status   post user_session_path, 'user[email]' => @user.email, 'user[password]' => "password"    follow_redirect!   assert_equal 200, status   assert_select "a[href=?]", user_session_path, count: 0 # THIS LINE FAILS   assert_select "a[href=?]", destroy_user_session_path   assert_select "a[href=?]", user_path(@user) end 

The error I get is

FAIL["test_login_with_valid_information", UsersLoginTest, 2016-06-19 11:06:18 -0400] test_login_with_valid_information#UsersLoginTest (1466348778.61s)       Expected exactly 0 elements matching "a[href="/users/sign_in"]", found 1..       Expected: 0         Actual: 1 

The login bar up at the top switches from Sign in to Account, so it looks like the test isn't getting the user in the setup block successfully signed in. Another, possibly unrelated, issue is that in another test I have, I try the same exact login method with post user_session_path... and then check that current_user is not null with assert_not current_user.nil?, but I get the error

NameError: undefined local variable or method 'current_user' for #<UsersLoginTest:0x00557f81155648> 

I've looked around and made sure that I have the correct lines of devise_for :users in my routes.rb file. I'm pretty sure It's not able to access current_user because somehow I don't have my integration test able to access resources in Devise. Those are my two problems! Any help would be greatly appreciated.

Edit: I tried

post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password 

instead of the previous method of testing the login, but I get the following errors

ERROR["test_login_with_valid_information", UsersLoginTest, 2016-06-28 20:40:59 -0400]  test_login_with_valid_information#UsersLoginTest (1467160859.16s) RuntimeError:         RuntimeError: not a redirect! 200 OK             test/integration/users_login_test.rb:36:in `block in <class:UsersLoginTest>'         test/integration/users_login_test.rb:36:in `block in <class:UsersLoginTest>'  ERROR["test_login_with_valid_information_followed_by_logout", UsersLoginTest, 2016-06-28 20:40:59 -0400]  test_login_with_valid_information_followed_by_logout#UsersLoginTest (1467160859.18s) NameError:         NameError: undefined local variable or method `current_user' for #<UsersLoginTest:0x0055d0b9e0df50>             test/integration/users_login_test.rb:49:in `block in <class:UsersLoginTest>'         test/integration/users_login_test.rb:49:in `block in <class:UsersLoginTest>' 

Edit 2:

I used Jemima's suggested fixture and reran the tests. Upon checking in the test log, I found

------------------------------------------------- UsersLoginTest: test_login_with_valid_information -------------------------------------------------   User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 762146111]] Started GET "/users/sign_in" for 127.0.0.1 at 2016-07-01 18:46:41 -0400 Processing by Devise::SessionsController#new as HTML   Rendered devise/shared/_links.html.erb (0.4ms)   Rendered devise/sessions/new.html.erb within layouts/application (1.6ms)   Rendered layouts/_shim.html.erb (0.1ms)   Rendered layouts/_header.html.erb (0.3ms)   Rendered layouts/_footer.html.erb (0.1ms) Completed 200 OK in 4ms (Views: 3.4ms | ActiveRecord: 0.0ms) Started POST "/users/sign_in" for 127.0.0.1 at 2016-07-01 18:46:41 -0400 Processing by Devise::SessionsController#create as HTML   Parameters: {"user"=>{"email"=>"michael@example.com", "password"=>"[FILTERED]"}} Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms) Processing by Devise::SessionsController#new as HTML   Parameters: {"user"=>{"email"=>"michael@example.com", "password"=>"[FILTERED]"}}   Rendered devise/shared/_links.html.erb (0.5ms)   Rendered devise/sessions/new.html.erb within layouts/application (2.1ms)   Rendered layouts/_shim.html.erb (0.1ms)   Rendered layouts/_header.html.erb (0.3ms)   Rendered layouts/_footer.html.erb (0.1ms) Completed 200 OK in 6ms (Views: 5.3ms | ActiveRecord: 0.0ms)    (0.1ms)  rollback transaction    (0.1ms)  begin transaction 

So it looks like it's unauthorized? Also, I attempted to put include Devise::Test::IntegrationHelpers at the top of my user login test, but it just throws the error NameError: uninitialized constant Devise::Test.

2 Answers

Answers 1

Have you tried it with a post_via_redirect?

post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password 

Answers 2

I'm having a similar issue that might help you to the answer. I believe my fixture isn't correct and therefore Devise is not authenticating.

My user fixture, in case it helps you:

user_no_club:   email: noclub@example.com   encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>   confirmed_at: 2016-01-02 08:31:23   confirmation_sent_at: 2016-01-02 08:30:59 

And log/test.log shows the correct email is getting passed, but then:

Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms) 

EDIT:

On further investigation, I think Devise integration testing should be done with the Devise helper. I've not been able to get it working, but my understanding from the Google group is that the docs and gem might be temporarily out of sync.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment