I am trying to validate that I will be redirected to the homepage after a successful password reset. The final line of my Rspec test is throwing the following error:
1) PasswordRetrievalController check if password updated check if password and repassword do match
Failure/Error: expect(response).to redirect_to '/'
Expected response to be a <3XX: redirect>, but was a <200: OK>
Response body:
# ./spec/controllers/password_retrieval_controller_spec.rb:89:in `block (3 levels) in <top (required)>'
I have tried many things from looking through other threads related to this error but none seem to solve my issue. This is my Rspec test:
describe 'check if password updated' do
it 'check if password and repassword do match' do
@user = User.new
@user.email = '[email protected]'
@user.fullname = 'John Doe'
@user.name = 'classman'
@user.save!
request_params = { reset: { password: 'AAAAAAAAA123!!', password_confirmation: 'AAAAAAAAA123!!', email: '[email protected]' } }
post :update_password, params: request_params
expect(response).to redirect_to '/'
end
end
And this is my controller function, update password is towards the bottom. As you can see the password must match the retyped password in order to redirect to the homepage:
class PasswordRetrievalController < ApplicationController
def action_allowed?
true
end
def forgotten
render template: 'password_retrieval/forgotten'
end
# on click of request password button, sends a password reset url with a randomly generated token parameter to an authenticated user email
def send_password
if params[:user][:email].nil? || params[:user][:email].strip.empty?
flash[:error] = 'Please enter an e-mail address.'
render template: 'password_retrieval/forgotten'
else
user = User.find_by(email: params[:user][:email])
if user
# formats password reset url to include a queryable token parameter
url_format = '/password_edit/validate_password_token?token='
# generates a random URL-safe base64 token with default length of 16 characters
token = SecureRandom.urlsafe_base64
PasswordReset.save_token(user, token)
url = request.base_url url_format token
# delivers formatted password reset url to a valid user email
MailerHelper.send_mail_to_user(user, 'Expertiza password reset', 'send_password', url).deliver_now
ExpertizaLogger.info LoggerMessage.new(controller_name, user.name, 'A link to reset your password has been sent to users e-mail address.', request)
flash[:success] = 'A link to reset your password has been sent to your e-mail address.'
redirect_to '/'
else
ExpertizaLogger.error LoggerMessage.new(controller_name, params[:user][:email], 'No user is registered with provided email id!', request)
flash[:error] = 'No account is associated with the e-mail address: "' params[:user][:email] '". Please try again.'
render template: 'password_retrieval/forgotten'
end
end
end
# The token obtained from the reset url is first checked if it is valid ( if actually generated by the application), then checks if the token is active.
def validate_password_token
days_until_token_expiration = 1
if params[:token].nil?
require_password_reset_token
else
@token = Digest::SHA1.hexdigest(params[:token])
password_reset = PasswordReset.find_by(token: @token)
if password_reset
# URL expires after 1 day
expired_url = password_reset.updated_at days_until_token_expiration.day
if Time.now < expired_url
# redirect_to action: 'reset_password', email: password_reset.user_email
@email = password_reset.user_email
render template: 'password_retrieval/reset_password'
else
ExpertizaLogger.error LoggerMessage.new(controller_name, '', 'User tried to access expired link!', request)
flash[:error] = 'Link expired . Please request to reset password again'
render template: 'password_retrieval/forgotten'
end
else
ExpertizaLogger.error LoggerMessage.new(controller_name, '', 'User tried to access either expired link or wrong token!', request)
flash[:error] = 'Link either expired or wrong Token. Please request to reset password again'
render template: 'password_retrieval/forgotten'
end
end
end
# avoid users to access this page without a valid token
def reset_password
require_password_reset_token
end
# called after entering password and repassword, checks for validation and updates the password of the email
def update_password
if params[:reset][:password] == params[:reset][:repassword]
user = User.find_by(email: params[:reset][:email])
user.password = params[:reset][:password]
user.password_confirmation = params[:reset][:repassword]
if user.save
PasswordReset.delete_all(user_email: user.email)
ExpertizaLogger.info LoggerMessage.new(controller_name, user.name, 'Password was reset for the user', request)
flash[:success] = 'Password was successfully reset'
else
ExpertizaLogger.error LoggerMessage.new(controller_name, user.name, 'Password reset operation failed for the user while saving record', request)
flash[:error] = 'Password cannot be updated. Please try again'
end
redirect_to '/'
else
ExpertizaLogger.error LoggerMessage.new(controller_name, '', 'Password provided by the user did not match', request)
flash[:error] = 'Password and confirm-password do not match. Try again'
@email = params[:reset][:email]
render template: 'password_retrieval/reset_password'
end
end
def require_password_reset_token
flash[:error] = 'Password reset page can only be accessed with a generated link, sent to your email'
render template: 'password_retrieval/forgotten'
end
end
Any help would be greatly appreciated.
UPDATE: HTTP error is gone and I am now getting this:
1) PasswordRetrievalController check if password updated check if password and repassword do match
Failure/Error: PasswordReset.delete_all(user_email: user.email)
ArgumentError:
wrong number of arguments (given 1, expected 0)
My new Rspec tests looks like this:
describe 'check if password updated' do
it 'check if password and repassword do match' do
@user = User.new
@user.email = '[email protected]'
@user.fullname = 'John Doe'
@user.name = 'classman'
@user.save!
local_token = 'some random string'
@password_retreival = PasswordReset.new
@password_retreival.token = Digest::SHA1.hexdigest(local_token)
@password_retreival.user_email = '[email protected]'
@password_retreival.save!
request_params = { reset: { password: 'AAAAAAAAA123!!', repassword: 'AAAAAAAAA123!!', email: '[email protected]' } }
post :update_password, params: request_params
expect(response).to redirect_to '/'
end
end
CodePudding user response:
In your request_params
you're calling the confirmation param password_confirmation
, but then in your update_password
method, you're first checking if params[:reset][:password] == params[:reset][:repassword]
. It doesn't seem like you're passing in params[:reset][:repassword]
at all, so my guess is that you're failing the if
condition and falling through to your error case