Im trying to test a user clicking on a button which makes an ajax call. When i click it manuallly in my browser it behaves as expected i.e. default behaviour of the button is ignored and instead it gets the results via ajax which are then added to the page.
But when i run my tests using capybara, after clicking on the button it redirects to the buttons action. It seems selenium isnt kicking in. I cant figure out why.
Is it my config? Since it works in development mode Im assuming this isnt due to my jquery code so for brevity not displaying that.
Gemfile
source 'http://rubygems.org'
gem 'rails', '3.1.0.rc4'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3'
gem 'omniauth', '~>0.2.0'
gem 'pusher'
gem 'youtube_it'
gem 'simple_form'
# Asset template engines
gem 'sass-rails', "~> 3.1.0.rc"
gem 'coffee-script'
gem 'uglifier'
gem 'jquery-rails'
# Use unicorn as the web server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
group :test do
gem "shoulda"
gem "factory_girl_rails"
# Pretty printed test output
gem 'turn', :require => false
gem 'mocha'
end
group :development do
gem 'rails3-generators'
gem "autotest"
end
group :development, :test do
gem "capybara", :git => 'git://github.com/jnicklas/capybara.git'
gem "launchy"
gem "haml-rails"
gem "database_cleaner"
end
or my test_helper
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'shoulda/rails'
require "capybara/rails"
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
fixtures :all
OmniAuth.config.test_mode = true
# Add more helper methods to be used by all tests here...
def login_in(user)
#request.session[:user_id] = user.id
end
def should_redirect_unauthorized
assert_redirected_to root_path
assert_match /you need to login/i, flash[:alert]
end
end
module ActionController
class IntegrationTest
include Capybara::DSL
self.use_transactional_fixtures = false
setup do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.start #workaround for capybara / selenium. See capybara docs
end
teardown do
DatabaseCleaner.clean #workaround for capybara / selenium. See capybara docs
end
#signup using twitter, facebook for authentication
def signup_using(provider)
OmniAuth.config.add_mock(provider.to_sym, {'uid' => "123456"})
visit '/'
page.click_link("#{provider}_auth")
assert_match /\/users\/\d+\/edit/, current_path
assert page.find("#flash").has_content?("Welcome to")
end
#login into existing account using twitter, facebook
def login_using(service)
OmniAuth.config.add_mock(service.provider.to_sym, {'uid' => service.uid})
visit '/'
page.click_link("#{service.provider}_auth")
assert page.find("#flash").has_content?("Welcome back")
assert_equal rooms_path, current_path
end
def login_and_visit_room(service, room)
login_using(service)
visit_room(room)
end
def visit_room(room)
visit room_path(room)
assert_equal room_path(#room.id), current_path
end
end
end
or the setup blocks in my integration test
require 'test_helper'
class PlaylistStoriesTestTest < ActionDispatch::IntegrationTest
fixtures :all
setup do
Capybara.current_driver = :selenium
#user = Factory(:user)
#service = #user.services.create(:provider => "twitter", :uid => "123456")
#room = Factory(:room)
end
....
teardown do
Capybara.use_default_driver
DatabaseCleaner.clean #workaround for capybara / selenium. See capybara docs
end
end
With Capybara, you should not get confused with the difference between a link (even if it looks like a button) and a button (like "submit"). You did not provide the view file contents, but I guess, you are using a button, not a link.
With capybara, you have to differentiate
visit '/'
click_button 'Login'
or
visit '/'
click_link 'Home'
See also the Capybara-Documentation at GitHub
Related
Update: After burning too many hours, decided to opt for the easy way out and use rack-test. This works straight out of the box and at least verifies that the content-type is a pdf.
scenario 'document can be downloaded' do
visit my_documents_path
click_on 'Download'
expect(page.response_headers['Content-Type']).to eq "application/pdf"
end
I am trying to write a feature spec to test the contents of my downloaded pdf, and I have followed the directions found here: https://stackoverflow.com/a/29544674/2464546
I am running Ruby 2.3, Rails 4.2.5.2, RSpec 3.4, Capybara 2.7.
In the code from the SO link above, there's a line that supposedly suppresses the Firefox Save popup, with this, adjusted to pdf from csv:
# Suppress "open with" dialog
profile['browser.helperApps.neverAsk.saveToDisk'] = 'application/pdf'
This doesn't seem to work because the dialog box still pops up, and then my test errors out.
My feature spec:
scenario 'document can be downloaded', js: true do
visit my_documents_path
click_on 'Download'
expect(DownloadHelpers::download_content).to have_content('Thingy')
end
Every time I run this spec, it errors out saying execution expired with a different error each time. For example the latest one had the following:
1) My documents home page document can be downloaded
Failure/Error: Dir[PATH.join("*")]
Timeout::Error:
execution expired
# ./spec/features/shared/download_helper.rb:8:in `downloads'
# ./spec/features/shared/download_helper.rb:31:in `downloading?'
# ./spec/features/shared/download_helper.rb:27:in `downloaded?'
# ./spec/features/shared/download_helper.rb:22:in `block in wait_for_download'
# ./spec/features/shared/download_helper.rb:21:in `wait_for_download'
# ./spec/features/shared/download_helper.rb:16:in `download_content'
# ./spec/features/my_documents/index_spec.rb:42:in `block (2 levels) in <top (required)>'
In the DownloadHelpers module, I've changed the sleep from 0.1 to 1 to 3, and occasionally I'll get the following error, with the sleep count changing w/ whatever I've set it to:
Failure/Error: sleep 3 until downloaded?
Timeout::Error:
execution expired
# ./spec/features/shared/download_helper.rb:22:in `sleep'
# ./spec/features/shared/download_helper.rb:22:in `block in wait_for_download'
# ./spec/features/shared/download_helper.rb:21:in `wait_for_download'
# ./spec/features/shared/download_helper.rb:16:in `download_content'
# ./spec/features/my_documents/index_spec.rb:42:in `block (2 levels) in <top (required)>'
I have also changed the TIMEOUT count with no change in failure result from the above. Ultimately, the dialog box still pops up and does not go away/doesn't look like it downloads the file.
My controller behind the Download button:
def download
pdf = #document.pdf_file_name
send_file pdf
end
The created document is not large, as all it has is a name and a few lines, so I don't suspect it'd need more than a few seconds to download and read the file.
Why is the execution expiring? How do I get Capybara/Feature spec to download the file so my expectation passes?
The view document.haml using angular tho I don't think that matters.
%li.col-xs-6
%li.col-xs-6= link_to 'Download', download_document_path(id: document.id), "ng-click" => "logAnalytics('#{document.document_template_id}', 'download')"
Also, my feature spec has require 'rails_helper' at the top, and my rails_helper has the code from the SO post (in full, w/ relevant bits):
require 'features/shared/download_helper'
RSpec.configure do |config|
Capybara.register_driver :selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = DownloadHelpers::PATH.to_s
profile['browser.download.folderList'] = 2
profile['browser.helperApps.neverAsk.saveToDisk'] = 'application/pdf'
Capybara::Selenium::Driver.new(app, browser: :firefox, profile: profile)
end
config.before( :each ) do
DownloadHelpers::clear_downloads
end
end
I think any of the following will work:
page.driver.browser.switch_to.alert.accept
# or
page.driver.browser.switch_to.alert.dismiss
# or
page.driver.browser.switch_to.alert.text
Check the mime type your pdf download is returning, odds are it's not actually 'application/pdf' and is most likely being returned as 'application/octet-stream'. You should fix the return type to be correct, but in the short term you can try changing to profile['browser.helperApps.neverAsk.saveToDisk'] = 'application/pdf,application/octet-stream'
I got the 'execution expired' error too. I followed all the steps above, but the error remained. It turned out to be the download directory was missing in the filesystem (DownloadHelpers::PATH).
Creating that one made the message disappear and the test pass.
I was experiencing this same error. The solution for me was to increase the timeout. So where ever you are doing the sleeping until timeout, increase the timeout. Of course it depends on your business logic but 5 seconds works for me consistently whereas 2 seconds failed consistently.
I have tried to implement something similar and spend lots of hours. Finally I have some solution, maybe it fit for you as well.
Gemfile:
#source 'https://rubygems.org'
gem 'rails', '4.2.2'
gem 'bcrypt', '3.1.7'
gem 'bootstrap-sass', '3.2.0.0'
gem 'faker', '1.4.2'
gem 'carrierwave', '0.10.0'
gem 'mini_magick', '3.8.0'
gem 'fog', '1.36.0'
gem 'will_paginate', '3.0.7'
gem 'bootstrap-will_paginate', '0.0.10'
gem 'sass-rails', '5.0.2'
gem 'uglifier', '2.5.3'
gem 'coffee-rails', '4.1.0'
gem 'jquery-rails', '4.0.3'
gem 'turbolinks', '2.3.0'
gem 'jbuilder', '2.2.3'
gem 'sdoc', '0.4.0', group: :doc
gem 'rename'
gem 'sprockets', '3.6.3'
gem 'responders', '~> 2.0'
gem 'inherited_resources'
group :development, :test do
gem 'sqlite3', '1.3.9'
gem 'byebug', '3.4.0'
gem 'web-console', '2.0.0.beta3'
gem 'spring', '1.1.3'
end
group :test do
gem 'minitest-reporters', '1.0.5'
gem 'mini_backtrace', '0.1.3'
gem 'guard-minitest', '2.3.1'
gem 'capybara', '2.8.1'
gem 'rspec', '3.5.0'
gem 'rspec-rails', '~> 3.4'
gem 'cucumber-rails', :require => false
gem 'shoulda-matchers', '~> 3.0', require: false
gem 'database_cleaner'
gem 'factory_girl_rails', '~> 4.5.0'
end
spec/rails_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'shoulda/matchers'
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
config.use_transactional_fixtures = false
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
end
spec/spec_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rspec'
require 'capybara/rails'
require 'download_helper'
Capybara.register_driver :selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = DownloadHelpers::PATH.to_s
profile['browser.download.folderList'] = 2
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
config.include Capybara::DSL
=begin
config.filter_run_when_matching :focus
config.example_status_persistence_file_path = "spec/examples.txt"
config.disable_monkey_patching!
if config.files_to_run.one?
config.default_formatter = 'doc'
end
config.profile_examples = 10
config.order = :random
Kernel.srand config.seed
=end
end
test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'capybara/rails'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
include ApplicationHelper
def is_logged_in?
!session[:user_id].nil?
end
# Logs in a test user.
def log_in_as(user, options = {})
password = options[:password] || 'password'
remember_me = options[:remember_me] || '1'
if integration_test?
post login_path, session: { email:user.email, password: password, remember_me: remember_me }
else
session[:user_id] = user.id
end
end
private
# Returns true inside an integration test.
def integration_test?
defined?(post_via_redirect)
end
end
class ActionDispatch::IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara::DSL
# Reset sessions and driver between tests
# Use super wherever this method is redefined in your individual test classes
def teardown
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
spec/download_helper.rb
module DownloadHelpers
TIMEOUT = 1
PATH = Rails.root.join("tmp/downloads")
extend self
def downloads
Dir[PATH.join("*")]
end
def download
downloads.first
end
def download_content
wait_for_download
File.read(download)
end
def wait_for_download
Timeout.timeout(TIMEOUT) do
sleep 0.1 until downloaded?
end
end
def downloaded?
!downloading? && downloads.any?
end
def downloading?
downloads.grep(/\.part$/).any?
end
def clear_downloads
FileUtils.rm_f(downloads)
end
end
spec/mpodels/spec.rb
describe 'Download file' do
specify do
visit '/createfile'
click_on 'create file'
page.response_headers['Content-Type'].should == "text/csv"
header = page.response_headers['Content-Disposition']
header.should match /^attachment/
header.should match /filename=\"temp.csv\"$/
end
end
I want Capybara to fill out a login form, click on 'Login', and redirect me to the root path like this: (example). This app is your classic blog app with Devise for authentication - I can't think of anything else that would affect the test.
I only get a 'failed assertion' test error so I checked the spelling of my button, experimented with Warden, and still couldn't figure it out. For a solution, I'd like to be able to exactly mimic how a user would navigate through a page.
Integration test:
require 'test_helper'
require 'database_cleaner'
class PostsTest < ActionDispatch::IntegrationTest
# for setup and tear down each time we run tests
self.use_transactional_fixtures = false
setup do
DatabaseCleaner.start
end
teardown do
DatabaseCleaner.clean
end
def setup
#post = posts(:valid_post)
#admin = users(:james)
#regular = users(:steve)
end
test 'display comments' do
assert #post.comments.first.body == 'hello'
end
test 'visit contact page' do
visit '/contact'
assert page.has_text?('jamesyoun710')
end
test 'login as admin' do
visit new_user_session_path
assert page.has_field?('Email', type: 'email')
fill_in('Email', with: 'jamesyoun710#gmail.com')
fill_in('Password', with: 'gooneen44')
click_on('Log in') # this doesn't redirect me into the page
# login_as(#admin) # I need to do this to execute the line above
visit root_path
assert page.has_link?('Logout')
assert page.has_link?('New Post')
end
end
test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
require 'minitest/rails'
require 'capybara/rails'
require 'minitest/rails/capybara'
Minitest::Reporters.use!
# for creating sessions in tests
include Warden::Test::Helpers
Warden.test_mode!
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
end
class ActionController::TestCase
include Devise::TestHelpers
end
class ActionDispatch::IntegrationTest
include Capybara::DSL
end
gemfile:
group :development, :test do
gem 'database_cleaner'
gem 'hirb'
gem 'byebug'
gem 'annotate'
gem 'web-console', '~> 2.0'
gem 'spring'
gem 'better_errors', '~> 2.1.1'
gem 'binding_of_caller', '~> 0.7.2'
end
group :test do
gem 'minitest-reporters', '1.0.5'
gem 'minitest-rails-capybara'
# gem 'mini_backtrace'
gem 'guard-minitest', '2.3.1'
end
Found the solution - I should have been using login info from my fixtures (test db) but instead I was using login info from my development db.
I have this project from my university and I'm trying to understand the code before making any changes.
The code has tests, which make this easier. But I'm having problems in run these tests. The person who wrote the code said it was working perfectly, so I think it's some kind of incompatibility with gems or something like that. The project has more than one year without updates, that's why the gems may be a little old rs. But since I haven't change any gems, this should work. Lets go to the problem:
Here is my test:
it 'edit user information' do
user = FactoryGirl.create :user
login(user.email, '123456')
click_link user.email
fill_in 'E-mail', :with => 'another_email#email.com'
click_button 'Save'
page.should have_content 'Update successfull.'
end
and here is my login function, that is located at spec_helper
def login(email, password)
visit '/admin'
fill_in('user_email', :with => email)
fill_in('user_password', :with => password)
click_button "Entrar"
end
And that is the error:
1) login and register edit user information
Failure/Error: login(user.email, '123456')
ArgumentError:
wrong number of arguments (1 for 0)
# ./spec/acceptance/login_spec.rb:18:in `block (2 levels) in <top (required)>'
where line 18 is: login(user.email, '123456')
After a while I realized that:
If I put a string as a parameter to login function, like login('login#email.com', '123456') instead of login(user.email, '123456'). It runs, but I get another error because login#email doesn't exist on my database then I can't log in.
But, if this string is exactly the same as FactoryGirl generates, I get the error of arguments again.
I've already tried update almost all gemfiles, but it was not successful. So, I'm still working with the old gems until I solve this problem. Here is my gemfile:
source 'http://rubygems.org'
gem 'rails', '3.2.11'
gem 'rake', '10.1.0'
gem 'mysql2', '0.3.11'
gem 'devise', '2.2.3'
gem 'fastercsv', '1.5.5'
gem 'rails_admin', '0.4.3'
gem 'cancan', '1.6.9'
gem 'simple_form', '2.0.4'
gem 'slim', '1.3.6'
gem 'jquery-rails', '2.2.0'
gem 'sprockets', '~> 2.2.1'
gem 'ckeditor', '4.0.2'
gem 'paperclip', '3.4.0'
gem 'twitter-bootstrap-rails', '2.2.0'
gem 'bootstrap-wysihtml5-rails', '0.3.1.17'
gem 'less-rails', '2.2.6'
gem 'therubyracer', '~> 0.12.0'
gem 'kaminari', '0.14.1'
group :assets do
gem 'uglifier', '1.3.0'
gem 'yui-compressor', '0.9.6'
end
group :test do
gem 'rspec-rails', '2.11.0'
gem 'capybara', '~> 2.0.2'
gem 'launchy', '2.1.2'
gem 'factory_girl_rails', '1.6.0'
gem 'valid_attribute', '1.3.1'
gem 'spork', '0.9.2'
gem 'capybara-webkit', '1.1.1'
gem 'database_cleaner', '0.8.0'
gem 'shoulda-matchers'
gem 'autotest'
end
group :developmet do
gem 'rails3-generators'
gem 'slim-rails', '1.1.0'
gem 'thin', '1.5.0'
end
Can anyone help me with this issue?
Edit:
Factory user:
# -*- encoding : utf-8 -*-
FactoryGirl.define do
factory :user do
sequence(:email) { |n| "user#{n}#email.com" }
password "123456"
password_confirmation "123456"
admin true
end
end
spec_helper.rb:
# -*- encoding : utf-8 -*-
require 'rubygems'
require 'spork'
Spork.prefork do
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rspec'
require 'valid_attribute'
require 'cancan/matchers'
require 'paperclip/matchers'
IMAGE = File.expand_path("../data/image.jpg", __FILE__)
TEXT = File.expand_path("../data/text.txt", __FILE__)
# 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}
Capybara.javascript_driver = :webkit
RSpec.configure do |config|
config.mock_with :rspec
config.use_transactional_fixtures = false
config.include Paperclip::Shoulda::Matchers
config.before :each do
if example.metadata[:js]
Capybara.server_port = 33333
Capybara.current_driver = :webkit
end
if Capybara.current_driver == :rack_test
DatabaseCleaner.strategy = :transaction
else
DatabaseCleaner.strategy = :truncation
end
DatabaseCleaner.start
end
config.after do
DatabaseCleaner.clean
Capybara.use_default_driver if example.metadata[:js]
end
end
def login(email, password)
visit '/admin'
fill_in('user_email', :with => email)
fill_in('user_password', :with => password)
click_button 'Entrar'
end
end
Spork.each_run do
require File.expand_path("../../config/routes", __FILE__)
load "#{Rails.root}/config/routes.rb"
Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }
end
login_spec.rb:
# -*- encoding : utf-8 -*-
require 'spec_helper'
feature 'login and register' do
background do
FactoryGirl.create :configuration
end
it 'should not be possible guest user register an administrator' do
visit '/admin'
page.should_not have_content 'Registrar'
lambda { visit '/users/sign_up' }.should raise_error ActionController::RoutingError
end
it 'edit user information' do
user = FactoryGirl.create :user
login(user.email, '123456')
click_link user.email
fill_in 'E-mail', :with => 'outro_email#email.com'
click_button 'Salvar'
page.should have_content 'Usuário atualizado(a) com sucesso.'
end
end
I am attempting to setup DatabaseCleaner with RSpec to make sure that I can properly cleanup any test objects that I have created. If I don't use DatabaseCleaner, then the following test passes.
However, when I add the DatabaseCleaner code to my spec_helper.rb file, the test fails as outlined below.
include AuthHelper
describe BulkJobsController do
describe 'GET /bulk_jobs/:id' do
context 'with valid user' do
before do
login_as('someuser')
end
context 'and a job' do
before do
#job = create(:bulk_job_close_cases)
puts "Test - Bulk Job Count: #{BulkJob.count}" # This is always 1
get :show, id: #job.id, format: 'json'
end
it 'is valid' do
response.status.should eq(200)
end
end
end
end
end
Here is the controller:
class BulkJobsController < ApiController
def show
puts "Controller - Bulk Job Count: #{BulkJob.count}" # This is 1 without DC and 0 with DC
#job = BulkJob.find(params[:id])
respond_with #job
end
end
Here is the relevant portion of my spec/spec_helper.rb file:
####################
# Database Cleanup #
####################
require 'database_cleaner'
config.use_transactional_fixtures = false
config.after(:suite) do
ActiveRecord::Base.connection.execute("DEALLOCATE ALL")
end
config.around(:each) do |example|
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.start
example.run
DatabaseCleaner.clean
end
Oddly, removing the DatabaseCleaner.clean statement doesn't actually make the test pass either; however, removing the DatabaseCleaner.start code does make the test pass.
The test is failing because the controller can't find a BulkJob with the proper ID. If I print out the counts of the objects, inside the test the number of BulkJobs is 1, but inside the controller, it's 0. When the test passes, obviously, the number is 1 in both spots.
I haven't included Capybara or Selenium, so as I understand it, rspec should be using rack-test to run this example.
Is there something wrong with my configuration/test? Is DatabaseCleaner cleaning too early?
Here is the failing test:
Failures:
1) BulkJobsController GET /bulk_jobs/:id with valid user and a job is valid
Failure/Error: get :show, id: #job.id, format: 'json'
ActiveRecord::RecordNotFound:
Couldn't find BulkJob with id=39
# ./app/controllers/bulk_jobs_controller.rb:6:in `show'
# ./spec/controllers/bulk_jobs_spec.rb:33:in `block (5 levels) in <top (required)>'
and my Gemfile:
source 'http://rubygems.org'
gem 'rails', '~>3.2.12'
gem 'composite_primary_keys', '>=3.1.0'
gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'pg'
gem 'activerecord-mysql2-adapter', '~> 0.0.3'
gem 'rake', '>=0.8.7'
gem 'dalli'
gem 'postmark-rails'
gem 'rb-readline'
gem 'statsmix'
gem 'daemons'
gem 'delayed_job_active_record'
gem 'whenever', :require => false
gem 'iron_worker'
gem 'statsmix'
gem 'exceptional'
#gem 'newrelic_rpm'
group :test do
gem 'database_cleaner'
gem 'rspec-rails'
gem 'shoulda-matchers'
gem 'factory_girl_rails'
end
I'm getting the following error when I try to run an rspec test:
/srv/offerme/spec/requests/static_pages_spec.rb:13: undefined method `visit' for #<Class:0xb3436684> (NoMethodError)
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/example_group.rb:238:in `module_eval'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/example_group.rb:238:in `subclass'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/example_group.rb:224:in `describe'
from /srv/offerme/spec/requests/static_pages_spec.rb:12
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/example_group.rb:238:in `module_eval'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/example_group.rb:238:in `subclass'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/example_group.rb:224:in `describe'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/dsl.rb:18:in `describe'
from /srv/offerme/spec/requests/static_pages_spec.rb:3
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `load'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `load_spec_files'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `map'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `load_spec_files'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/command_line.rb:22:in `run'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:69:in `run'
from /var/lib/gems/1.8/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:8:in `autorun'
from /usr/local/bin/rspec:19
The file I get this error in looks like this (spec/requests/static_pages_spec.rb) :
require 'spec_helper'
describe "StaticPages" do
include Capybara::DSL
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_index_path
response.status.should be(200)
end
end
describe "Home page" do
visit 'static_pages/home'
page.should have_content('OfferMe')
end
end
My spec_helper.rb file looks like this:
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rspec'
# 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
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
config.include Capybara::DSL
end
module ::RSpec::Core
class ExampleGroup
include Capybara::DSL
include Capybara::RSpecMatchers
end
end
And, finally, my Gemfile looks like this:
source 'https://rubygems.org'
gem 'rails', '3.2.7'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
group :development, :test do
gem 'sqlite3'
gem 'rspec-rails'
end
group :test do
gem 'capybara'
end
gem 'json'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.4'
gem 'coffee-rails', '~> 3.2.2'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
gem 'twitter-bootstrap-rails'
end
gem 'jquery-rails'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
# To use Jbuilder templates for JSON
# gem 'jbuilder'
# Use unicorn as the app server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug'
gem 'therubyracer', '0.10.1'
gem 'libv8'
gem 'webrat'
I have seen this GitHub issue and have tried some of the workarounds as well as looked at some other StackOverflow questions pertaining to the similar issue (that's why some of the code looks redundant/hacky). However, none of them have worked yet. Please help!
UPDATE:
The problem is that you're calling visit outside of an it block, here:
describe "Home page" do
visit 'static_pages/home'
page.should have_content('OfferMe')
end
Wrap those middle lines in an it block:
describe "Home page" do
it "has a homepage" do
visit 'static_pages/home'
page.should have_content('OfferMe')
end
end
That should work.
ORIGINAL ANSWER:
I could be wrong, but I believe you have to include capybara in both the test and development sections of your Gemfile.
Try changing that section of your Gemfile to this:
group :development, :test do
gem 'sqlite3'
gem 'rspec-rails'
gem 'capybara'
end
This is an old post. I have had the same issue. I thought I share my solution.
In my Gemfile I have had
group :test do
gem 'capybara'
end
And the visit was in the right spot however I was getting the same error. so this is what I did. I ran the update on the Gem and all are good now.
bundle update capybara
Hope this help someone.