Capybara v3

🚧

Deprecated

v3 is deprecated. See the docs for the newest version.

Percy::Capybara is a library for integrating Percy's visual regression testing into your existing Capybara feature tests in any Ruby web framework---including Rails, Sinatra, etc.

If you've written feature tests (or "UI tests", "acceptance tests", etc.), you know how hard it can be to get them right and to get your app in the correct UI state. Percy::Capybara lets you take all the time you've spent building your feature tests and expand them with screenshots and visual regression tests to cover all the visual changes in your app, even behind complex UI states.

The examples below assume you are using RSpec, but they could be easily adapted for other testing frameworks.

Installation


Add this line to your application's Gemfile:

gem 'percy-capybara'

And then run:

$ bundle install

Or install it yourself with gem install percy-capybara.

Setup


Test suites must call two hooks:

  • Percy::Capybara.initialize_build before running the test suite.
  • Percy::Capybara.finalize_build after the test suite is finished, even if tests fail.

🚧

NOTE: If your builds get stuck "Receiving...", check this configuration first.

RSpec

Add these setup lines to spec_helper.rb:

RSpec.configure do |config|
  # ...

  config.before(:suite) { Percy::Capybara.initialize_build }
  config.after(:suite) { Percy::Capybara.finalize_build }
end

Cucumber

Add these lines to features/support/percy.rb:

Percy::Capybara.initialize_build
at_exit { Percy::Capybara.finalize_build }

Other test frameworks (MiniTest, etc.)

For example, with MiniTest you can add this to your test_helper.rb:

Percy::Capybara.initialize_build
MiniTest.after_run { Percy::Capybara.finalize_build }

NOTE: Rails 5.0.0 has a bug and doesn't invoke MiniTest.after_run. Please upgrade to 5.0.1 or use an at_exit hook instead.

Usage


Now the fun part!

You can integrate with Percy by adding one line to your existing feature specs:

Percy::Capybara.snapshot(page, name: 'homepage with dropdown')

For example:

describe 'a feature', type: :feature, js: true do
  it 'shows the dropdown menu when clicked' do
    visit '/'
    first('.dropdown-toggle').click
    expect(page).to have_selector('#main-dropdown', visible: true)

    Percy::Capybara.snapshot(page, name: 'homepage with dropdown')
  end
end

Done! 🚀 That's it! Now commit and push your branch to run your tests in your CI service, or create a GitHub PR. Snapshots will be uploaded to Percy for rendering and processing visual diffs.

📘

Best practices for Capybara and writing feature specs are outside the scope of these docs. See the Capybara docs for more Capybara usage examples.

The name: 'homepage with dropdown' argument is not required, but it is helpful to identify the page by more than just its URL. If you are snapshotting a page multiple times with the same URL, name must be set. See Identifying snapshots below.

Responsive visual diffs

You can use Percy responsive visual diffs to test pages at different CSS breakpoints.

In your spec_helper.rb, simply set the default widths for all snapshots:

Percy.config.default_widths = [375, 1280]

With the above configuration, all snapshots will render at both mobile and desktop breakpoints by default.

You can also override widths per-snapshot:

Percy::Capybara.snapshot(page, name: 'homepage', widths: [375, 1280])

If you're testing components instead of full pages, you may also want to set the minimum_height argument to override the default of 1024px. Note that minimum_height sets the default viewport height and the resulting screenshot may still be be larger if the page's content height is larger.

Percy::Capybara.snapshot(page, name: 'homepage', minimum_height: 300)

Local dev environments

You may want to enable Percy locally while getting set up. See Local development setup for more info.

Identifying snapshots

Percy needs to be able to uniquely identify the same snapshot across builds to provide visual diffs.

To accomplish this, Percy::Capybara uses the current page URL as the name of the snapshot. We assume that your app has been built with stateful navigation and that the URL fully identifies the page state.

However, there are many cases where this is not enough---for example, populating test data in the page, or performing a UI interaction that doesn't change the URL (like clicking the dropdown in the example above).

To manually identify a snapshot, you can provide the name parameter:

Percy::Capybara.snapshot(page, name: 'homepage (with dropdown clicked)')

The name param can be any string that makes sense to you to identify the page state. It should be unique and remain the same across builds. It is required if you are snapshotting a page multiple times with the same URL.

Advanced


Webpacker

Webpacker is new in Rails 5.1, and can be used to manage assets (javascript, css, images, and fonts) with webpack. If you're using Webpacker, we recommend running webpacker:compile in your CI before running your tests. This allows Percy to handle assets created by webpacker.

bundle exec rails webpacker:compile

Including iframes

Percy::Capybara disables iframes by default. We've found that iframes usually don't affect the rendering of the page, and can sometimes timeout and break builds. However, if you'd like to include iframes, use the include_iframes option.

RSpec.configure do |config|
  # ..
  config.before(:suite) do
    Percy::Capybara.use_loader(:sprockets_loader, include_iframes: true)
  end
end

Ember CLI Rails

If you are using Ember CLI Rails you need to tell Percy about the Ember apps you've mounted in routes.rb.

For example, if your routes.rb file looks like this:

Rails.application.routes.draw do
  mount_ember_app :admin, to: "/admin", controller: "admin"
  mount_ember_app :frontend, to: "/"
end

Then configure your before suite block like this:

config.before(:suite) do
  ember_apps = {admin: '/admin', frontend: '/'}

  EmberCli.compile!
  Percy::Capybara.use_loader(:ember_cli_rails, {mounted_apps: ember_apps})
  Percy::Capybara.initialize_build
end

Troubleshooting


Debug mode

Run with the PERCY_DEBUG=1 environment variable to see what build resources and snapshots are being created for your build.

WebMock/VCR users

If you use VCR to mock and record HTTP interactions, you need to allow connections to the Percy API:

VCR.configure do |config|
  config.ignore_hosts 'percy.io'
end

If you use WebMock to stub out HTTP connections, you need to allow connections to the Percy API:

WebMock.disable_net_connect!(allow: 'percy.io')

If you still experience problems, and you are using a Webmock version older than 2.0.0, try adding require: false to the line in your Gemfile so that Webmock won't block the HTTP request in initialize_build:

gem 'webmock', require: false

Turn off debug assets

After upgrading to Sprockets 3, you may notice broken CSS in Percy builds. You likely have this option set in test.rb:

config.assets.debug = true

This must be set to false in your test.rb file:

config.assets.debug = false

There is no compelling reason to have debug assets permanently enabled in tests---debug assets disables concatenation of asset files and will negatively affect your test performance and consistency. You must turn off debug assets in tests for Percy to work correctly.

Cleanup locally compiled assets

Have you run rake assets:precompile locally to test assets? These compiled assets take precedence over others and can break Percy's asset discovery. You should run rake assets:clobber to clear out your public/assets directory.