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
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 have added the database_cleaner gem to my rails application in order to clean my database between specs. Here's my current configuration for database_cleaner, located in spec/spec_helper.rb:
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
DatabaseCleaner.start
DatabaseCleaner.clean
end
config.before(:each) do
DatabaseCleaner.clean
end
config.after(:each) do
DatabaseCleaner.clean
end
config.after(:suite) do
DatabaseCleaner.clean
end
Now, this configuration works fine, so long as every last spec that is run either passes or fails.
However, in the event of an error (rspec doesn't give you a nice little E like minitest, it throws this sort of thing:
09:17:32 - INFO - Running: spec
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/validations.rb:57:in `save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)
), the database isn't cleaned! Residual data from the spec just before the error stays in the database. I suppose this is because database_cleaner doesn't regard the erroneous spec as finishing and so doesn't clean the database.
Now, this doesn't really cause any harm until you run your specs again. The residual data then causes an error analogous to this:
09:17:32 - INFO - Running: spec
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/validations.rb:57:in `save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)
Getting around this error is simple enough; running rails_env=test rake db:reset or firing up your database shell and emptying the relevant tables with sql statements will clear this data and allow the specs to be run without a hitch.
However, this is getting annoying. One wrong character in any of my specs (anything to make it erroneous rather than a failure) causes my whole testing workflow to jam up, almost like the firing mechanism of an automatic weapon!
What are your suggestions regarding database_cleaner? Do you have any example configurations that allow for the database to be cleaned, even in the event of an erroneous test?
I'm using guard to run my rspecs that are further augmented with factory-girl:
Gemfile:
source 'https://rubygems.org'
group :development do
gem 'capistrano'
gem 'rb-fsevent'
gem 'debugger'
end
group :development, :test do
gem 'rspec-rails', '~> 2.14.0'
gem 'sqlite3'
gem 'guard-rspec'
gem 'guard-livereload', require: false
gem 'guard-shell'
gem 'webrick', '~> 1.3.1'
end
group :test do
gem 'factory_girl_rails'
gem 'capybara', '~> 2.2.0'
gem 'selenium-webdriver'
# capybara-webkit gem requires an application called 'libqtwebkit-dev' to build. To install 'libqtwebkit-dev' in Ubuntu, run
# sudo apt-get install libqtwebkit-dev
# gem 'capybara-webkit'
gem 'rb-readline'
gem 'launchy'
gem 'database_cleaner'
end
group :production do
gem 'pg'
# gem 'puma'
end
# rails version
gem 'rails', '4.0.1'
# standard library
gem 'sass-rails', '~> 4.0.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 1.2'
group :doc do
gem 'sdoc', require: false
end
# custom
gem 'activeadmin', github: 'gregbell/active_admin'
gem 'devise'
gem 'simple_form'
spec/spec_helper:
# 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'
# 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 }
# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
RSpec.configure do |config|
config.include Capybara::DSL
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
DatabaseCleaner.start
DatabaseCleaner.clean
end
config.before(:each) do
DatabaseCleaner.clean
end
config.after(:each) do
DatabaseCleaner.clean
end
config.after(:suite) do
DatabaseCleaner.clean
end
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# config.include RSpec::Rails::RequestExampleGroup, type: :feature
# 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"
end
You want to change this
config.after(:suite) do
DatabaseCleaner.clean
end
To this:
config.after(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
Otherwise, it will simply roll back the transaction, which will leave any data that existed before the transaction was started.
add a file:
# RSpec
# spec/support/database_cleaner.rb
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
end
and uncomment
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
in spec/rails_heper.rb
This works for me:
DatabaseCleaner.strategy = :truncation
...
before(:each) do
DatabaseCleaner.clean
end
Please show the spec(s).
You need to be sure that your setup/teardown is done in before/after/its, etc. statements.
If you have setup and variable assignment outside of the above and just 'in the test itself' then the test will bomb out as you are experiencing. If done in setup, this problem can be avoided.
You should not need to be trying to jigger with the internals the way you are. As with many thing in Ror land, if you're doing this, chances are you may be 'going' off the rails with your code. Rails is intended to be a framework that does all the tedium for you, you just have to stay 'on the rails'.
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