Getting Started with Snapshot Tests in Playwright
Tags: playwright, javascript, testing, ux
Published: 2024-03-04 00:00:00

As your web app matures, it becomes challenging to ensure your GUI doesn't break with any given update. There are a lot of browsers and devices, and countless states for every one of your components. Unit tests ensure your code remains consistent, and E2E tests will ensure your system remains consistent, but neither will catch visual anomalies, layout issues, or platform compatibility issues.

Enter _visual testing_. Visual tests store snapshots of your app's appearance, and compares them to the current state of your app. No more surprise bugs. No more developing in three different browsers and 12 different breakpoints. Visual testing automates the process, ensuring your app looks exactly right, all the time.

This article covers the basics of visual testing with Playwright. If you're interested in going deeper into visual testing, you'll love my [Ultimate Guide to Visual Testing in Playwright](https://www.browsercat.com/post/ultimate-guide-visual-testing-playwright).

Let's get started...

## 1. Install dependencies

If you already have Playwright installed, skip this step.

Otherwise, install your dependencies and create a sample test file:

```bash
# Install node dependencies
npm install -D @playwright/test
npm install -D typescript

# Install playwright browsers
npx playwright install

# Create the test file
mkdir -p tests
touch tests/homepage.spec.ts
```

## 2. Write your first visual test

Open `tests/homepage.spec.ts` and add the following code:

```typescript
import {test, expect} from '@playwright/test';

test('home page visual test', async ({page}) => {
  await page.goto('https://www.browsercat.com');
  await expect(page).toHaveScreenshot();
});
```

## 3. Run your visual tests

Run your tests with the following command:

```bash
npx playwright test
```

The first time your run your tests, they will fail with an error message like this:

```text
Error: A snapshot doesn't exist at {TEST_OUTPUT_PATH}, writing actual.
```

This is expected. Since Playwright has nothing to compare `expect(page).toHaveSnapshot()` to, it _must_ fail the test. But don't worry: the next time you run your tests, Playwright will compare the current state of the page to the stored snapshot.

So run your tests a second time:

```bash
npx playwright test
```

Success! You should see a message like this:

```text
Running 1 test using 1 worker
  1 passed (6.6s)
```

If your test failed, take a few minutes to see if you can fix the issue. If not, continue reading. I cover numerous troubleshooting tips later in this article.

### Where are snapshots stored?

By default, test snapshots are stored alongside the test file that created them.

When a visual test fails, Playwright will store the "before" image, the "after" image, and a "diff" image in the `./test-results` directory. These will come in handy later, for debugging your failed tests.

(Keep reading for advice on configuring the location of these snapshots. You probably don't want test output littering your codebase.)

## 4. Updating test snapshots

Awesome! Your test now confirms there haven't been any changes to the page, but what if you actually want to make some changes?

To update your snapshots, run your tests with the `--update-snapshots` (or `-u`) flag:

```bash
npx playwright test -u
```

This command will run your tests and update the snapshots to match the current state of the page. If you run this now, you should expect a passing result.

A word of caution: This command updates _all_ snapshots. Be very careful, as it's easy to accidentally update snapshots you didn't intend to.

### How do I update only _some_ snapshots?

To update the snapshots for a subset of tests, we can filter tests from the CLI. Only matching tests will be updated.

```bash
# Update tests with matching file name
npx playwright test -u "**/home*.spec.ts"

# Update tests with matching test name
npx playwright test -u --grep "home" --grep-invert "zzz"

# Updates tests within project
npx playwright test -u --project "chromium"
```

We'll go deeper into snapshot management later, but for now, let's focus on debugging...

## 5. Debug visual tests

We know how to update failing tests' snapshots, but what about when a test is failing because of a bug?

To explore this scenario, let's update our test so that our snapshot fails:

```typescript
test('home page visual test', async ({page}) => {
  await page.goto('https://www.browsercat.com');
  await expect(page).toHaveScreenshot({
    // crop the screenshot to a specific area
    clip: {x: 0, y: 0, width: 500, height: 500},
  });
});
```

Now let's run the tests, asking playwright to produce an HTML report:

```bash
npx playwright test --reporter html
```

After that command, your browser should have opened to your test report. And it should show a failed result.

Scroll down to the bottom of the page, and you'll see this widget:

![Visual test diff](https://res.cloudinary.com/browsercat/image/upload/v1709122396/articles/pw-snapshot-report-diff.png)

The "Diff" view offers a stark comparison between the expected and actual screenshots. However, I find the "Slider" view to be the most useful for actually fixing issues.

### How do I interpret the "diff" view?

The "diff" view shows the difference between the expected and actual screenshots.

Yellow pixels vary between snapshots, but they fall within the allowed threshold for differences.

Red pixels fall outside the allowed threshold for differences. By default, even a single red pixel will fail your test.

For advice on configuring these thresholds, visit my _Ultimate Guide to Visual Testing with Playwright_, and learn how to [make visual tests more forgiving](https://www.browsercat.com/post/ultimate-guide-visual-testing-playwright#make-visual-tests-more-forgiving).

### Do I need to use the HTML report?

No, you don't have to use the HTML report to run visual tests (though I recommend it). Whether you generate an HTML report, failing visual tests will automatically output the "before," "after," and "diff" images to the `./test-results` directory.

Often, I'll open the "before" image directly in VSCode while I work. That way I can keep my browser focused on my development app.

## 6. Use UI mode for quick visual testing

Playwright has an industry-leading "UI Mode" that makes working with tests a breeze.

While it has numerous killer features, my favorite is that it _automatically_ snapshots the test after _every single step_. This allows you to quickly debug your tests. It also makes it very easy to spot the right places to insert a visual assertion.

To run your tests in UI mode, use the following command:

```bash
npx playwright test --ui
```

I encourage you to explore UI mode, as it has a wealth of useful features.

![Playwright UI mode](https://res.cloudinary.com/browsercat/image/upload/v1709054370/articles/pw-snapshot-ui-mode.png)

## Next Steps...

You've now got a solid foundation for visual testing with Playwright. But there's so much more to learn!

For advanced tips, configuration guidance, and strategies for managing visual tests in your CI/CD pipeline, check out my [Ultimate Guide to Visual Testing in Playwright](https://www.browsercat.com/post/ultimate-guide-visual-testing-playwright).

In the meantime, happy testing!