snowguy
snowguy

Reputation: 911

Test stay signed in with Rspec

I'm a bit stumped on how (and where) to write some rspec tests for the "stay signed in" functionality you see all over, including on the google login.

The examples I found on the web weren't much help. Specifically I want to test these two scenarios.

1

2

My first attempt at solving the problem involved simulating a browser close by deleting the user_id I stored in the session (since it gets deleted on browser close). However, these tests failed because I was working in the request spec folder and have no access there to the session variables. My earlier related question: session available in some rspec files and not others. how come?

What is the best way to do these test with rspec?

Upvotes: 1

Views: 1366

Answers (3)

Jussi Hirvi
Jussi Hirvi

Reputation: 725

This still seems to be a recurring problem in 2018. Some basic documentation is clearly missing. I finally found a solution: "Show me the cookies" gem.

Switching the Capybara driver clears the session, so one possibility would be changing the driver in the middle of a test to simulate browser close/open. But getting an alternative driver (for example selenium, or selenium_chrome) to work is not trivial, and besides this method would probably delete all cookies.

Also this simple command resets the session: Capybara.reset_sessions! But the problem again is that it not only destroys the session cookie but also permanent cookies. So it's useless for testing "Remember me" functionality.

I finally settled on Show me the cookies gem. It was very simple to install and implement. I just followed the provided directions for rspec. The command expire_cookies provides a satisfying simulation of quitting and opening a browser.

Upvotes: 0

Wolfram Arnold
Wolfram Arnold

Reputation: 7273

There are two problems here, that I think belong into different tests:

  1. User cannot access protected page when not logged in. That's a controller test.
  2. User gets logged in automatically even after the session has been destroyed, so long the "remember" me flag was set in the cookie.

For #1, you can try something like:

describe UsersController do
  context "when not logged in" do
    context "GET users/edit" do
      it "redirects to login" do
        get :edit, :id => 123
        response.should redirect_to login_path
      end
    end
  end
end

You can make a more general test case that asserts all actions which aren't explicitly listed, so that you don't have test gaps if the access code later becomes more permissive by accident. But that's a more subtle point.

For #2 you can write a request spec that sets the "remember me flag", then logs out, then logs in again and checks that you get to the page you expected. Drive all this from the browser by filling out credentials, checking the remember me box, clicking buttons.

The question is: Why? Why do you want to test this? Are you using a home-grown login system? Highly discouraged, unless you're a top-notch security expert. If you're not using a home-grown system, but instead Devise which comes tested, then don't re-test the library functionality. Just only test your application code, such as access rights to certain pages, which is covered by #1. You can also take a look at the tests that come with Devise how they test for this condition.

Hope this helps.

Update To clarify the request spec for #2. As mentioned in the other answer by @cutalion (who deserves the credit for the right answer), the mechanism for verifying that login can persist across session closing is built into the ActionDispatch IntegrationTest framework with open_session.

See Rails docs IntegrationTest API which includes examples. A blog post expanding on the use of a custom DSL.

Upvotes: 1

cutalion
cutalion

Reputation: 4394

I think you should try standard rails method for integration tests - open_session.
Personally I never did that and can't give you tested code.

See multiple sessions example on rails guides.

Upvotes: 1

Related Questions