I have a User
model and Authentications
model, which is a basic omniauth setup. Essentially, users can sign up through oauth without setting a password.
I have a Authentication.is_destroyable?
method that returns true if the user has a password or has more than one authentication. Essentially, this prevents users deleting their one and only way of authentication.
def is_destroyable?
if user.encrypted_password.present? || user.authentications.count > 1
true
else
errors.add :base, 'not allowed'
false
end
end
When testing this in development it works as expected under all conditions. However, my unit tests are failing:
describe "Authentication#is_destroyable?" do
before(:each) do
# This creates a user with no password and a single authentication
@user = FactoryGirl.create(:user_with_oauth)
@auth = @user.authentications.first
end
# This spec passes :)
it "should return false when is users only authentication method" do
@auth.is_destroyable?.should be_false
end
# This FAILS - I have no idea why :(
it "should return true when user has multiple authentications" do
@user.authentications.create FactoryGirl.attributes_for(:authentication, :provider => 'twitter')
@auth.is_destroyable?.should be_true
end
# This FAILS - I have no idea why :(
it "should return true when user has a password" do
@user.update_attributes :password => 'password'
@auth.is_destroyable?.should be_true
end
end
I've spent the best part of 3 hours banging my head against the wall. I can't for the life of me understand why this works when I manually test the functionality (and Cucumber stories pass also testing the functionality), but in rspec the unit tests are failing. Is there something obvious that I'm missing?
Edit
As requested, here's some further detail.
Both failing specs fail with:
Failure/Error: @auth.is_destroyable?.should be_true
expected false to be true
The Factories:
FactoryGirl.define do
factory :user do
username { FactoryGirl.generate(:username) }
name 'Test User'
email { FactoryGirl.generate(:email) }
password 'password'
end
factory :user_with_oauth, :parent => :user do
password nil
authentications [ FactoryGirl.build(:authentication) ]
end
factory :authentication do
provider 'facebook'
uid SecureRandom.hex(16)
end
end
Also, maybe relevant, am using DatabaseCleaner with the truncation strategy.