← Back to Upcase

How to make Capybara/Poltergiest wait until models are created?


(Aaron Renner) #1

When doing integration tests, I usually use factory_girl to quickly set up the required objects for my test. However, when I use js: true and poltergiest, capybara runs the web browser in a separate thread, so the objects may not be created when it starts clicking through the web pages. Here is an example

require 'spec_helper'

feature 'Bike administration' do
  scenario 'create a bike', js: true do
    user = create(:admin)
    dealer = create(:dealer)
    brand = create(:brand, name: "Trek")

    # Since the browser is on a separate thread, this can potentially run
    # before the user is finished being created
    sign_in_as(user)

    visit admin_root_path
    click_link "Dealers"

    view_bikes_for(dealer)

    click_on "New Bike"
    fill_out_bike_form "Superfly 100"
    add_bike_photo
    save
    
     ...
  end
end

I ended up creating the following helper module that I would call like wait_until{dealer.persisted?} right after my factory girl functions and before I start navigating on the website.

#Found here: https://gist.github.com/jnicklas/d8da686061f0a59ffdf7
module WaitHelper

  def wait_until
    require "timeout"
    Timeout.timeout(Capybara.default_wait_time) do
      sleep(0.1) until value = yield
      value
    end
  end

end

RSpec.configure do |config|
  config.include WaitHelper, type: :feature
end

Is this how you handle setting up your javascript integration tests? Do you create objects from factories and then use some sort of waiting function before you start navigating the site?


(Aaron Renner) #2

Nevermind, I think I am having some other issues with database cleaner running before it’s supposed to. Now that I think about this, this should all run synchronously.


(Patrik Bóna) #3

The issue with javascript tests is that DB connection is not shared between the threads by default. And because of tests are running in transactions, you cannot see same data between different threads.

I am not sure if it is also your issue, but solution for issue above is to patch active record for tests. Put following code into spec/support/shared_db_connection.rb and it should work:

class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil
 
  def self.connection
    @@shared_connection || retrieve_connection
  end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

For me it works very well. You can find more information here (point 3): http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/