Capybara check if class changed after click - capybara

How can I check if the css class was added to the div after the button click?
I have a button with class "btn-success" and a modal form which by default doesn't have "show" class, but after clicking on the button the "show" class is added to the modal.
My test:
it 'shows up popup with form' do
modal_window = page.find('#data-modal')
expect(modal_window[:class]).not_to include('show')
page.find('.btn-success').click
expect(modal_window[:class]).to include('show')
end
My Gemfile:
group :development, :test do
gem 'rspec-rails', '~> 3.8'
gem 'factory_bot_rails'
gem 'rails-controller-testing'
gem 'webmock'
gem 'capybara'
gem 'selenium-webdriver'
gem 'rails-controller-testing'
end

To do exactly what you're asking the easiest solution would be something like
it 'shows up popup with form' do
expect(page).not_to have_css('#data-modal.show')
page.find('.btn-success').click
expect(page).to have_css('#data-modal.show')
end
However you really shouldn't be testing for the existence of specific classes in feature tests. Instead you should be testing that the modal actually appears. Since this is JS driven behavior it would mean making sure your test is running with a JS capable driver, making sure you haven't set Capybara.ignore_hidden_elements to false, and then doing
it 'shows up popup with form' do
# Should initially be hidden so won't be found
expect(page).not_to have_css('#data-modal')
page.find('.btn-success').click
# Should now be found
expect(page).to have_css('#data-modal')
end

Related

Clicking an element (not link or button) in Capybara

I'm doing an integration test wherein I need to click an html class element and it will go to controller action using Ajax.
Here's my html slim code:
table.table-default
thead
tr Title
tbody
tr.title
td Hello World
The JavaScript handles the click event on the tr
$(function() {
$('.title').click(function() {
$.ajax({
type: 'GET',
url: "/admin/dashboards/load_info/
});
})
})
I raised an error in a controller action to test if it will go to the controller
class Admin::DashboardsController < Admin::BaseController
def load_info
raise 'hello'.inspect
end
end
When I test on browser it raises hello
This is my current setup for testing:
gem "minitest-rails"
group :test do
gem 'shoulda', '~> 3.5'
gem 'shoulda-matchers', '~> 2.0'
gem 'rails-controller-testing'
gem 'minitest-spec-rails'
gem 'm', '~> 1.5.0'
gem 'minitest-rails-capybara'
gem 'database_cleaner'
gem 'phantomjs', :require => 'phantomjs/poltergeist'
gem 'poltergeist'
end
My test suit is this:
class DashboardFlowTest < Capybara::Rails::TestCase
before(:all) do
Capybara.current_driver = :poltergeist
end
test "Given I'm at dashboard page when I click the table row it should redirect me to load_info' do
visit 'admin/dashboards'
find('.title').click
assert_current_path admin_dashboards_load_info_path
end
end
The error I'm getting is:
Capybara::Poltergeist::StatusFailError: Request to 'http://127.0.0.1:50102/admin/dashboards/' failed to reach server, check DNS and/or server status - Timed out with no open resource requests
When I run the test it doesn't raises an error. I'm suspecting that the click function on the test only supports link or button or my test is not JavaScript enabled.

click_button on a button that was initially disabled, but enabled using javascript

