l85m
l85m

Reputation: 838

rspec/factory issues from hartl chapter 9.2 - app functions fine, but tests are failing

All tests were working fine up until I made the last change to my rspec tests in section 9.2 of Hartl's tutorial. At that point all the related tests in my user_pages_spec.rb and application_pages_spec.rb failed.

I've checked the site though and the failures are not showing up in real life - so I think its a problem with the way the test suite is trying to simulate users - which makes sense as that's what I changed.

One thing to note - I've tweaked the Hartl tutorial a bit as I've gone along, but most have been cosmetic or minor - the only thing that might matter here is I use User name instead of email for login and lookup.

Full files are below - would really appreciate any help as I've been banging my head against the wall for a couple hours now and its getting pretty discouraging.

spec/support/utilities.rb:

def full_title(page_title)
  base_title = "nsent"
  if page_title.empty?
    base_title
  else
    "#{base_title} | #{page_title}"
  end
end

def sign_in(user)
  visit signin_path
  fill_in "Name",    with: user.name
  fill_in "Password", with: user.password
  click_button "Sign in"
  # Sign in when not using Capybara as well.
  cookies[:remember_token] = user.remember_token
end

spec/support/factories.rb:

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

user_pages_spec.rb:

require 'spec_helper'

describe "User pages" do

  subject { page }

  describe "signup" do

    before { visit signup_path }

    describe "should have the right title and heading" do
            it { should have_selector('h1',    text: "Sign up") }
        it { should have_selector('title', text: full_title("Sign up")) }
    end

    let(:submit) { "Sign up" }

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

        it { should have_selector('title', text: "Sign up") }
        it { should have_content('field') }
      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 "Password confirmation", with: "foobar"
      end

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

      describe "after saving the user" do
        before { click_button submit }
        let(:user) { User.find_by_email('[email protected]') }

        it { should have_selector('title', text: user.name) }
        it { should have_selector('div.alert.alert-success', text: 'welcome') }
        it { should have_link('Sign out') }
      end
        end
  end

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

      it { should have_selector('h1',    text: user.name) }
      it { should have_selector('title', text: user.name) }
    end

  describe "edit" do
    let(:user) { FactoryGirl.create(:user) }
    before do
      sign_in user
      visit edit_user_path(user)
    end

    describe "page" do
      it { should have_selector('h1',    text: "Update your profile") }
      it { should have_selector('title', text: "Edit user") }
      it { should have_link('Change Profile Picture', href: 'http://gravatar.com/emails') }
    end

    describe "with invalid information" do
      before { click_button "Save changes" }

      it { should have_content('Whoops') }
    end

    describe "with valid information" do
      let(:new_name)  { "New Name" }
      let(:new_email) { "[email protected]" }
      before do
        fill_in "Name",             with: new_name
        fill_in "Password",         with: user.password
        fill_in "Password confirmation", with: user.password
        fill_in "Email",            with: new_email
        click_button "Save changes"
      end

      it { should have_selector('title', text: new_name) }
      it { should have_selector('div.alert.alert-success') }
      it { should have_link('Sign out', href: signout_path) }
      specify { user.reload.name.should  == new_name }
      specify { user.reload.email.should == new_email }
    end
  end
end

user_pages_spec.rb failures (output from terminal):

    Failures:

  1) User pages edit with invalid information
     Failure/Error: before { click_button "Save changes" }
     Capybara::ElementNotFound:
       no button with value or id or text 'Save changes' found
     # (eval):2:in `click_button'
     # ./spec/requests/user_pages_spec.rb:75:in `block (4 levels) in <top (required)>'

  2) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  3) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  4) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  5) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  6) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  7) User pages edit page
     Failure/Error: it { should have_selector('title', text: "Edit user") }
       expected css "title" with text "Edit user" to return something
     # ./spec/requests/user_pages_spec.rb:70:in `block (4 levels) in <top (required)>'

  8) User pages edit page
     Failure/Error: it { should have_link('Change Profile Picture', href: 'http://gravatar.com/emails') }
       expected link "Change Profile Picture" to return something
     # ./spec/requests/user_pages_spec.rb:71:in `block (4 levels) in <top (required)>'

  9) User pages edit page
     Failure/Error: it { should have_selector('h1',    text: "Update your profile") }
       expected css "h1" with text "Update your profile" to return something
     # ./spec/requests/user_pages_spec.rb:69:in `block (4 levels) in <top (required)>'

