Created
July 25, 2014 16:06
-
-
Save cupakromer/fc5ccd67714c878dd5d8 to your computer and use it in GitHub Desktop.
Sample model spec using RSpec 3.0 and Ruby 2.x
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rails_helper' | |
RSpec.describe User, type: :model do | |
def build_valid_user(opts = {}) | |
valid_opts = { | |
name: "Example User", | |
email: "user@example.com", | |
password: "foobar", | |
password_confirmation: "foobar", | |
} | |
User.new valid_opts.merge(opts) | |
end | |
it { should respond_to(:name) } | |
it { should respond_to(:email) } | |
it { should respond_to(:password_digest) } | |
it { should respond_to(:password) } | |
it { should respond_to(:password_confirmation) } | |
it { should respond_to(:authenticate) } | |
context "given a valid user" do | |
subject(:any_valid_user) { build_valid_user } | |
it { should be_valid } | |
end | |
context "validations" do | |
subject(:a_user) { build_valid_user } | |
before do | |
expect(a_user).to be_valid, "PRECONDITION FAILED: User is not valid!" | |
end | |
it "requries a name" do | |
expect{ a_user.name = " " }.to change(a_user, :valid?).to(false) | |
end | |
it "requires an email" do | |
expect{ a_user.email = " " }.to change(a_user, :valid?).to(false) | |
end | |
it "requires a name less than 51 characters" do | |
expect{ a_user.name = "a" * 51 }.to change(a_user, :valid?).to(false) | |
end | |
context "verifies the email format" do | |
# In general, using a Regex for validating an email is horribly broken. | |
# Email addresses can have many different things. Additionally, there's | |
# nothing a regex can do to verify that the email account is even open. | |
# | |
# Generally, in our apps we do not validate emails outside of forcing it | |
# as part of the sign-up process. Thus it has to be a live email for at | |
# least part of the time. | |
it "does not allow symbols in the domain" do | |
expect{ a_user.email = "user@foo,com" } | |
.to change(a_user, :valid?).to(false) | |
end | |
it "requires an @ symbol between address and domain" do | |
expect{ a_user.email = "user_at_foo.org" } | |
.to change(a_user, :valid?).to(false) | |
end | |
it "requires an TLD in the domain" do | |
expect{ a_user.email = "example.user@foo." } | |
.to change(a_user, :valid?).to(false) | |
end | |
end | |
it "requires a unique email address" do | |
_an_existing_user = a_user.dup | |
expect{ _an_existing_user.save! }.to change(a_user, :valid?).to(false) | |
end | |
it "requires a password" do | |
expect{ a_user.password = " " }.to change(a_user, :valid?).to(false) | |
end | |
it "requires the password to match the confirmation password" do | |
expect{ a_user.password_confirmation = "mismatch" } | |
.to change(a_user, :valid?).to(false) | |
end | |
it "requires a password longer than 5 characters" do | |
expect{ a_user.password = a_user.password_confirmation = "a" * 5 } | |
.to change(a_user, :valid?).to(false) | |
end | |
end | |
context "valid email format" do | |
# ... one spec per email format | |
end | |
context "authenticating a user" do | |
# Note I only extracted these lets and before **AFTER** I wrote the | |
# following three specs with these as local variables. I then made the | |
# decision that yes these could all "be the exact same user", meaning I | |
# could extract them. | |
let(:any_password) { 'this is not a good password' } | |
let(:any_valid_email) { 'any_email@example.com' } | |
let(:existing_user) { | |
build_valid_user( | |
email: any_valid_email, | |
password: any_password, | |
) | |
} | |
before { existing_user.save! } | |
it "passes given valid authentication credentials" do | |
registered_email, matching_password = any_valid_email, any_password | |
expect( | |
User.authenticate(email: registered_email, password: matching_password) | |
).to eq existing_user | |
end | |
context "with invalid credentials", "no matching email" do | |
matching_password = any_password | |
bad_email = 'tricky@hobbits.com' | |
expect( | |
User.authenticate(email: bad_email, password: matching_password) | |
).to be false | |
end | |
context "with invalid credentials", "no matching password" do | |
registered_email = any_valid_email | |
different_password = 'try all the combos!' | |
expect( | |
User.authenticate(email: registered_email, password: different_password) | |
).to be false | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment