Today I wanted to write some javascript tests for my Moviezz project.

Maybe two years ago, I’ve written javascript tests for a project at nine.ch. I ended up by using Cucumber, Capybara and Selenium for this. The result was okay, but it took you a very long time to run the tests and you could not do anything else than watching your webbrowser clicking links and filling in text.

Some weeks ago, I heard about PhantomJS and I waited since for the right chance to try it out. PhantomJS enables you to run your javascript tests headless, means no browser windows is opened and used to click and fill. This also gives you the ability to run your javascript tests via Jenkins or Travis.

At first, I verified that capybara is in my Gemfile.

gem 'capybara', group: :test

It also has to be loaded by RSpec, so I required it in spec_helper.

require 'capybara/rspec'
require 'capybara/rails'

After this, I went on and wrote the first javascript test with RSpec. Note the js: true on line 7, this switches the Capybara driver to the javascript adapter.

require 'spec_helper'

describe 'search for a movie' do

  let(:tmdb_movie) { tmdb_result }

  it 'searches for the given title', js: true do
    visit new_movie_path
    page.should_not have_content('Star Wars Episode VII')
    fill_in 'title', with: 'Star Wars'
    page.should have_content('Star Wars Episode VII')
  end
end

When I ran the test, Capybara opened a new Firefox window and did my defined steps as expected.

To use PhantomJS with Capybara, you have to switch to another adapter. There is an adapter called Poltergeist which enables you to use PhantomJS. So I went on and added Poltergeist to my Gemfile.

gem 'poltergeist', group: :test

As soon as I required capybara/poltergeist and added Capybara.javascript_driver = :poltergeist in spec_helper.rb, my javascript test passed without opening a window.

You cannot use transactions, which is the default, to cleanup your database after each javascript test, better explained here. To solve this, you can use DatabaseCleaner with the truncation strategy instead of transactions.

But there is a caveat, the truncation strategy is slower. As I like my tests run fast, I wrote the following RSpec configuration which just enables the truncation strategy for tests with js: true set.

RSpec.configure do |config|

  config.before :suite do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with :truncation
    Capybara.javascript_driver = :poltergeist
  end

  config.before :each do
    if example.metadata[:js]
      DatabaseCleaner.strategy = :truncation
    else
      DatabaseCleaner.strategy = :transaction
      DatabaseCleaner.start
    end
  end

  config.after :each do
    DatabaseCleaner.clean
  end

end

Note, that I also moved Capybara.javascript_driver = :poltergeist into this config file as it belongs to the javascript configuration.

After this, I just had to disable the default transactional feature in spec_helper.rb

RSpec.configure do |config|
  config.use_transactional_fixtures = false
end

Now, I have headless javascript tests and the fastest possible database cleanup strategy depending on the test type.

All the code above can also be found in a gist.