Finished in 1.06 seconds
20 examples, 9 failures

Failed examples:

rspec ./spec/requests/user_pages_spec.rb:77 # User pages edit with invalid information
rspec ./spec/requests/user_pages_spec.rb:91 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:93 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:92 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:95 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:94 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:70 # User pages edit page
rspec ./spec/requests/user_pages_spec.rb:71 # User pages edit page
rspec ./spec/requests/user_pages_spec.rb:69 # User pages edit page

application_pages_spec.rb:

require 'spec_helper'

describe "Authentication" do

  subject { page }

  describe "signin page" do
    before { visit signin_path }

    it { should have_selector('h1',    text: 'Sign in') }
    it { should have_selector('title', text: 'Sign in') }
  end

  describe "signin" do
    before { visit signin_path }

    describe "with invalid information" do
      before { click_button "Sign in" }

      it { should have_selector('title', text: 'Sign in') }
      it { should have_selector('div.alert.alert-error', text: 'Invalid') }

      describe "after visiting another page" do
        before { click_link "nsent"}
        it { should_not have_selector('div.alert.alert-error') }
      end
    end

    describe "with valid information" do
      let(:user) { FactoryGirl.create(:user) }
      before { sign_in user }

      it { should have_selector('title', text: user.name) }
      it { should have_link('Profile',  href: user_path(user)) }
      it { should have_link('Settings', href: edit_user_path(user)) }
      it { should have_link('Sign out', href: signout_path) }
      it { should_not have_link('Sign in', href: signin_path) }

      describe "followed by signout" do
        before { click_link "Sign out" }
        it { should have_link('Sign in', href: signin_path) }
        it { should_not have_link('Profile',  href: user_path(user)) }
        it { should_not have_link('Settings', href: edit_user_path(user)) }
        it { should_not have_link('Sign out', href: signout_path) }
      end
    end
  end

    describe "authorization" do

    describe "for non-signed-in users" do
      let(:user) { FactoryGirl.create(:user) }

      describe "in the Users controller" do

        describe "visiting the edit page" do
          before { visit edit_user_path(user) }
          it { should have_selector('title', text: 'Sign in') }
        end

        describe "submitting to the update action" do
          before { put user_path(user) }
          specify { response.should redirect_to(signin_path) }
        end
      end
    end
  end
end

applications_pages_spec.rb failures (output from terminal):

