I have a very simple password reset form, which is just a text field to enter an email and a submit button.
There are some client-side validations using JS, so I use the Capyabara JS driver when writing spec tests for it.
This test just tests that a password reset token is added to the user's auth_info
table.
describe "password reset form", js: true do
let(:email) { "[email protected]" }
# Create existing user with an email so we can reset it's password
let!(:user) { create(:user, email: email) }
before(:each) do
fill_in email_field, with: email
click_button reset_button
end
it "generates a new token" do
# `token` is definitely getting set properly when I pause it here
# with binding.pry and inspect the object using `user.reload`
# But when running the test it always shows up as `nil`
expect(user.reload.auth_info.token).to match(/[A-Fa-f0-9]{32}/)
end
end
As the comment notes, I know for a fact the token is getting properly set when I inspect it directly using binding.pry
. But RSpec and Capybara are seeing it as nil
, even after refreshing the model using reload
.
Is Capybara maintaining a different cache or something?
Thanks!
EDIT: Also tried different combinations of applying the reload
to the User
model as well as the AuthInfo
model, in case I needed to refresh the latter too
You're using a JS capable browser which means click_button is asynchronous. The result of this is you're executing click_button and then immediately checking for the token before the action triggered by the button has occurred. You can verify this by putting sleep 5
before the expect
and the test should pass. The correct way to make the test wait before the check is to use capybaras matchers to look for info on the page that changes once the click_button has completed, something like either of the following
expect(page).to have_text('text that appears after click_button has succeeded')
expect(page).to have_selector('div.abcde') #element that appears after click_button has succeeded
Those will make the test wait until the action has completed and then you can check for the token