Rails 4 + Devise: How to write a test for Devise Reset Password without RSpec?

For reasons beyond my control, I cannot use RSpec for testing in my current project. I am trying to check out the Devise Reset Password, and I cannot come up with something that works.

Here is what I still have:

require 'test_helper' class ResetPasswordTest < ActionDispatch::IntegrationTest setup do @user = users(:example) end test "reset user password" do old_password = @user.encrypted_password puts @user.inspect # This assertion works assert_difference('ActionMailer::Base.deliveries.count', 1) do post user_password_path, user: {email: @user.email} end # puts @user.reset_password_token => nil # Not sure why this doesn't assign a reset password token to @user patch "/users/password", user: { reset_password_token: @user.reset_password_token, password: "new-password", password_confirmation: "new-password", } # I get a success here, but I'm not sure why, since reset password token is nil. assert_response :success # This assertion doesn't work. assert_not_equal(@user.encrypted_password, old_password) end end 

I added a few comments above where things do not seem to work. Does anyone have an idea or idea on how best to test this?

+8
ruby-on-rails ruby-on-rails-4 devise minitest
source share
3 answers

I realized that you need to restart the user when sending the reset password and when put ting route /user/password . You also need to get the password token from the email, as it is different from the one stored in the database.

 require 'test_helper' class ResetPasswordTest < ActionDispatch::IntegrationTest setup do @user = users(:example) end test "reset user password" do # store old encrypted password old_password = @user.encrypted_password # check to ensure mailer sends reset password email assert_difference('ActionMailer::Base.deliveries.count', 1) do post user_password_path, user: {email: @user.email} assert_redirected_to new_user_session_path end # Get the email, and get the reset password token from it message = ActionMailer::Base.deliveries[0].to_s rpt_index = message.index("reset_password_token")+"reset_password_token".length+1 reset_password_token = message[rpt_index...message.index("\"", rpt_index)] # reload the user and ensure user.reset_password_token is present # NOTE: user.reset_password_token and the token pulled from the email # are DIFFERENT @user.reload assert_not_nil @user.reset_password_token # Ensure that a bad token won't reset the password put "/users/password", user: { reset_password_token: "bad reset token", password: "new-password", password_confirmation: "new-password", } assert_match "error", response.body assert_equal @user.encrypted_password, old_password # Valid password update put "/users/password", user: { reset_password_token: reset_password_token, password: "new-password", password_confirmation: "new-password", } # After password update, signed in and redirected to root path assert_redirected_to root_path # Reload user and ensure that the password is updated. @user.reload assert_not_equal(@user.encrypted_password, old_password) end end 
+6
source share

Perform PasswordsController testing internally. I wanted to test my PasswordsController with additional functionality and went to the β€œDevelop Controller Tests” to get help in building tests for the default Devise function, and then adding assertions for my new functionality in the test case.

As stated in other answers, you should get reset_password_token . Instead of parsing the delivered email, as in another solution here, you can get the token just like Devise:

 setup do request.env["devise.mapping"] = Devise.mappings[:user] @user = users(:user_that_is_defined_in_fixture) @reset_password_token = @user.send_reset_password_instructions end 

Check out the Devise solution for PasswordControllerTest :

https://github.com/plataformatec/devise/blob/master/test/controllers/passwords_controller_test.rb .

+11
source share
 require 'rails_helper' feature 'User' do let(:user) { create(:user) } let(:new_password) { 'Passw0rd!' } it 'reset password' do visit '/' click_link 'Forgot password?' fill_in 'E-mail', with: user.email expect do click_button 'Send me reset password instructions' end.to change(ActionMailer::Base.deliveries, :count).by(1) expect(unread_emails_for(user.email)).to be_present open_email(user.email, with_subject: 'Reset password instructions') click_first_link_in_email fill_in 'New password', with: new_password fill_in 'Confirm new password', with: new_password click_button 'Change password' expect(page).to have_notice 'Your password has changed' click_link 'Logout' fill_in 'E-mail', with: user.email fill_in 'Password', with: new_password click_button 'Sign in' expect(page).to have_notice 'Wellcome!' end end 

This code requires the mail_spec and FactoryGirl attributes.

+3
source share

All Articles