Capybara v4
Covered in this doc
Integrating Percy with 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 can be easily adapted for other testing frameworks.
Percy Capybara v4
This documentation is for Percy Capybara version 4.0.0 and above. Earlier versions of Percy Capybara had a different, and incompatible, API.
See the Upgrading to v4 guide or the old docs.
Setup
Add this line to your application's Gemfile:
gem 'percy-capybara', '~> 4.0.0'
And then run:
$ bundle install
Or install it yourself with gem install percy-capybara
.
You will also need to install the Percy agent. This is a process runs alongside your tests, uploading snapshots to Percy on your behalf. You will need to use npm to install it.
If your project does not already have a
package.json
file in the root directory, runnpm init
and follow the prompts.package.json
is like a Gemfile for Node packages.
To install @percy/agent
locally for your project:
$ npm install --save-dev @percy/agent
This will create a ./node_modules/
directory containing the agent and its dependencies. The agent's executable binary will be located in ./node_modules/.bin/percy
.
Next, import the Percy Capybara library into the file(s) from which you want to take snapshots:
require 'percy'
Now you can use Percy.snapshot(...)
to generate a snapshot from your test:
describe 'Test with visual testing', type: :feature, js: true do
it 'loads example.com homepage' do
visit 'https://example.com'
Percy.snapshot(page, { name: 'example.com homepage' })
end
end
The page
object you pass into Percy.snapshot
is the Capybara::Session
object that represents the web page under test. It should be available in your Capybara tests.
Finally, wrap your test runner command in a percy exec
command. This will start a local Percy agent to receive snapshots from your tests and upload them to your Percy dashboard.
Before you can successfully run Percy, the PERCY_TOKEN
environment variable must be set:
# Windows
$ set PERCY_TOKEN=<your token here>
# Unix
$ export PERCY_TOKEN=<your token here>
You can invoke percy using its full path (typically ./node_modules/.bin/percy
), or by calling npx percy
(npx is a Node utility that lets you execute package binaries). If you're using an npm version before 5.2 that does not support npx, you can use $(npm bin)/percy
instead.
For example, if you're using RSpec to run your tests, your new test command becomes:
$ npx percy exec -- rspec
Note the double dash, --
, between npx percy exec
and your test run command.
You'll want to add this npx percy exec -- <test runner>
command as the new way for your CI system to run your tests.
That's it! Now, whenever your CI runs, snapshots of the app in that state will be uploaded to Percy for visual testing!
Configuration
Percy.snapshot(page)
Percy.snapshot(page, options)
page
is the Capybara::Session
object representing the web page you want to snapshot. Required.
options
is an optional hash that can include:
name
: A string identifying this snapshot. It can be any string that makes sense to you to identify the page and its state. It needs to be unique and remain the same across builds. If you don't provide it, Percy will use the full URL of the page under test. If you are taking multiple snapshots with the same URL, you will need to manually provide snapshot names in order to disambiguate between the two snapshots. For more details on generating snapshot names, see Autogenerated snapshot names.widths
: An array of integers representing the browser widths (in pixels) at which you want to take snapshots.min_height
: An integer specifying the minimum height of the resulting snapshot (the snapshot might turn to be higher than this value, depending on the contents of the page). Defaults to 1024px.percy_css
: A string containing Percy specific CSS that will be applied to this snapshot.request_headers
: An object containing HTTP headers to be sent for each request made during asset discovery for this snapshot.
Examples
Percy.snapshot(page, { name: 'Responsive snapshot', widths: [768, 992, 1200] })
Percy.snapshot(page, { min_height: 2000 })
Global Configuration
You can also configure Percy to use the same options over all snapshots. To see supported configuration, including widths, read our SDK configuration docs
Waiting for elements with Capybara
Capybara has a robust internal wait system that can be used to efficiently wait for certain page elements to appear before continuing. You should never need to write a flaky sleep
call with Capybara.
With RSpec tests
expect(page).to have_css('#new-project')
expect(page).to have_content('New Project')
This will efficiently wait for the #new-project
element to exist.
Without RSpec
You can use Capybara's generic has_no_css?
/has_no_content?
/has_no_xpath?
methods to make sure that the page state is correct before continuing on. You probably will want to raise an exception to stop execution if the query for the element returns true.
raise 'element missing!' if page.has_no_css?('#new-project')
raise 'element missing!' if page.has_no_content?('New Project')
More info
- https://github.com/teamcapybara/capybara#querying
- https://github.com/teamcapybara/capybara#asynchronous-javascript-ajax-and-friends
Troubleshooting
Missing styles
If your screenshots are missing styles and you're using Webpacker to build your apps front end assets, you will need to configure it to extract the CSS when building for tests. By default, Webpack will generate CSS as a blob
asset, which cannot be discovered or saved when we're doing asset discovery. In your webpacker config file you will need to specify extract_css: true
:
test:
...
# Extract and emit a css file
extract_css: true
Updated about 2 years ago