I have a test that keeps failing because the button is initially disabled until I check a checkbox which then removes the disabled attribute from the button.
%button.btn.btn-success{id: 'registration_button', :type => "submit", :disabled=>'disabled'} Register
$('#tos_acceptance').click ->
tosChecked = $('#tos_acceptance').is(':checked');
if tosChecked
$('#registration_button').attr('disabled', false);
else
$('#registration_button').attr('disabled', 'disabled');
The problem I keep getting is that capybara cannot find the button.
Unable to find button "Register" (Capybara::ElementNotFound)
This is part of my test:
When(/^User goes to the registration page and enters (.*) and (.*) and (.*)$/) do |email, password, password_confirmation|
within all('.nav')[1] do
click_link('Register')
end
current_path.should == new_user_registration_path
page.should have_content('Please create your new account')
fill_in('user[email]', :with => email)
fill_in('user[password]', :with => password)
fill_in('user[password_confirmation]', :with => password_confirmation)
check 'tos_acceptance'
click_button('Register')
end
Here is my related Gemfile:
group :test do
gem 'rspec-rails'
gem 'cucumber-rails', :require => false
gem 'capybara'
gem 'database_cleaner'
gem 'email_spec'
gem 'spork'
gem 'launchy'
gem 'autotest'
gem 'turn', :require => false
gem 'minitest', '=4.7.5'
gem 'minitest-reporters', '>= 0.14.23'
How do I enable the button (with the javascript logic) so that this test passes? If I remove the disabled attribute, my tests pass fine, so I'm pretty confident that the issue is with enabling JS for the cucumber tests.
I'm not sure, but it seems, you didn't enable javascript for your Cucumber scenario.
You should add #javascript before your scenario to enable javascript for this scenario (selenium web driver will be used by default): https://github.com/jnicklas/capybara#using-capybara-with-cucumber
If you don't want to use selenium and want to enable headless javascript driver (like capybara-webkit or poltergeist), you'll need to add a gem to your Gemfile and change javascript driver as described here: https://github.com/jnicklas/capybara#drivers
I'm assuming it's not actually disabled-- so I don't think the issue is Capybara-- at least that's my guess-- You have to actually remove the disabled attribute. This doesn't address the test-- but in my experience the disabled attribute must actually be removed from the DOM to make the button disabled.
$('#tos_acceptance').click ->
tosChecked = $('#tos_acceptance').is(':checked');
if tosChecked
$('#registration_button').removeAttr('disabled');
else
$('#registration_button').attr('disabled', 'disabled');

rspec error during Rails Tutorial : undefined local variable or method `static_pages_index_path'

I'm followind the Rails Tutorial but have a problem in section 3.2.1, just before figure 3.6.
When running
$ bundle exec rspec spec/requests/static_pages_spec.rb
I get failure
Failures:
1) StaticPages GET /static_pages works! (now write some real specs)
Failure/Error: get static_pages_index_path
NameError:
undefined local variable or method `static_pages_index_path' for # <RSpec::Core::ExampleGroup::Nested_1::Nested_1:0x007fe7592b33b8>
# ./spec/requests/static_pages_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 0.00454 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/requests/static_pages_spec.rb:5 # StaticPages GET /static_pages works! (now write some real specs)
here are the files :
spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "Static pages" do
describe "Home page" do
it "should have the content 'Sample App'" do
visit '/static_pages/home'
page.should have_content('Sample App')
end
end
end
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
end
def help
end
end
app/views/static_pages/home.html.erb
<h1>Sample App</h1>
<p>
This is the home page for the
Ruby on Rails Tutorial
sample application.
</p>
config/routes.rb
SecondApp::Application.routes.draw do
get "static_pages/home"
get "static_pages/help"
end
Gemfile
source 'https://rubygems.org'
gem 'rails', '3.2.3'
group :development do
gem 'sqlite3', '1.3.5'
gem 'rspec-rails', '2.9.0'
gem 'guard-rspec', '0.5.5'
end
group :assets do
gem 'sass-rails', '3.2.4'
gem 'coffee-rails', '3.2.2'
gem 'uglifier', '1.2.3'
end
gem 'jquery-rails', '2.0.0'
group :test do
gem 'rspec-rails', '2.9.0'
gem 'capybara', '1.1.2'
gem 'growl', '1.0.3'
end
group :production do
gem 'pg', '0.12.2'
end
Any idea about what I did wrong ?
I was having this problem as well; the tutorial seems to have missed a step.
in static_pages_spec.rb, the line:
get static_pages_index_path
...should be changed to:
get static_pages_home_path
This is because there is no index method in static_pages_controller.rb. The index is instead called home.
I reviewed your code, however, and it seems your static_pages_spec.rb file does not match the tutorial, but I guess you're copying the code from another place? I do not see static_pages_index_path anywhere, except in your console error text, which seems odd.
This is my static_pages_spec.rb in its entirety (at this stage), which passes the test:
require 'spec_helper'
describe "StaticPages" do
describe "GET /static_pages" do
it "works! (now write some real specs)" do
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
get static_pages_home_path
response.status.should be(200)
end
end
end
After this, the tutorial (in Listing 3.12) superseeds this step, changing static_pages_spec.rb altogether, although forgetting to explicitly recommend the change. This makes my code above irrelevant, but hopefully it explains your error.
Have a closer look at your spec/requests/static_pages_spec.rb. Please make sure you've deleted get static_pages_index_path line.
You have to update your app/views/static_pages/help.html.erb page to contain 'Sample App' in the same way as you have done with home.html.erb.
I had the same problem and I figured it out in the following way. I am also a newbie (first Stack Overflow post... nervous), so I don't have the jargon down:
The reason I was getting this error is that I didn't create the staticpages controller described in Listing 3.4 of the tutorial (I think I deleted it messing around with the practice commands that follow Listing 3.4 teaching you how to ahem, delete things). The way to check if you don't have the staticpages controller is to go to:
sample_app/controllers/ and so I only had the application_controller.rb file there and no static_pages_controller.rb.
So you have to run the rails generate controller StaticPages home help --no-test-framework
command and get that controller in there.
You can double-check your work by going to localhost:3000/static_pages/home and seeing if there is actually something there.
Then edit, per the tutorial, the home.html.erb files and check back to static_pages/home to see if it actually says "Sample App".
If static_pages/home actually says "Sample App" and the test is still a failure when you run it, then only God can help you. Or maybe someone else on Stack Overflow. Good luck.
Have you deleted the public/index.html? This could be causing the problem.
When you add "config.include Capybara::DSL" to the bottom of the RSpec helper file, in the section right before this, you may have forgotten to save the page. That is done by pressing the Command + S keys together. Sometimes it is also a good idea to restart your Rails Server if something doesn't work the way you expect it to the first time.
The problem is that you are trying to run a generated spec that doesn't actually work yet. The tutorial tells you to replace the body of that spec with this:
it "should have the content 'Sample App'" do
visit '/static_pages/home'
page.should have_content('Sample App')
end
Note that it says "visit", not "get", and so on...
This happened because the spec generator (rails generate integration_test static_pages) assumes that there is a valid RESTful resource with lots of named routes, including _index_path, but that's simply not the case for this controller in this tutorial.
I was facing a similar problem. When you edit the static_pages_spec.rb, it looks like you typed this command (in listings 3.9)
<editor name> static_pages_spec.rb
whereas you had to type
<editor name> spec/requests/static_pages_spec.rb
This will surely solve your problem.

