September 23, 2013

JavaScript in integration tests

Update! I do not recommend to use shared DB connection anymore. Check this article to see why.

Testing of Ruby on Rails applications is easy. Especially when you use some additional tools which make it even easier.

But there is one tool which I did not mention in my previous post about tools for TDD. It is capybara-webkit. It allows you to test JavaScript in your integration tests without starting a browser.

You can use JavaScript in your integration tests just with capybara itself, but then you need to have firefox installed which is started for every JS test. And it is not very fast.

With capybara-webkit there is no browser started. It uses just webkit engine to perform your JavaScript tests.

But there are two tricky parts:

1) capybara-webkit native extension can be hard to install. But it depends on your platform. You can find more information on capybara-webkit readme.

2) Within JavaScript integration tests browser (or browser engine) runs in different thread then test itself. Because of this also another database connection is used. This can be tricky, because by default database transactions are used and you cannot see new DB entries from transaction of another DB connection. There are more solution to this, but I like following one most.

# spec/support/shared_db_connection.rb
class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil

  def self.connection
    @@shared_connection || retrieve_connection
  end
end

# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

It is solution taken from this article.

And it can be used with spork too! Just update you spec_helper.rb.

# spec/spec_helper.rb
Spork.each_run do
  # This code will be run each time you run your specs.
  if Object.const_defined?('ActiveRecord')
    class ActiveRecord::Base
      mattr_accessor :shared_connection
      @@shared_connection = nil

      def self.connection
        @@shared_connection || retrieve_connection
      end
    end

    # Forces all threads to share the same connection. This works on
    # Capybara because it starts the web server in a thread.
    ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
  end
end

And now you can enjoy testing JavaScript in your integration tests. But note that it makes them slower, so use it carefully.

For more information about setup see capybara-webkit page.

Hey there!

My name is Patrik Bóna and I am the only programmer at Memberful. This blog is kind of dead, but I just started my own Ruby on Rails screencast. Follow me on Twitter if you want to be notified about my newest videos.