0
votes

I'm at a loss here, everything was going smoothly until about mid-way through chapter 7 of the Rails tutorial by Michael Hartl. I'm now getting failing tests saying that the email has already been taken, and (I believe because of the first error) it won't save a valid user to change the count by 1. I've gone back to chapter 6 and essentially copy and pasted the code back into my program in hopes that it was a nesting error or similar, but no such luck. Here's the failing tests I get:

Failures:

1) User pages profile page Failure/Error: let(:user) { FactoryGirl.create(:user) } ActiveRecord::RecordInvalid: Validation failed: Email has already been taken # ./spec/requests/user_pages_spec.rb:8:in block (3 levels) in <top (required)>' # ./spec/requests/user_pages_spec.rb:9:inblock (3 levels) in '

2) User pages signup with valid information should create a user Failure/Error: expect { click_button submit }.to change(User, :count).by(1) count should have been changed by 1, but was changed by 0 # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '

My spec/models/user_spec.rb

require 'spec_helper'

describe User do

  before do
  @user = User.new(name: "Example User", email: "[email protected]",
                   password: "foobar", password_confirmation: "foobar")
  end

  subject { @user }

  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 be_valid }

  describe "when name is not present" do
    before { @user.name = " " }
    it { should_not be_valid }
  end


  describe "when email is not present" do
    before { @user.email = " " }
    it { should_not be_valid }
  end

  describe "when name is too long" do
    before { @user.name = "a" * 51 }
    it { should_not be_valid }
  end

  describe "when email format is invalid" do
    it "should be invalid" do
      addresses = %w[user@foo,com user_at_foo.org example.user@foo.
                     foo@bar_baz.com foo@bar+baz.com]
      addresses.each do |invalid_address|
        @user.email = invalid_address
        expect(@user).not_to be_valid
      end
    end
  end

  describe "when email format is valid" do
    it "should be valid" do
      addresses = %w[[email protected] [email protected] [email protected] [email protected]]
      addresses.each do |valid_address|
        @user.email = valid_address
        expect(@user).to be_valid
      end
    end
  end

  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.email = @user.email.upcase
      user_with_same_email.save
    end

    it { should_not be_valid }
  end

  describe "when password is not present" do
    before do
      @user = User.new(name: "Example User", email: "[email protected]",
                     password: " ", password_confirmation: " ")
    end
    it { should_not be_valid }
  end

  describe "when password doesn't match confirmation" do
    before { @user.password_confirmation = "mismatch" }
    it { should_not be_valid }
  end

  describe "when password confirmation is nil" do
    before { @user.password_confirmation = nil }
    it { should_not be_valid }
  end

  describe "with a password that's too short" do
    before { @user.password = @user.password_confirmation = "a" * 5 }
    it { should_not be_valid }
  end

  describe "return value of authenticate method" do
    before { @user.save }
    let(:found_user) { User.find_by(email: @user.email) }

    describe "with valid password" do
      it { should eq found_user.authenticate(@user.password) }
    end

    describe "with invalid password" do
      let(:user_for_invalid_password) { found_user.authenticate("invalid") }

      it { should_not eq user_for_invalid_password }
      specify { expect(user_for_invalid_password).to be_false }
    end
  end
end

user_pages_spec.rb

require 'spec_helper'

describe "User pages" do

  subject { page }

  describe "profile page" do
    let(:user) { FactoryGirl.create(:user) }
    before { visit user_path(user) }

    it { should have_content(user.name) }
    it { should have_title(user.name) }
  end

  describe "signup page" do
    before { visit signup_path }

    it { should have_content('Sign up') }
    it { should have_title(full_title('Sign up')) }
  end

  describe "signup" do

    before { visit signup_path }

    let(:submit) { "Create my account" }

    describe "with invalid information" do
      it "should not create a user" do
        expect { click_button submit }.not_to change(User, :count)
      end
    end

    describe "with valid information" do
      before do
        fill_in "Name",         with: "Example User"
        fill_in "Email",        with: "[email protected]"
        fill_in "Password",     with: "foobar"
        fill_in "Confirmation", with: "foobar"
      end

      it "should create a user" do
        expect { click_button submit }.to change(User, :count).by(1)
      end
    end
  end
end

I know people have run into similar issues with FactoryGirl but it's usually later in the tutorial from what I've gathered and has to do with writing to the development database which I've confirmed is not happening in my instance. If anyone has any help, hints, or resources they'd be greatly appreciated about now.

EDIT: added User.rb

class User < ActiveRecord::Base

    before_save { self.email = email.downcase }
    validates :name, presence: true, length: { maximum: 50 }
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
    validates :email, presence:   true,
                    format:     { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
    has_secure_password
    validates :password, length: { minimum: 6 }
end

and factories.rb

FactoryGirl.define do
  factory :user do
    name     "Example Guy"
    email    "[email protected]"
    password "foobar"
    password_confirmation "foobar"
  end
end

Thanks!

2

2 Answers

1
votes

It's hard to know without seeing your User model and factories.rb file, but I'm guessing you have a uniqueness constraint on emails for users. Something like validates :email, uniqueness: true.

Additionally, I'm betting you've specified a hardcoded email address in your user factory.

Because of this constraint, factory_girl is creating a user with email "[email protected]", then you try to create a second user, but with the same email address, and the validation (correctly) prevents you from saving this new user.

If this is the case, you want each user generated with factory_girl to have a unique email address, something you can accomplish using sequences.

0
votes

Maybe you have a hardcoded user with the same email. Either delete the user by hand or run bundle exec rake db:reset and that will get rid of the user that's giving you trouble (this will clear out your entire database btw so make sure this is what you want to do). I've run into this problem a few times while going through the tutorial too.