chase dougherty
chase dougherty

Reputation: 131

How to test updating user's password in RSpec

I am using Rails 5.2, Ruby 2.4.1, and Rspec. I am trying to make an automation test using Rspec to update a User's password. I know the code works from manually testing.

The RSpec test does not pass the @user.update_attributes(user_params) condition in the controller and then goes to the else condition. Thus, my RSpec test says that the passwords are still equal to each other. How can I get my RSpec test to pass the condition?

Here is the method

# Creates user, saves old password, generates a url for user to go to, updates password, reloads user, and test if old password equals new password
context "with a valid token" do
    it "updates the user's password and resets the token" do
        test_users = User.create(first_name: 'chase', last_name: 'dougherty', email: '[email protected]', password: '1', password_confirmation: '1')
        old_password = test_users.password
        test_users.generate_password_reset_token!
        patch :update, params: { id: test_users.password_reset_token, user: { password: 'newpassword', password_confirmation: 'newpassword' } }
        test_users.reload
        expect(test_users.password).to_not eq(old_password)
      end
    end

Here is the Controller

# Finds user, test if update_attributes is true, updates password, logs user in, redirects user, displays flash
def update
    @user = User.find_by(password_reset_token: params[:id])
    if @user && @user.update_attributes(user_params)
      @user.update_attribute(:password_reset_token, nil)
      session[:user_id] = @user.id
      redirect_to '/maps'
      flash[:notice] = "Password updated"
    else
      flash[:notice] = "Password reset failure."
      render action: 'edit'
    end
  end

  private
  def user_params
    params.require(:user).permit(:password, :password_confirmation)
  end

Upvotes: 2

Views: 1078

Answers (2)

Ruslan Valeev
Ruslan Valeev

Reputation: 1907

If you use has_secure_password method in your user model, you can use this syntax for check password has been changed:

it "changes user's password" do
  expect { send_request }.to change { user.reload.authenticate(password) }.from(false).to(user)
end

Upvotes: 2

nightsurgex2
nightsurgex2

Reputation: 250

If the update_attributes line is failing, you probably have some validations on the User model that are firing and causing it to return false.

Also, I would advise against "creating" a user object in the test files. Especially because the first time you run the tests it will create the entry, but then every time after that it will return a User instance that is not saved to the database (because of uniqueness violations in the data) and the tests may not run as expected.

Unless you want to clean up your created user objects after the test runs. Otherwise you will want to use factory_bot and stub out most of these models and the database calls.

Upvotes: 1

Related Questions