Making assertions on current_path

I often find myself wanting to make assertions on what path a user is on after doing some action. Howerver I find that using the path methods in an integration test is quite clunky.

Now I have a test like this:

scenario "a user signs up" do
  sign_up_and_log_in_as username: 'david'

  expect(current_path).to eq user_path User.last

  expect(page).to have_content 'Welcome david'
  expect(page).to have_content 'Logout'

  expect(page).not_to have_content 'Sign up'
  expect(page).not_to have_content 'Log in'

There I’m testing that the current path is equal to the last user’s path, but having to call User.last to get to that user seems not right. It also starts getting complicated when I create more than one user in a single test.

I’m wondering if there is a better way…

In this test - where you are specifically testing sign up - I think User.last makes some sense if you want to test that they were redirected to the correct path. Another approach would be to handle the redirect location test in a controller spec that tests users are redirected to their show page after create.

In tests where you aren’t specifically testing sign up and log in, you should can stub them. For instance, Clearance offers the BackDoor for integration tests.

If you were using something like that and needed a handle on the user, your tests would look like:

user = create(:user)
visit some_path(as: user)

No need to do User.last.

When writing integration tests, it is useful to think from the user’s perspective. After signing in to the website, the user doesn’t care that the URL is /users/5, but rather wants to see his name in the header and see his profile page. I would test the page’s content rather than it’s URL.