Reputation: 39
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>
Upvotes: 1
Views: 1708
Reputation: 39
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>
Upvotes: 0
Reputation: 656
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.
Upvotes: 2