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:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With