Playwright
The happo/playwright module makes it easy to
integrate a Playwright test suite with
Happo.
Pre-requisites
Before you start following the instructions here, you'll need a working Playwright setup and a Happo account.
Installation
In your project, install the happo npm module.
npm install --save-dev happo
Setup
Below is an example Playwright spec file. It takes a screenshot of a Hero image on an imaginary page.
import { test } from 'happo/playwright';
test('start page', async ({ page, happoScreenshot }) => {
await page.goto('http://localhost:7676');
const heroImage = page.locator('.hero-image');
await happoScreenshot(heroImage, {
component: 'Hero Image',
variant: 'default',
});
});
You will also need a happo.config.ts file with some minimal/required
configuration:
import { defineConfig } from 'happo';
export default defineConfig({
apiKey: process.env.HAPPO_API_KEY,
apiSecret: process.env.HAPPO_API_SECRET,
integration: {
type: 'playwright',
},
targets: {
chrome: {
type: 'chrome',
viewport: '1024x768',
},
},
});
See Configuration for more configuration options.
NOTE: For security reasons, you'll most likely want to pass in apiKey and
apiSecret via environment variables:
import { defineConfig } from 'happo';
export default defineConfig({
apiKey: process.env.HAPPO_API_KEY,
apiSecret: process.env.HAPPO_API_SECRET,
// ... more config
});
With Playwright fixtures
If you're using
Playwright fixtures, you can mix
happo-playwright in with
mergeTests.
Here's an example of how to do this:
import { test as happoTest } from 'happo/playwright';
import { test as base, mergeTests } from '@playwright/test';
const baseTest = base.extend({
myFixture: async ({}, use) => {
await use('my fixture value');
},
});
export const test = mergeTests(baseTest, happoTest);
Then in your Playwright test file, you can use the test function as usual:
import { test } from './test';
test('start page', async ({ page, happoScreenshot }) => {
await page.goto('http://localhost:7676');
const heroImage = page.locator('.hero-image');
await happoScreenshot(heroImage, {
component: 'Hero Image',
variant: 'default',
});
});
Usage
To enable Happo in your test suite, wrap your test command with the happo
script. Here's an example:
npx happo -- playwright test
If you're using yarn, you might have to specify the
double dashes twice (the first one is consumed by yarn itself):
yarn happo -- -- yarn playwright test
If you're not using the happo wrapper, Happo will be disabled for the whole
test suite.
Allowing failures
By default, no Happo reports are produced when the Playwright run fails. In some
cases, you might want to allow Happo to succeed even if the overall test run
fails. The allowFailures configuration option can then be used:
export default defineConfig({
integration: {
type: 'playwright',
allowFailures: true,
},
// ... rest of the config
});
If you're using yarn, you might need to pass the double dashes twice, like so:
yarn happo -- --allow-failures -- yarn playwright test
Selecting targets
If you want to avoid rendering an example in all browser targets (found in
happo.config.ts), you can use the targets option. The example will then be
rendered in the specified targets exclusively.
await happoScreenshot(heroImage, {
component: 'Footer',
variant: 'Default',
targets: ['chrome-small'],
});
In this example, the "Footer" snapshot will only be rendered in the target named
'chrome-small' found in happo.config.ts.
Dynamic targets
If you want to create a snapshot in a target that isn't defined in the
happo.config.ts config, you can use an object with name, browser and
viewport properties. Here's an example where a snapshot is taken in a
dynamically generated target:
await happoScreenshot(heroImage, {
component: 'Footer',
variant: 'Default',
targets: [{ name: 'firefox-small', browser: 'firefox', viewport: '400x800' }],
});
Here, "Footer" will only be rendered in a 400x800px Firefox window.
You can mix and match dynamic targets and target names as well:
await happoScreenshot(heroImage, {
component: 'Footer',
variant: 'Default',
targets: [
'chrome-small',
{ name: 'firefox-small', browser: 'firefox', viewport: '400x800' },
],
});
"Footer" is now rendered in Chrome (target specified in happo.config.ts) and
Firefox (dynamic target).
Continuous Integration
If you run the test suite in a CI environment, the happo module will do its
best to auto-detect your environment and adapt its behavior accordingly:
- On PR builds, compare the screenshots against the main branch
- On main branch builds, simply create the Happo report
To get the results of the Happo jobs back to your PRs/commits, you need to install and configure the Happo GitHub app. Instructions are available in the Continuous Integration docs.
Happo auto-detects the following CI environments:
- GitHub Actions
- Circle CI
- Travis CI
If you are using a different CI service, you'll have to set a few CLI args when
invoking the happo command:
--beforeShathe commit SHA that the branch/PR is based on (usually a commit onmain). Only set this for PR builds.--afterShathe SHA of the commit currently under test (typically the SHA atHEAD). Always set this.--baseBranchthe default/base branch you use, e.g.origin/dev. Defaults toorigin/main, so you only need to set this if you are using a different base branch.--linka URL to the PR/commit to help contextualize the report. Optional.
Parallel builds
If your Playwright test suite is spread across multiple machines and you want to get a combined Happo report for all the test runs, you can do the following:
- Use the
--nonceCLI argument to tie individual runs together. Any string unique to the build will do. - After the whole test suite is done, call
npx happo finalize. Make sure that the same--nonceis set as for the individual builds.
In some CI tools, you can use a built-in environment variable as --nonce. In
CircleCI for instance, you can use
--nonce ${CIRCLE_WORKFLOW_ID}.
You can also use a timestamp or a randomly generated string. The important thing
is that it's unique to the current CI run.
Email notifications
If you set the --notify CLI argument as part of your Playwright run, an email
will be sent out when the Happo comparison report is ready.
Usage instructions for --notify are available in
the Continuous Integration docs.
Advanced usage
Download all assets
By default, happo will download assets found locally and include them in an
assets package sent to happo.io. Any external URL will be left as-is, which
means they are expected to be publicly accessible by Happo workers. To include
external assets in the assets package as well, set a HAPPO_DOWNLOAD_ALL
environment variable.
HAPPO_DOWNLOAD_ALL=true npx happo -- playwright test
With this environment variable set, all assets are assumed to be private (i.e. not publicly accessible).
Clip snapshot strategy
By default, Happo uses the hoist snapshot strategy. This works by selecting the element for snapshotting and hoisting it out of the document to be sent to the workers. This element is then rendered in isolation in your configured browsers for screenshots.
For flexible elements, the default hoist snapshot strategy may cause the dimensions of the element to be different than it was on the page in the context that it was rendered.
If you want your screenshot to be taken of the element as it was rendered in its context on the page, and not in isolation, you may use the clip snapshot strategy.
To use the clip snapshot strategy, pass snapshotStrategy: 'clip' as an option
to happoScreenshot:
happoScreenshot(page.locator('.header'), {
component: 'Header',
variant: 'large',
snapshotStrategy: 'clip',
});
Troubleshooting
I need support!
We're here to help — send an email to support@happo.io and we'll assist you.
Happo isn't producing any screenshots
The happo/playwright module will disable itself if it can't detect any api
tokens (apiKey and apiSecret in config). Check to make sure your
happo.config.ts config is properly set up. There might also be more
information in the console logs from Playwright. Look for lines starting with
[HAPPO].
Where are my screenshots?
During test suite execution, Happo will only record information. All screenshots are taken asynchronously outside of the test run. This means that your test suite will finish sooner than the Happo job is done. To follow along the progress, look for a url logged by Happo:
[HAPPO] https://happo.io/a/284/async-reports/34
Styles are missing from my screenshots
Styles and assets are collected automatically during your test suite. If you notice styles/images/fonts etc are missing, one of a few things might have happened:
- CSS selectors depend on context that is missing to Happo. If you e.g. have
something like
#start-page .header { color: red }and screenshoot.header, the red color will be missing. This is because Happo only sees the.headerelement, never the surrounding page. - There could be a bug in how
happo/playwrightcollects styles and assets. Reach out to support@happo.io and we'll triage.