1

Im writing a simple login test using RSpec 3 and Capybara 2.2.0 and cannot for the life of me figure out why this test keeps failing.

I've managed to identify that the test isn't actually clicking on the button, but it thinks it is. Another strange thing is that even though this isn't a javascript form, running the test with capybara set to js: true, will render a successful test. What am I missing?

GemFile

source 'https://rubygems.org'
ruby '2.0.0'

gem 'rails', '4.0.1'
gem 'bootstrap-sass', '~> 3.0.2.0'
gem 'bcrypt-ruby', '3.1.2'
gem 'faker', '1.1.2'
gem 'will_paginate', '3.0.4'
gem 'will_paginate-bootstrap', '1.0.0'
gem 'holder_rails', '2.2.0'

group :development, :test do
  gem 'sqlite3', '1.3.8'
  gem 'rspec-rails', '~> 3.0.0.beta'
end

group :test do
  gem 'selenium-webdriver', '2.35.1'
  gem 'capybara'
  gem 'factory_girl_rails', '4.2.0'
  gem 'cucumber-rails', '1.4.0', :require => false
  gem 'database_cleaner', github: 'bmabey/database_cleaner'
  gem 'launchy'
  gem 'growl', '1.0.3'
end

gem 'sass-rails', '>= 3.2'
gem 'uglifier', '2.1.1'
gem 'coffee-rails', '4.0.1'
gem 'jquery-rails', '3.0.4'
gem 'turbolinks', '1.1.1'
gem 'jbuilder', '1.0.2'

group :doc do
  gem 'sdoc', '0.3.20', require: false
end

group :production do
  gem 'pg', '0.15.1'
  gem 'rails_12factor', '0.0.2'
end

*Authentication_pages_spec.rb*

require 'spec_helper'

describe "Authentication" do

  subject { page }

  describe "signin page" do
    before { visit signin_path }

    it { should have_content('Sign in') }
    it { should have_title('Sign In') }
  end

  describe "signin", :type => :feature do

    before :each do
      visit signin_path
    end

    describe "with invalid information" do
      specify do
        click_button 'Sign in'
        should have_selector('div.alert.alert-danger',  text: 'Invalid')
        should have_title('Sign In')
      end
    end

    describe "with valid information" do
      let(:user) { FactoryGirl.build(:user) }
        before do    
            fill_in "Username",     with: user.username
        fill_in "Password",     with: user.password
      end

      specify do
        click_button 'Sign in'
        save_and_open_page
        # current_path.should == root_path
        should_not have_title("Sign In")
        should have_content("dreams")
      end
    end
  end
end

Sessions.rb

class SessionsController < ApplicationController
    def new
    end

    def destroy
    end

    def create
        user = User.find_by(username: params[:session][:username].downcase)
        if user && user.authenticate(params[:session][:password])
            sign_in user
            redirect_to root_path
        else
            flash.now[:danger] = 'Invalid email/password combination'
            render 'new'
        end
    end
end

Result:

Failures:

  1) Authentication signin with valid information should not have title "Sign In"
     Failure/Error: should_not have_title("Sign In")
       expected there not to be title "Sign In" in "Adventure|Byte Games - Sign In"
     # ./spec/features/authentication_pages_spec.rb:39:in `block (4 levels) in <top (required)>'

  2) Authentication signin with invalid information should have css "div.alert.alert-danger" with text "Invalid"
     Failure/Error: should have_selector('div.alert.alert-danger',  text: 'Invalid')
     Capybara::ExpectationNotMet:
       expected to find css "div.alert.alert-danger" with text "Invalid" but there were no matches
     # ./spec/features/authentication_pages_spec.rb:23:in `block (4 levels) in <top (required)>'

Added Sign in View (new.html.erb)

<% provide(:title, "Sign In") %>
<h1>Sign in</h1>

<div class = "container">
<%= form_for(:session, url: sessions_path) do |f| %>
    <form role = "form">
        <div class="col-md-6 col-md-offset-3">

            <div class="form-group">
                <%= f.label :username %>
                <%= f.text_field :username, class: "form-control" %>
            </div>

            <div class="form-group">
                <%= f.label :password %>
                <%= f.password_field :password, class: "form-control"%>
            </div>

            <div class="form-group">
                <%= f.submit "Sign in", class: "btn btn-lg btn-primary" %>
            </div>

         </div>
    </form>
<% end %>
</div>

So it turns out that I was over doing the formatting on the form, the following view seems to work:

<% provide(:title, "Sign In") %>
<h1>Sign in</h1>

<div class = "container">
    <div class="col-md-6 col-md-offset-3">
        <%= form_for(:session, url: sessions_path) do |f| %>

            <%= f.label :username %>
            <%= f.text_field :username, class: "form-control" %>

            <%= f.label :password %>
            <%= f.password_field :password, class: "form-control"%>

            <%= f.submit "Sign in", class: "btn btn-lg btn-primary" %>

        <% end %>
    </div>
</div>
3
  • Can you share the code for your sign in view? Commented Dec 4, 2013 at 23:56
  • OK, looks like you may be having your flash messages rendered using javascript, probably in the application.html.erb file. Commented Dec 5, 2013 at 2:05
  • try click_link("Sign in") Commented Dec 5, 2013 at 16:04

2 Answers 2

2

Personally I would not use the click_button method. It can be quite flaky.

I like to use this sort of thing

page.find('the.css.for.the.button').trigger('click') 

The reason for using trigger('click') is that it is much more reliable with javascript.

I hope that helps.

Sign up to request clarification or add additional context in comments.

Comments

0

So it turns out that I was over doing the formatting on the form, the following view seems to work:

<% provide(:title, "Sign In") %>
<h1>Sign in</h1>

<div class = "container">
    <div class="col-md-6 col-md-offset-3">
        <%= form_for(:session, url: sessions_path) do |f| %>

            <%= f.label :username %>
            <%= f.text_field :username, class: "form-control" %>

            <%= f.label :password %>
            <%= f.password_field :password, class: "form-control"%>

            <%= f.submit "Sign in", class: "btn btn-lg btn-primary" %>

        <% end %>
    </div>
</div>

1 Comment

I do not see how removing some classes helped capybara find your button. Care to explain?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.