Factory already registered: user (FactoryGirl::DuplicateDefinitionError)

Description of problem:
- I've setup factory_girl_rails however whenever I try and load a factory it's trying to load it multiple times.
Environment:
- rails (3.2.1)
- factory_girl (2.5.2)
- factory_girl_rails (1.6.0)
- ruby-1.9.3-p0 [ x86_64 ]
> rake spec --trace
** Execute environment
-- Creating User Factory
-- Creating User Factory
rake aborted!
Factory already registered: user
The only other thing I've changed is:
/config/initializers/generator.rb
Rails.application.config.generators do |g|
g.test_framework = :rspec
g.fixture_replacement :factory_girl
end
GEMFILE
gem 'rails', '3.2.1'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
gem 'devise'
gem 'haml-rails'
group :development do
gem 'hpricot'
gem 'ruby_parser'
gem "rspec-rails"
end
group :test do
gem "rspec"
gem 'factory_girl_rails'
end
gem 'refinerycms-core', :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-dashboard', :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-images', :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-pages', :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-resources', :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-settings', :git => 'git://github.com/resolve/refinerycms.git'
group :development, :test do
gem 'refinerycms-testing', :git => 'git://github.com/resolve/refinerycms.git'
end
gem 'refinerycms-inventories', :path => 'vendor/engines'
FactoryGirl.define do
factory :role do
title "MyString"
end
end
This seems to be a compatibility/environment issue that I can't seem to figure out. Any suggestions?
EDIT: here's my spec/spec_helper.rb:
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
#require 'factory_girl_rails'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
### Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
#config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
end
The gem factory_girl_rails should be required in the spec_helper.rb rather than the gemfile - it is possible that you are requiring FactoryGirl twice which is why you are getting the duplicate.
Try this in your gem file:
group :test do
gem "rspec"
gem 'factory_girl_rails', :require => false
end
Then make sure that factory girl is required in the spec_helper with:
require 'factory_girl_rails'
By the way - you don't need both rspec and rpsec-rails in your gemfile. You can replace both with the following:
group :development, :test do
gem 'rspec-rails'
end
You need rspec in both groups so that the rake tasks will work in development and the core testing will work in test.
I had the same problem recently. In my case one of the files in /factories had a _spec.rb ending (result of creative cp use). It was loading twice, first by rspec and then as a factory.
Is there any chance you pasted this whole snippet for the support file from the config docs?
# RSpec
# spec/support/factory_girl.rb
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
# RSpec without Rails
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.before(:suite) do
FactoryGirl.find_definitions
end
end
If you read the comments you'll see you only want one block or the other. I made this mistake and got the error stated in the question.
I had this problem too. In my case there were two files with the same code, like this:
FactoryGirl.define do
factory :user do
end
end
One file was named "Useres.rb" and the other "User.rb" so I just deleted "Useres.rb" and fixed the error.
Call FactoryGirl.define(:user) or FactoryGirl.find_definitions twice you also have this problem.
Try removing the second call or:
FactoryGirl.factories.clear
FactoryGirl.find_definitions
Another possible reason is spare call of FactoryGirl.find_definitions.
Try to remove find_definitions if found.
Make sure your individual factory files are not ending with _spec.
https://github.com/thoughtbot/factory_girl/issues/638
Loading factory girl into a development console will do this too:
require 'factory_girl_rails'; reload!; FactoryGirl.factories.clear; FactoryGirl.find_definitions
will raise a FactoryGirl::DuplicateDefinitionError on a sequence under Factory Girl v4.4.0.
It seems the sequences get handled differently within FG and simply wrapping all sequences in a rescue block will solve the issue.
For example:
begin
sequence :a_sequence do |n|
n
end
sequence :another_sequence do |n|
n*2
end
rescue FactoryGirl::DuplicateDefinitionError => e
warn "#{e.message}"
end
I have the same the problem. What I do is move the spec/factories.rb to spec/factories/role.rb
I renamed spec/factories as spec/setup_data and the problem gone.
Try renaming the spec/factories to anything that suites you, should work.
I had the same problem- make sure you aren't loading FactoryGirl a second time in your spec/support/env.rb file.
I had same problem. This happens becouse of you using gem 'refinerycms-testing'? wich requires factory-girl, so you should commit this gem, or commit gem 'factory_girl_rails', don't use all of this gems.
#gem 'refinerycms-testing', '~> 2.0.9', :group => :test
gem 'factory_girl_rails', :group => :test
or
#gem 'factory_girl_rails', :group => :test
gem 'refinerycms-testing', '~> 2.0.9', :group => :test
Please try following these steps
1) I looked for all occurrences of "factory_girl" from my RAILS_ROOT:
find . -name "*.rb" | xargs grep "factory_girl"
2) Because this was a full engine plugin "app" that I created via "rails plugin new --mountable", I had a file under RAILS_ROOT//lib/ called "engine.rb". It had:
config.generators do |g|
g.test_framework :rspec, :fixture => false
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
g.assets false
g.helper false
end
3) I also had the following in my spec_helper.rb file:
Dir["#{File.dirname(FILE)}/factories/*/.rb"].each { |f| require f }
4) the g.fixture_replacement line in engine.rb and the Dir line in spec_helper.rb were initializing the factories twice. I commented out the one from spec_helper.rb and that fixed the problem.
Alternatively, you can leave in spec_helper.rb and comment out in engine.rb.
Both fixed the problem in my case.
I had exactly the same problem.
It occurs when you use the scaffold generator.
It automatically creates a factory in test/factories/
So generally just deleting this file solve your issue
I had the same problem, it turned out there was a default users.rb created inside the test/factories which was created by the rails g command. This file was causing the conflict. The error went away when I deleted the file.
try to run
rake db:test:prepare
I just found I was getting this answer when accidentally calling cucumber features. When I just called cucumber, the problem went away.
I also ran with the same issue and commenting out a single line in spec_helper.rb file solved my problem.
Try commenting out this line from spec_helper.rb file and you should be good.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
I defined the same name factory at factories.rb, and I just found that someone else define the same factory below the directory of factories. So actually I can just use it without define another one.
Replace the refinerycms-testing gem with rspec-rails and factory_girl_rails
Check to see if you added factories through the model generator. My generator made a model and I added one to my main factory.rb file. Deleting the automatically generated ones worked for me.
In my case,
First my co-worker has setup the project with factory_girl gem with
Dir[Rails.root.join('spec/factories/**/*.rb')].each { |f| require f }
in rails_helper.
After some days, I replaced the gem with factory_girl_rails. Since this new gem also does that internally so factories were registered twice. This was causing the error.
Removed that line from rails_helper and it worked.
I solved this because I was trying to create two factories. My feature spec included the line:
let!(:user) { create(:user) }
And then I used a sign_up(user) helper method:
def sign_up(user)
visit '/users/sign_up'
fill_in 'Email', with: user.email
fill_in 'Password', with: user.password
fill_in 'Password confirmation', with: user.password_confirmation
click_button 'Sign up'
end
Back to my feature spec, I called:
context 'logging out' do
before do
sign_up(user)
end
...
thus effectively trying to sign up a User that was already being created by the factory.
I altered the sign_up(user) to sign_in(user), and the helper to:
def sign_in(user)
visit '/users/sign_in'
fill_in 'Email', with: user.email
fill_in 'Password', with: user.password
click_button 'Log in'
end
now the user argument creates the User in the db due to the let! block and the sign_up(user) logs them in.
Hope this helps someone!
oh! and I also had to comment out:
Dir[Rails.root.join('spec/factories/**/*.rb')].each { |f| require f }
as a lot of the other answers suggest.
The strangest thing, I got this error with the following syntax error in the code:
before_validation :generate_reference, :on: :create
:on: was causing this error. How or why will remain a mystery.
I resolved it by removing spec/factories/xxx.rb from command line:
rspec spec/factories/xxx.rb spec/model/xxx.rb # before
rspec spec/model/xxx.rb # after
for me, this issue was coming because was using both gems
gem 'factory_bot_rails'
gem 'factory_girl_rails'
to solve I removed gem 'factory_bot_rails' from gem file.
and also added require 'factory_girl' to spec/factories/track.rb file.
if Rails.env.test?
require 'factory_girl'
FactoryGirl.define do
factory :track do
id 1
name "nurburgring"
surface_type "snow"
time_zone "CET"
end
end
I hope this will help.
I solved this issue by just adding required: false to gem 'factory_bot_rails' like so:
gem 'factory_bot_rails', require: false
Check that you don't have multiple factories with same name this is one of reasons which causes error
Attempting to define multiple factories with the same name will raise an error.