Failures:

  1) Authentication signin with valid information
     Failure/Error: it { should have_selector('title', text: user.name) }
       expected css "title" with text "Example User" to return something
     # ./spec/requests/authentication_pages_spec.rb:33:in `block (4 levels) in <top (required)>'

  2) Authentication signin with valid information
     Failure/Error: it { should have_link('Settings', href: edit_user_path(user)) }
       expected link "Settings" to return something
     # ./spec/requests/authentication_pages_spec.rb:35:in `block (4 levels) in <top (required)>'

  3) Authentication signin with valid information
     Failure/Error: it { should have_link('Profile',  href: user_path(user)) }
       expected link "Profile" to return something
     # ./spec/requests/authentication_pages_spec.rb:34:in `block (4 levels) in <top (required)>'

  4) Authentication signin with valid information
     Failure/Error: it { should_not have_link('Sign in', href: signin_path) }
       expected link "Sign in" not to return anything
     # ./spec/requests/authentication_pages_spec.rb:37:in `block (4 levels) in <top (required)>'

  5) Authentication signin with valid information
     Failure/Error: it { should have_link('Sign out', href: signout_path) }
       expected link "Sign out" to return something
     # ./spec/requests/authentication_pages_spec.rb:36:in `block (4 levels) in <top (required)>'

  6) Authentication signin with valid information followed by signout
     Failure/Error: before { click_link "Sign out" }
     Capybara::ElementNotFound:
       no link with title, id or text 'Sign out' found
     # (eval):2:in `click_link'
     # ./spec/requests/authentication_pages_spec.rb:40:in `block (5 levels) in <top (required)>'

  7) Authentication signin with valid information followed by signout
     Failure/Error: before { click_link "Sign out" }
     Capybara::ElementNotFound:
       no link with title, id or text 'Sign out' found
     # (eval):2:in `click_link'
     # ./spec/requests/authentication_pages_spec.rb:40:in `block (5 levels) in <top (required)>'

  8) Authentication signin with valid information followed by signout
     Failure/Error: before { click_link "Sign out" }
     Capybara::ElementNotFound:
       no link with title, id or text 'Sign out' found
     # (eval):2:in `click_link'
     # ./spec/requests/authentication_pages_spec.rb:40:in `block (5 levels) in <top (required)>'

  9) Authentication signin with valid information followed by signout
     Failure/Error: before { click_link "Sign out" }
     Capybara::ElementNotFound:
       no link with title, id or text 'Sign out' found
     # (eval):2:in `click_link'
     # ./spec/requests/authentication_pages_spec.rb:40:in `block (5 levels) in <top (required)>'

  10) User pages edit with invalid information
     Failure/Error: before { click_button "Save changes" }
     Capybara::ElementNotFound:
       no button with value or id or text 'Save changes' found
     # (eval):2:in `click_button'
     # ./spec/requests/user_pages_spec.rb:75:in `block (4 levels) in <top (required)>'

  11) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  12) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  13) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  14) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  15) User pages edit with valid information
     Failure/Error: fill_in "Password confirmation", with: user.password
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'Password confirmation' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:86:in `block (4 levels) in <top (required)>'

  16) User pages edit page
     Failure/Error: it { should have_selector('title', text: "Edit user") }
       expected css "title" with text "Edit user" to return something
     # ./spec/requests/user_pages_spec.rb:70:in `block (4 levels) in <top (required)>'

  17) User pages edit page
     Failure/Error: it { should have_link('Change Profile Picture', href: 'http://gravatar.com/emails') }
       expected link "Change Profile Picture" to return something
     # ./spec/requests/user_pages_spec.rb:71:in `block (4 levels) in <top (required)>'

  18) User pages edit page
     Failure/Error: it { should have_selector('h1',    text: "Update your profile") }
       expected css "h1" with text "Update your profile" to return something
     # ./spec/requests/user_pages_spec.rb:69:in `block (4 levels) in <top (required)>'

Finished in 1.53 seconds
36 examples, 18 failures

Failed examples:

rspec ./spec/requests/authentication_pages_spec.rb:33 # Authentication signin with valid information
rspec ./spec/requests/authentication_pages_spec.rb:35 # Authentication signin with valid information
rspec ./spec/requests/authentication_pages_spec.rb:34 # Authentication signin with valid information
rspec ./spec/requests/authentication_pages_spec.rb:37 # Authentication signin with valid information
rspec ./spec/requests/authentication_pages_spec.rb:36 # Authentication signin with valid information
rspec ./spec/requests/authentication_pages_spec.rb:42 # Authentication signin with valid information followed by signout
rspec ./spec/requests/authentication_pages_spec.rb:44 # Authentication signin with valid information followed by signout
rspec ./spec/requests/authentication_pages_spec.rb:41 # Authentication signin with valid information followed by signout
rspec ./spec/requests/authentication_pages_spec.rb:43 # Authentication signin with valid information followed by signout
rspec ./spec/requests/user_pages_spec.rb:77 # User pages edit with invalid information
rspec ./spec/requests/user_pages_spec.rb:91 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:93 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:92 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:95 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:94 # User pages edit with valid information
rspec ./spec/requests/user_pages_spec.rb:70 # User pages edit page
rspec ./spec/requests/user_pages_spec.rb:71 # User pages edit page
rspec ./spec/requests/user_pages_spec.rb:69 # User pages edit page

Upvotes: 0

Views: 547

Answers (1)

muttonlamb
muttonlamb

Reputation: 6501

When you define a block using describe, you need to put the page visit step in. describe kind of resets the context in which the subsequent steps are called.

 describe "with invalid information" do
      before do
      visit edit_user_path(user)
      click_button "Save changes"
      end

      it { should have_content('Whoops') }
 end

When you are defining sub step in RSpec, use it, instead.

Upvotes: 1

Related Questions