Skip to content

Commit

Permalink
feat: deprecate toMatchSnapshot for buffers (#26718)
Browse files Browse the repository at this point in the history
These are usually used for screenshots instead of toHaveScreenshot.
String-based snapshots are left as is.

<img width="836" alt="deprecated"
src="https://github.com/microsoft/playwright/assets/9881434/d02818da-7eea-47fc-8ea8-4104b0dd49b5">

---

Also deemphasized toMatchSnapshot throughout all docs.

Fixes #26612.
  • Loading branch information
dgozman committed Aug 26, 2023
1 parent bc1f627 commit 8348f66
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 163 deletions.
83 changes: 70 additions & 13 deletions docs/src/api/class-snapshotassertions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,75 @@
* since: v1.20
* langs: js

Playwright provides methods for comparing page and element screenshots with
expected values stored in files.
:::tip
For visual regression testing, use [`method: PageAssertions.toHaveScreenshot#1`] and [`method: LocatorAssertions.toHaveScreenshot#1`] instead.
:::

Playwright provides methods for comparing text values with expected values stored in snapshot files.

```js
expect(screenshot).toMatchSnapshot('landing-page.png');
expect(text).toMatchSnapshot('snapshot.txt');
```

## method: SnapshotAssertions.toMatchSnapshot#1
* since: v1.22

Ensures that the passed [string] matches the expected snapshot stored in the test snapshots directory.

**Usage**

```js
// Basic usage.
expect(await page.title()).toMatchSnapshot('page-title.txt');

// Bring some structure to your snapshot files by passing file path segments.
expect(await page.title()).toMatchSnapshot(['page-title', 'step1.txt']);
expect(await page.title()).toMatchSnapshot(['page-title', 'step2.txt']);
```

Note that matching snapshots only work with Playwright test runner.

### param: SnapshotAssertions.toMatchSnapshot#1.name
* since: v1.22
- `name` <[string]|[Array]<[string]>>

Snapshot name.

## method: SnapshotAssertions.toMatchSnapshot#2
* since: v1.22

Ensures that passed value, either a [string] or a [Buffer], matches the expected snapshot stored in the test snapshots directory.

**Usage**

```js
// Basic usage.
expect(await page.title()).toMatchSnapshot();

// Configure the snapshot name.
expect(await page.title()).toMatchSnapshot({
name: 'page-title.txt',
});
```

Note that matching snapshots only work with Playwright test runner.

### option: SnapshotAssertions.toMatchSnapshot#2.name
* since: v1.22
- `name` <[string]|[Array]<[string]>>

Snapshot name. If not passed, the test name and ordinals are used when called multiple times.



## method: SnapshotAssertions.toMatchSnapshot#3
* deprecated: To avoid flakiness, use [`method: PageAssertions.toHaveScreenshot#1`] instead.
* since: v1.22

Ensures that the passed [Buffer] matches the expected snapshot stored in the test snapshots directory.

**Usage**

```js
// Basic usage.
expect(await page.screenshot()).toMatchSnapshot('landing-page.png');
Expand All @@ -37,25 +92,26 @@ Learn more about [visual comparisons](../test-snapshots.md).

Note that matching snapshots only work with Playwright test runner.

### param: SnapshotAssertions.toMatchSnapshot#1.name
### param: SnapshotAssertions.toMatchSnapshot#3.name
* since: v1.22
- `name` <[string]|[Array]<[string]>>

Snapshot name.

### option: SnapshotAssertions.toMatchSnapshot#1.maxDiffPixels = %%-assertions-max-diff-pixels-%%
### option: SnapshotAssertions.toMatchSnapshot#3.maxDiffPixels = %%-assertions-max-diff-pixels-%%
* since: v1.22

### option: SnapshotAssertions.toMatchSnapshot#1.maxDiffPixelRatio = %%-assertions-max-diff-pixel-ratio-%%
### option: SnapshotAssertions.toMatchSnapshot#3.maxDiffPixelRatio = %%-assertions-max-diff-pixel-ratio-%%
* since: v1.22

### option: SnapshotAssertions.toMatchSnapshot#1.threshold = %%-assertions-threshold-%%
### option: SnapshotAssertions.toMatchSnapshot#3.threshold = %%-assertions-threshold-%%
* since: v1.22

## method: SnapshotAssertions.toMatchSnapshot#2
## method: SnapshotAssertions.toMatchSnapshot#4
* deprecated: To avoid flakiness, use [`method: PageAssertions.toHaveScreenshot#1`] instead.
* since: v1.22

Ensures that passed value, either a [string] or a [Buffer], matches the expected snapshot stored in the test snapshots directory.
Ensures that the passed [Buffer] matches the expected snapshot stored in the test snapshots directory.

**Usage**

Expand All @@ -79,17 +135,18 @@ Learn more about [visual comparisons](../test-snapshots.md).

Note that matching snapshots only work with Playwright test runner.

### option: SnapshotAssertions.toMatchSnapshot#2.maxDiffPixels = %%-assertions-max-diff-pixels-%%
### option: SnapshotAssertions.toMatchSnapshot#4.maxDiffPixels = %%-assertions-max-diff-pixels-%%
* since: v1.22

### option: SnapshotAssertions.toMatchSnapshot#2.maxDiffPixelRatio = %%-assertions-max-diff-pixel-ratio-%%
### option: SnapshotAssertions.toMatchSnapshot#4.maxDiffPixelRatio = %%-assertions-max-diff-pixel-ratio-%%
* since: v1.22

### option: SnapshotAssertions.toMatchSnapshot#2.name
### option: SnapshotAssertions.toMatchSnapshot#4.name
* since: v1.22
- `name` <[string]|[Array]<[string]>>

Snapshot name. If not passed, the test name and ordinals are used when called multiple times.

### option: SnapshotAssertions.toMatchSnapshot#2.threshold = %%-assertions-threshold-%%
### option: SnapshotAssertions.toMatchSnapshot#4.threshold = %%-assertions-threshold-%%
* since: v1.22

20 changes: 10 additions & 10 deletions docs/src/test-api/class-testconfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ export default defineConfig({
- type: ?<[Object]>
- `timeout` ?<[int]> Default timeout for async expect matchers in milliseconds, defaults to 5000ms.
- `toHaveScreenshot` ?<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot#1`] method.
- `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
- `threshold` ?<[float]> An acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> An acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
- `animations` ?<[ScreenshotAnimations]<"allow"|"disabled">> See [`option: animations`] in [`method: Page.screenshot`]. Defaults to `"disabled"`.
- `caret` ?<[ScreenshotCaret]<"hide"|"initial">> See [`option: caret`] in [`method: Page.screenshot`]. Defaults to `"hide"`.
- `scale` ?<[ScreenshotScale]<"css"|"device">> See [`option: scale`] in [`method: Page.screenshot`]. Defaults to `"css"`.
- `toMatchSnapshot` ?<[Object]> Configuration for the [`method: SnapshotAssertions.toMatchSnapshot#1`] method.
- `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
- `threshold` ?<[float]> **Deprecated.** An acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> **Deprecated.** An acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> **Deprecated.** An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.

Configuration for the `expect` assertion library. Learn more about [various timeouts](../test-timeouts.md).
Configuration for the `expect` assertion library. Learn more about [test configuration](../test-configuration.md#expect-options).

**Usage**

Expand All @@ -62,7 +62,7 @@ import { defineConfig } from '@playwright/test';
export default defineConfig({
expect: {
timeout: 10000,
toMatchSnapshot: {
toHaveScreenshot: {
maxDiffPixels: 10,
},
},
Expand Down Expand Up @@ -196,7 +196,7 @@ export default defineConfig({
* since: v1.26
- type: ?<[boolean]>

Whether to skip snapshot expectations, such as `expect(value).toMatchSnapshot()` and `await expect(page).toHaveScreenshot()`.
Whether to skip snapshot expectations, such as [`method: PageAssertions.toHaveScreenshot#1`] and [`method: SnapshotAssertions.toMatchSnapshot#1`].

**Usage**

Expand Down Expand Up @@ -296,7 +296,7 @@ test('example test', async ({}, testInfo) => {
* discouraged: Use [`property: TestConfig.snapshotPathTemplate`] to configure snapshot paths.
- type: ?<[string]>

The base directory, relative to the config file, for snapshot files created with `toMatchSnapshot`. Defaults to [`property: TestConfig.testDir`].
The base directory, relative to the config file, for screenshot files created with [`method: PageAssertions.toHaveScreenshot#1`]. Defaults to [`property: TestConfig.testDir`].

**Usage**

Expand Down
2 changes: 1 addition & 1 deletion docs/src/test-api/class-testinfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ Use of [`property: TestInfo.snapshotSuffix`] is discouraged. Please use [`proper
snapshot paths.
:::

Suffix used to differentiate snapshots between multiple test configurations. For example, if snapshots depend on the platform, you can set `testInfo.snapshotSuffix` equal to `process.platform`. In this case `expect(value).toMatchSnapshot(snapshotName)` will use different snapshots depending on the platform. Learn more about [snapshots](../test-snapshots.md).
Suffix used to differentiate snapshots between multiple test configurations. For example, if snapshots depend on the platform, you can set `testInfo.snapshotSuffix` equal to `process.platform`. In this case [`method: PageAssertions.toHaveScreenshot#1`] will use different snapshots depending on the platform. Learn more about [snapshots](../test-snapshots.md).

## property: TestInfo.status
* since: v1.10
Expand Down
12 changes: 6 additions & 6 deletions docs/src/test-api/class-testproject.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,16 @@ export default defineConfig({
- type: ?<[Object]>
- `timeout` ?<[int]> Default timeout for async expect matchers in milliseconds, defaults to 5000ms.
- `toHaveScreenshot` ?<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot#1`] method.
- `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
- `threshold` ?<[float]> An acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> An acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
- `animations` ?<[ScreenshotAnimations]<"allow"|"disabled">> See [`option: animations`] in [`method: Page.screenshot`]. Defaults to `"disabled"`.
- `caret` ?<[ScreenshotCaret]<"hide"|"initial">> See [`option: caret`] in [`method: Page.screenshot`]. Defaults to `"hide"`.
- `scale` ?<[ScreenshotScale]<"css"|"device">> See [`option: scale`] in [`method: Page.screenshot`]. Defaults to `"css"`.
- `toMatchSnapshot` ?<[Object]> Configuration for the [`method: SnapshotAssertions.toMatchSnapshot#1`] method.
- `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
- `threshold` ?<[float]> **Deprecated.** An acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
- `maxDiffPixels` ?<[int]> **Deprecated.** An acceptable amount of pixels that could be different, unset by default.
- `maxDiffPixelRatio` ?<[float]> **Deprecated.** An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.

Configuration for the `expect` assertion library.

Expand Down
1 change: 1 addition & 0 deletions docs/src/test-assertions-js.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Prefer [auto-retrying](#auto-retrying-assertions) assertions whenever possible.
| [`method: GenericAssertions.toHaveProperty`] | Object has a property |
| [`method: GenericAssertions.toMatch`] | String matches a regular expression |
| [`method: GenericAssertions.toMatchObject`] | Object contains specified properties |
| [`method: SnapshotAssertions.toMatchSnapshot#1`] | String equals a reference value, stored in a snapshot file |
| [`method: GenericAssertions.toStrictEqual`] | Value is similar, including property types |
| [`method: GenericAssertions.toThrow`] | Function throws an error |
| [`method: GenericAssertions.any`] | Matches any instance of a class/primitive |
Expand Down
11 changes: 2 additions & 9 deletions docs/src/test-configuration-js.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,22 +131,15 @@ export default defineConfig({
// An acceptable amount of pixels that could be different, unset by default.
maxDiffPixels: 10,
},

toMatchSnapshot: {
// An acceptable ratio of pixels that are different to the
// total amount of pixels, between 0 and 1.
maxDiffPixelRatio: 0.1,
},
},

});
```

| Option | Description |
| :- | :- |
| [`property: TestConfig.expect`] | [Web first assertions](./test-assertions.md) like `expect(locator).toHaveText()` have a separate timeout of 5 seconds by default. This is the maximum time the `expect()` should wait for the condition to be met. Learn more about [test and expect timeouts](./test-timeouts.md) and how to set them for a single test. |
| [`method: PageAssertions.toHaveScreenshot#1`] | Configuration for the `expect(locator).toHaveScreeshot()` method. |
| [`method: SnapshotAssertions.toMatchSnapshot#1`]| Configuration for the `expect(locator).toMatchSnapshot()` method.|
| `expect.timeout` | [Web first assertions](./test-assertions.md) like `expect(locator).toHaveText()` have a separate timeout of 5 seconds by default. This is the maximum time the `expect()` should wait for the condition to be met. Learn more about [test and expect timeouts](./test-timeouts.md) and how to set them for a single test. |
| `expect.toHaveScreenshot` | Configuration for [`method: PageAssertions.toHaveScreenshot#1`] and [`method: LocatorAssertions.toHaveScreenshot#1`] methods. |


### Add custom matchers using expect.extend
Expand Down
36 changes: 10 additions & 26 deletions docs/src/test-snapshots-js.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ When you run above for the first time, test runner will say:
Error: A snapshot doesn't exist at example.spec.ts-snapshots/example-test-1-chromium-darwin.png, writing actual.
```

That's because there was no golden file yet. This method took a bunch of screenshots until two consecutive
screenshots matched, and saved the last screenshot to file system. It is now ready to be added to the repository.
That's because there was no reference screenshot yet. This method took a bunch of screenshots until two consecutive
screenshots matched, and saved the last screenshot to file system. It is now ready to be added to the repository. You should review any changes to the reference screenshots to make sure they are expected.

The name of the folder with the golden expectations starts with the name of your test file:
The name of the folder with the reference screenshots starts with the name of your test file:

```bash
drwxr-xr-x 5 user group 160 Jun 4 11:46 .
Expand All @@ -32,31 +32,22 @@ drwxr-xr-x 6 user group 192 Jun 4 11:45 ..
drwxr-xr-x 3 user group 96 Jun 4 11:46 example.spec.ts-snapshots
```

The snapshot name `example-test-1-chromium-darwin.png` consists of a few parts:
The name of the reference screenshot `example-test-1-chromium-darwin.png` consists of a few parts:
- `example-test-1.png` - an auto-generated name of the snapshot. Alternatively you can specify snapshot name as the first argument of the `toHaveScreenshot()` method:
```js
await expect(page).toHaveScreenshot('landing.png');
```

- `chromium-darwin` - the browser name and the platform. Screenshots differ between browsers and platforms due to different rendering, fonts and more, so you will need different snapshots for them. If you use multiple projects in your [configuration file](./test-configuration.md), project name will be used instead of `chromium`.

If you are not on the same operating system as your CI system, you can use Docker to generate/update the screenshots:

```bash
docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v%%VERSION%%-jammy /bin/bash
npm install
npx playwright test --update-snapshots
```
You can customize the name and the path of the reference screnshot by modifying [`property: TestProject.snapshotPathTemplate`] property in the config file.

Sometimes you need to update the reference screenshot, for example when the page has changed. Do this with the `--update-snapshots` flag.

```bash
npx playwright test --update-snapshots
```

> Note that `snapshotName` also accepts an array of path segments to the snapshot file such as `expect().toHaveScreenshot(['relative', 'path', 'to', 'snapshot.png'])`.
> However, this path must stay within the snapshots directory for each test file (i.e. `a.spec.js-snapshots`), otherwise it will throw.
Playwright Test uses the [pixelmatch](https://github.com/mapbox/pixelmatch) library. You can [pass various options](./api/class-pageassertions.md#page-assertions-to-have-screenshot-1) to modify its behavior:

```js title="example.spec.ts"
Expand All @@ -79,17 +70,10 @@ export default defineConfig({
});
```

Apart from screenshots, you can use `expect(value).toMatchSnapshot(snapshotName)` to compare text or arbitrary binary data. Playwright Test auto-detects the content type and uses the appropriate comparison algorithm.

Here we compare text content against the reference.

```js title="example.spec.ts"
import { test, expect } from '@playwright/test';
If you are not on the same operating system as your CI system, you can use Docker to generate/update the screenshots:

test('example test', async ({ page }) => {
await page.goto('https://playwright.dev');
expect(await page.textContent('.hero__title')).toMatchSnapshot('hero.txt');
});
```bash
docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v%%VERSION%%-jammy /bin/bash
npm install
npx playwright test --update-snapshots
```

Snapshots are stored next to the test file, in a separate directory. For example, `my.spec.ts` file will produce and store snapshots in the `my.spec.ts-snapshots` directory. You should commit this directory to your version control (e.g. `git`), and review any changes to it.

0 comments on commit 8348f66

Please sign in to comment.