Rails4 Javascript-integrated unit tests via PhantomJS, RSpec, and Capybara
In this blog post, I’ll share some code that sets up a basic configuration to do Javascript testing via RSpec and Phantomjs.
If you don’t already have PhantomJS, you can install it via Homebrew.
brew install phantomjs
For this post, I ran a few commands to setup a new project space for a Rails app:
mkdir rails4_integration_test
# set ruby version and gemset:
echo ruby-2.1.4 > rails4_integration_test/.ruby-version
echo rails4_integration_test > rails4_integration_test/.ruby-gemset
# install rails gem, and create a new project:
gem install rails --no-rdoc --no-ri
rails new .
# integrate with git
git init
git add .
git commit -am "initial commit"
# initialize database
rake db:migrate
For my test I created a new controller called “Demos” with an action “index”:
rails generate controller Demos index
I revised the default index file (app/views/demos/index.html.erb) and added an ID to the H1 tag. Later in the code I will use a JQuery selector to find this element and get its content.
<h1 id='demos_index_test'>Demos#index</h1>
<p>Find me in app/views/demos/index.html.erb</p>
I wanted to integrate user authentication with this test, so I added the devise gem. edit file: Gemfile, added:
gem 'devise'
Devise integration:
# install gems:
bundle install
# execute devise generators:
rails generate devise:install
rails generate devise User
# update database:
rake db:migrate
Updated the Demos controller to require an authenticated user, edit file: app/controllers/demos_controller.rb
class DemosController < ApplicationController
# require authenticated user:
before_action :authenticate_user!
def index
end
end
Set the root/home route to point to the Demos controller index method. edit file: config/routes.rb, add:
root to: "demos#index"
Next I added the test gems. edit file: Gemfile, add:
group :test do
gem 'rspec-rails'
gem 'capybara'
gem 'poltergeist'
gem 'factory_girl_rails'
end
Install the gems and run the RSpec generator:
bundle install
rails generate rspec:install
Revised the RSpec helper to include the new gems and configuration, edit file: spec/spec_helper.rb
require 'rails_helper'
# ..snip..
require 'capybara/rspec'
require 'capybara/poltergeist'
require 'factory_girl_rails'
RSpec.configure do |config|
# ..snip..
# Factory Girl
config.include FactoryGirl::Syntax::Methods
end
# register phantomjs driver:
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {
debug: true,
#timeout: 60,
js_errors: true,
#inspector: true,
})
end
# set defaults:
Capybara.javascript_driver = :poltergeist
Capybara.default_driver = :poltergeist
# Capybara.default_wait_time = 60
Created a FactoryGirl User factory, new file: spec/factories/user.rb
FactoryGirl.define do
factory :user do
email "test@example.com"
password "password123"
password_confirmation "password123"
end
end
Created the integration unit test, new file: spec/features/demos_spec.rb
describe "demos", :type => :feature, :js => true do
before :all do
@current_user = create(:user)
end
after :all do
@current_user.destroy
end
it "logs in user" do
# sign in
visit new_user_session_path
# fill out log in form
fill_in 'user_email', with: @current_user.email
fill_in 'user_password', with: @current_user.password
find("#new_user input[type='submit']").click
# execute jQuery selector to check page/H1 contents:
result = page.evaluate_script("$(\"h1#demos_index_test\").text()")
expect(result).to eq "Demos#index"
end
end
The test can be executed via:
rspec
# or
rspec spec/features/demos_spec.rb
Example sucess output!
Finished in 2.44 seconds (files took 2.02 seconds to load)
1 example, 0 failures