assigns_to doesn't work for Rails 3 Shoulda on Ubuntu

I'm using Rails3 with rspec and shoulda. I have the below spec
describe PagesController, "on GET to show while logged off" do
before(:each) do
#site = Factory.create(:site)
#site.domains << Factory.create(:domain)
#site.save!
#site.pages << Factory.create(:page)
#site.menus << Factory.create(:menu, {:site=>#site, :is_visible=>true})
#site.menus << Factory.create(:menu, {:site=>#site, :is_visible=>true})
#site.menus << Factory.create(:menu, {:is_visible=>false, :site=>#site})
get :show
end
it { should render_template(:show) }
it { should render_template('layouts/2col') }
it { should assign_to(:site) }
it { should assign_to(:site).with(#site) }
it { should assign_to(:site).with(#site) }
it { should assign_to(:page).with(#site.pages[0])}
it "show visible menu_items only" do
assert assigns[:menu_items].length == 2
end
end
Here's my Gem File
group :development, :test do
gem 'autotest'
gem 'factory_girl'
gem 'rspec', '>=2.0.0.beta.19'
gem 'rspec-rails', '>=2.0.0.beta.17'
gem 'shoulda'
end
and here's my spec_helper
require 'rspec/rails'
require 'shoulda'
require 'shoulda/integrations/rspec2'
require 'authlogic/test_case'
require 'factory_girl
Ok so far everything pretty close matches what I've seen before, however whenever I run my tests I get the errors like below
1) PagesController on GET to show while logged off
Failure/Error: it { should assign_to(:site) }
Expected action to assign a value for #site
# ./spec/controllers/pages_controller_spec.rb:19
No my first thought was that the code was broken, however the application runs correcty. Also if I test that the values are assigned by using the assigns[:site] then the test passes.
Has anyone any idea what I need to change in order to make these tests start working again.
Thanks In Advance
Andy
You need to call subject { controller } before your it statements. This actually confused me so badly for a while that I wrote my first ever blog post about it.
If you are using Ruby 1.9.2 the assign_to matcher with the shoulda-matchers gem version lower than 1.0.0beta2 will still not work, even if you include the subject { controller } (which, I believe, is not really needed).
It's caused by a change in Ruby 1.9.2. Here is the bugreport for shoulda. The fix is already included and released in shoulda-matchers version 1.0.0beta2.
So just have this in your Gemfile:
group :development, :test do
gem 'shoulda-matchers'
...
and update to the latest version (1.0.0.beta2 atm):
bundle update shoulda-matchers

Resources