#391 Testing JavaScript with PhantomJS pro
PhantomJS allows us to test JavaScript without going through a browser window. Here I show how to do this using Capybara and Poltergeist. I also give some tips on handling database transactions and skipping javascript tests.
- Download:
- source code Project Files in Zip (57 KB)
- mp4 Full Size H.264 Video (27.3 MB)
- m4v Smaller H.264 Video (12.3 MB)
- webm Full Size VP8 Video (13.5 MB)
- ogv Full Size Theora Video (28.5 MB)
Browse_code
Browse Source Code
Resources
- PhantomJS
- Poltergeist
- Headless Testing Frameworks
- Three tips to improve the performance of your test suite
- Episode 257: Request Specs and Capybara
- Episode 261: Testing JavaScript with Jasmine
Note: In the episode I mention the Rails app is running in a separate process, but it is actually a separate thread. Also some have reported concurrency issues with the shared database connection hack, therefore you may want to use truncation with Database Cleaner instead (thanks Jon Leighton).
terminal
brew install phantomjs phantomjs try_phantom.coffee rake spec rspec . --tag '~js'
Gemfile
group :test do gem 'capybara' gem 'poltergeist' end
spec/spec_helper.rb
require 'capybara/poltergeist' Capybara.javascript_driver = :poltergeist
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
spec/requests/orders_spec.rb
describe "Orders" do it "validates card number", js: true do visit new_order_path fill_in "Credit Card Number", with: "1234" page.should have_content("Invalid card number") end it "fetches more orders when scrolling to bottom", js: true do 11.times { |n| Order.create! number: n+1 } visit orders_path page.should have_content('Order #1') page.should_not have_content('Order #11') page.evaluate_script("window.scrollTo(0, document.height)") page.should have_content('Order #11') end end
try_phantom.coffee
page = require('webpage').create() page.open 'http://localhost:3000', (status) -> title = page.evaluate -> document.title console.log "Title: #{title}" phantom.exit()
loading