Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Password Reset Test Passes When Run Individually But Fails When Running the Entire Test Suite

Tags:

I am testing the password reset flow that uses the Clearance authentication gem and I can't figure out how to write a test for this that passes when I run the entire test suite. The test passes when I run it individually but fails when I run the entire test suite giving me this error message:

Capybara::ExpectationNotMet: expected "/users/467591525/password/edit?token=8fd60112cf461061eb405632f35e08a3830f661c" to equal "/users/467591525/password/edit"

I was first trying to do this as a system test, which is where I have every other test like this. That one was in test/system/user_password_reset_test.rb and it inherited from ApplicationSystemTestCase as class UserPasswordResetTest < ApplicationSystemTestCase.

But I get the same error message when I run that test individually as a system test.

If I switch it to an integration test with class PasswordResetTest < ActionDispatch::IntegrationTest the test passes when run individually but fails with the same Capybara::ExpectationNotMet error when running the entire test suite.

Here's the full test:

require 'application_system_test_case'

class PasswordResetTest < ActionDispatch::IntegrationTest

  def setup
    clear_emails
    @user = users(:lee)
  end

  test 'User can reset their password' do
    perform_enqueued_jobs do
      visit sign_in_path
      assert_current_path sign_in_path
      click_link 'Forgot Password'
      assert_current_path new_password_path
      assert_title 'Password reset | Flagship'
      assert_selector 'h1', text: 'Reset your password'
      fill_in('Email', with: @user.email)
      click_button 'Reset password'
      assert_current_path passwords_path
      assert_selector 'h1', text: 'Your password reset email is on the way.'
    end
    sleep 10
    open_email(@user.email)
    current_email.click_link 'Change my password'
    assert_current_path(edit_user_password_path(@user, token: @user.confirmation_token))
    assert_title 'Change your password | Flagship'
    assert_selector 'h1', text: 'Change your password'
    fill_in('Choose password', with: 'New_Password')
    click_button 'Save this password'
    assert_current_path(dashboard_path)
  end
end

I've been trouble shooting this for a while now and can't figure out what I'm doing wrong. Here's my test/application_system_test_case.rb:

require 'test_helper'

# System tests
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :chrome, screen_size: [1400, 1400]

  include SignInHelper
end

And my test/test_helper.rb:

ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'
require 'minitest/reporters'
Minitest::Reporters.use!

# Helpers used in tests
module SignInHelper
  def sign_in_as_user_without_account
    @user_without_account = users(:user_without_account)
    visit root_path(as: @user_without_account)
  end

  def sign_in_as_account_owner
    @account_owner = users(:lee)
    visit root_path(as: @account_owner)
  end
end

# Model tests
class ActiveSupport::TestCase
  parallelize(workers: :number_of_processors)

  fixtures :all
end


class ActionDispatch::IntegrationTest
  # Controllers
  require 'capybara/rails'
  require 'capybara/minitest'
  include Capybara::DSL
  include SignInHelper

  # Mailers
  include ActiveJob::TestHelper
  include Capybara::Email::DSL

end

Have I configured something wrong there?


Update

As Thomas' answer suggested adding ignore_query: true fixed the line where the test was falling. So I changed assert_current_path(edit_user_password_path(@user, token: @user.confirmation_token)) to assert_current_path(edit_user_password_path(@user), ignore_query: true) but now the test just fails at the next step.

It seems that when capybara clicks the link in the email it doesn't go to the correct page with the token that allows the user to create a new password. Instead it goes back to the password reset page with the Clearance flash message: failure_when_forbidden: Please double check the URL or try submitting the form again..

So it seems that Capybara clicking the link is somehow not going to the correct page with the reset token. But it's weird that this passes when run in isolation then fails every time I run the whole test suite.

Here's a screenshot of that screen where the test fails: enter image description here

like image 692
Lee McAlilly Avatar asked Sep 06 '19 00:09

Lee McAlilly


1 Answers

This should remain a system test. After that it's likely that once the user hits the edit password route the token is reset so that it can only be used once. This could make your comparison fail. However, you really have no need to confirm the token is part of the route, because if the token verification failed you wouldn't get to the edit password page and the rest of the test would fail. Therefore rather than

assert_current_path(edit_user_password_path(@user, token: @user.confirmation_token))

you can just do

assert_current_path(edit_user_password_path(@user), ignore_query: true)
like image 164
Thomas Walpole Avatar answered Dec 05 '22 22:12

Thomas Walpole