Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec+Capybara request specs w/ JS not working

I cannot get request specs working when using Javascript. My specs pass if I run them without Javascript (the page is built to work with or without JS).

Specifically, the specs fail when I do assertions like Post.should have(1).record. Capybara just doesn't pick up the records from the DB, and the database is not cleaned between runs.

I've tried using DatabaseCleaner with transactional fixtures disabled - the common approach to this, I guess. No dice.

I've also tried (and, would ideally prefer) running without DatabaseCleaner, using transactional fixtures and forcing AR to share the same connection between threads (a patch described by José Valim). Again, no dice.

Additionally, I've also tried switching between Capybara-webkit and Selenium - the issue persists.

I've put up a sample app with just a basic Post scaffold, that replicates the problem: https://github.com/cabgfx/js-specs There's a spec_helper.rb with transactional fixtures and AR shared connection, and a spec_helper_database_cleaner.rb for the other scenario.

I normally use Spork, but I've disabled it in both spec_helper.rb files, just to eliminate a potential point of failure (in both apps; the "real" one and the sample app).

I develop locally using Pow on a Macbook Air, running OS X 10.7.3 with MRI 1.9.3 thru RVM. (I also tried on 1.9.2).

Hope I'm making sense - any guidance/help/pointers are greatly appreciated!

like image 643
cabgfx Avatar asked Oct 09 '22 05:10

cabgfx


2 Answers

Matt - thanks a lot for taking time to assist me! I tried setting it up with your spec_helper, using Selenium as the javascript driver.

The spec still failed - but I could see the correct behavior being executed in Firefox... Then it dawned on me, that the problem might occur because of Capybara not waiting for AJAX requests to finish.

I then reverted to my initial spec_helper (with Spork and no DatabaseCleaner), and simply used Capybara's wait_until { page.has_content? "text I'm inserting with JS" }.

I updated the sample app, and just added sleep 1 in the request spec, so you can see for yourself. It now works with and without Spork, and the AR monkey patch seems to work perfectly.

like image 106
cabgfx Avatar answered Oct 13 '22 11:10

cabgfx


I have tried your code with the spec_helper.rb listed below and the test passes. Note that the syntax for triggering database cleaner is a bit different than in your spec_helper_database_cleaner.rb.

We're using this in production, and we've also tried the modification suggested by Jose Valim but it didn't work for us - this did.

require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However,
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.

  # 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'

  # Add this to load Capybara integration:
  require 'capybara/rspec'
  require 'capybara/rails'

  include Capybara::DSL

  # 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 = false

    # 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

    # Include sign_in & sign_out for tests
    # config.include Devise::TestHelpers, :type => :controller

    # Use database_cleaner to ensure a known good test db state as we can't use
    # transactional fixures due to selenium testing
    config.before(:suite) do
      DatabaseCleaner.strategy = :truncation
      DatabaseCleaner.clean_with(:truncation)
    end

    config.before(:each) do
      DatabaseCleaner.start
    end

    config.after(:each) do
      DatabaseCleaner.clean
    end
  end
end

Spork.each_run do
  # This code will be run each time you run your specs.
end
like image 29
Matt Rohrer Avatar answered Oct 13 '22 12:10

Matt Rohrer