OMGPOP
OMGPOP

Reputation: 1004

rails devise validation password_confirmation not working

I am having trouble with devise validation. This is my model class (Note that I have enabled validatable):

class User < ApplicationRecord

  devise :database_authenticatable, :registerable, :recoverable,
    :rememberable, :trackable, :validatable

end

And I try to validate the password confirmation using:

describe User do
  before { @user = FactoryGirl.build(:user) }
  subject { @user }
  it { should validate_confirmation_of(:password) }
end

My factory:

FactoryGirl.define do
  factory :user do
    email { FFaker::Internet.email }
    password "12345678"
    password_confirmation "12345678"
  end
end

But i got this error:

  1) User should require password_confirmation to match password
     Failure/Error: it { should validate_confirmation_of(:password) }

   Expected errors to include "doesn't match Password" when password is set to "different value",
   got no errors
 # ./spec/models/user_spec.rb:18:in `block (2 levels) in <top (required)>'

Which means the devise validator is not triggered.

Now I add a custom validator:

  validate :password_must_match
  def password_must_match
    errors.add(:password, "doesn't match confirmation") if password != password_confirmation
  end

And got this error:

Failures:

  1) User should require password_confirmation to match password
     Failure/Error: it { should validate_confirmation_of(:password) }

       Expected errors to include "doesn't match Password" when password is set to "different value",
       got errors:
       * "doesn't match Password" (attribute: password_confirmation, value: "some value")
       * "doesn't match confirmation" (attribute: password, value: "different value")
     # ./spec/models/user_spec.rb:18:in `block (2 levels) in <top (required)>'

As you can see, we now have 2 validation errors, "doesn't match Password" is from devise's validatable, and "doesn't match confirmation" is from my own custom validator.

I also tried using a custom test instead of it { should validate_confirmation_of(:password) }

  describe "#confirmation_of_password" do
    it "should fail when password does not match" do
      expect { User.create!(email: "[email protected]", password: "123456", password_confirmation: "1234567") }.to raise_error
    end
  end

And it works. But I dont wanna reinvent the wheel from shoulda

Upvotes: 1

Views: 891

Answers (1)

ruby_newbie
ruby_newbie

Reputation: 3285

In your first test You expect that it will validate confirmation of password but you pass in the same password so it never gets a chance to fail. SO you have 3 options. 1 use your first test but change the confirmation to not be the same(by passing in the params via factory girl). 2 you can expect to raise(if you do this you should specify which error will raise). Or you can also use Factory Girl's build method and expect the user to not be valid.

Upvotes: 1

Related Questions