npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cronn/playwright-file-snapshots

v0.38.1

Published

Write tests with Playwright using file snapshots

Readme

playwright-file-snapshots

Write tests with Playwright using file snapshots.

Motivation

Classical assertions in Playwright typically assert only specific aspects of a page considered relevant for the current test. Complex assertions are usually cumbersome to write and hard to maintain. Also, regressions caused by side effects might be introduced unnoticed, because assertions focus only on what's expected to change after a user interaction.

File snapshots can help to increase test coverage by enabling assertions which cover larger portions of a tested page. playwright-file-snapshots provide custom matchers for snapshot testing with the following features:

  • Zero configuration: snapshot files are named based on the test name
  • Multiple snapshot formats: JSON, text
  • Snapshot retries: avoid flaky tests by retrying snapshots
  • ARIA and element snapshots: Achieve high test coverage by snapshotting the semantical structure and accessible contents of a page

Getting Started

Adding the library to your project

npm install -D @cronn/playwright-file-snapshots
yarn add -D @cronn/playwright-file-snapshots
pnpm add -D @cronn/playwright-file-snapshots

Using the Custom Matchers in your project

Define the Custom Matchers as a reusable export (e.g. in fixtures.ts):

import { defineValidationFileExpect } from "@cronn/playwright-file-snapshots";

export const expect = defineValidationFileExpect();

Then import your custom expect instead of Playwright's base expect in your tests:

import { test } from "@playwright/test";

import { expect } from "./fixtures";

test("matches JSON file", async () => {
  const snapshot = "…";
  await expect(snapshot).toMatchJsonFile();
});

If you are already using other custom matchers, you can merge them with the validation file matchers:

import { mergeExpects, mergeTests } from "@playwright/test";

import { defineValidationFileExpect } from "@cronn/playwright-file-snapshots";

const expect = mergeExpects(defineValidationFileExpect(), otherExpect);

Adding output files to .gitignore

All file snapshots are generated to /data/test. The golden masters will be stored in /data/test/validation, which should be under version control. The file snapshots generated for test runs will be stored under /data/test/output and should be ignored:

# file snapshots
/data/test/output

Writing Tests

File snapshot assertions use one of the custom matchers:

  • toMatchJsonFile
  • toMatchTextFile

JSON File Snapshot

test("value is expected value", async () => {
  await expect({ value: "expected value" }).toMatchJsonFile();
});

// value_is_expected_value.json
// {
//   "value": "expected value"
// }

Text File Snapshot

test("value is expected value", async () => {
  await expect("expected value").toMatchTextFile();
});

// value_is_expected_value.txt
// expected value

Normalization of Snapshots

Normalizers can be used to apply custom normalization, e.g. mask values which are not stable. Custom normalizers are applied before internal normalizers and the snapshot serialization.

function maskDate(value: unknown): unknown {
  if (value instanceof Date) {
    return "[DATE]";
  }

  return value;
}

test("date is masked", async () => {
  await expect({ date: new Date() }).toMatchJsonFile({
    normalizers: [maskDate],
  });
});

// date_is_masked.json
// {
//   "date": "[DATE]"
// }

Named Snapshots

By default, the name of a file snapshot is automatically derived from the hierarchy of test titles, including test.describe, test and test.step. When using multiple file snapshot matchers in the same test context, it's necessary to define a unique name for the snapshot.

test("named snapshots", async () => {
  // named_snapshots/snapshot_1.txt
  await expect("value 1").toMatchTextFile({ name: "snapshot 1" });
  // named_snapshots/snapshot_2.txt
  await expect("value 2").toMatchTextFile({ name: "snapshot 2" });
});

By default, all named snapshots are stored as separate files in the same directory, which is determined by the test context.

To change this behavior, you can use a different file path resolver:

import { resolveNameAsFileSuffix } from "@cronn/playwright-file-snapshots";

test("named snapshots", async () => {
  // named_snapshots_snapshot_name.txt
  await expect("value 1").toMatchTextFile({
    name: "snapshot name",
    resolveFilePath: resolveNameAsFileSuffix,
  });
});

Snapshot Retries

All file snapshot assertions support retries, inspired by Playwright's existing retry mechanism. In order to enable snapshot retries, pass a callback as actual value:

test("retry snapshot", async ({ page }) => {
  await expect(() => page.getByRole("main").textContent()).toMatchTextFile();
});

By default, Playwright's Expect timeout (5 s) is used. To define a custom timeout, pass the timeout option to the matcher:

test("retry snapshot", async ({ page }) => {
  await expect(() => page.getByRole("main").textContent()).toMatchTextFile({
    timeout: 500,
  });
});

When creating missing file snapshots, instead of retrying a delay of 250 ms (or timeout when lower) is added before performing the snapshot. This avoids flaky snapshots and long-running tests. The same behavior is used when updating snapshots.

The default delay can be overridden by defining updateDelay as matcher or file snapshot option.

Using Soft Assertions

We recommend to use soft assertions for all file snapshot matchers. This prevents tests from terminating early when a file snapshot cannot be matched, making the process of reviewing failed test runs more efficient.

Enabling Soft Assertions for Individual Assertions

test("match values using soft assertions", async () => {
  await expect.soft({ value: "value 1" }).toMatchJsonFile();
  await expect.soft({ value: "value 2" }).toMatchJsonFile();
});

Enabling Soft Assertions for All Matchers

export const expect = defineValidationFileExpect().configure({
  soft: true,
});

[!NOTE] Enabling soft assertions for all matchers may have unintended side effects if you are using matchers like expect.toPass.

Snapshot Implementations

ARIA Snapshots

ARIA Snapshots are a JSON-based adapter for Playwright's YAML-based ARIA Snapshots. They facilitate snapshot composition using a format natively supported by JavaScript.

import { snapshotAria } from "@cronn/aria-snapshot";

test("matches ARIA snapshot", async ({ page }) => {
  await expect(snapshotAria(page.getByRole("main"))).toMatchJsonFile();
});

ARIA Snapshot Example:

{
  "main": [
    "heading 'List' [level=1]",
    {
      "list": [
        {
          "listitem": "Apple"
        },
        {
          "listitem": "Peach"
        }
      ]
    }
  ]
}

Element Snapshots

Element Snapshots are an alternative to ARIA Snapshots, providing a higher coverage of HTML and ARIA attributes as well as the ability to implement custom snapshots, e.g. for Markdown Tables.

import { snapshotElement } from "@cronn/element-snapshot";

test("matches element snapshot", async ({ page }) => {
  await expect(snapshotElement(page.getByRole("main"))).toMatchJsonFile();
});

Element Snapshot Example:

{
  "main": [
    {
      "heading": {
        "name": "List",
        "level": 1
      }
    },
    {
      "list": [
        {
          "listitem": "Apple"
        },
        {
          "listitem": "Peach"
        }
      ]
    }
  ]
}

Configuration

Matcher Options

Matcher options can be passed when defining the matcher:

import { defineValidationFileExpect } from "@cronn/playwright-file-snapshots";

const expect = defineValidationFileExpect({
  validationDir: "custom-validation",
  outputDir: "custom-output",
});

| Option | Default Value | Description | | ----------------- | ---------------------- | ------------------------------------------------------------------- | | validationDir | data/test/validation | Directory in which golden masters are stored. | | outputDir | data/test/output | Directory in which file snapshots from test runs are stored. | | indentSize | 2 | Indentation size in spaces used for serializing snapshots. | | resolveFileName | resolveNameAsFile | Custom resolver for the file path used to store snapshots. | | updateDelay | 250 | Delay in ms before repeatable snapshots are created in update mode. |

File Snapshot Options

Snapshot options can be passed whenever calling the validation file matcher:

await expect(value).toMatchTextFile({
  name: "snapshot",
});

| Option | Default Value | Description | | ----------------- | ------------------- | ------------------------------------------------------------------------------------------------------- | | name | undefined | Unique name of the file snapshot. Used to distinguish multiple file snapshots within the same test. | | normalizers | [] | Custom normalizers to apply before serialization. | | timeout | expect timeout | Retries the snapshot until it passes or the timeout value is reached. | | resolveFileName | resolveNameAsFile | Custom resolver for the file path used to store snapshots. | | updateDelay | 250 | Delay in ms before repeatable snapshots are created in update mode. |

JSON Snapshot Options

| Option | Default Value | Description | | ---------------------------------- | ------------- | --------------------------------------------------------------------------- | | includeUndefinedObjectProperties | false | Serializes undefined properties in objects. By default, they are omitted. |

Text Snapshot Options

| Option | Default Value | Description | | --------------- | ------------- | ---------------------------------------------- | | fileExtension | txt | File extension used for storing the text file. |

Updating Snapshots

Snapshots can be updated using Playwright's built-in support for snapshot updates:

  • Using the CLI parameter --update-snapshots [mode]
  • Configuring the Testing Option "Update snapshots" in the Playwright Test UI
  • Configuring the option updateSnapshots in your playwright.config.ts

By default, only missing validation files are written. Using the values all or changed, existing validation files will also be overridden.

[!NOTE] If you accidentally updated more snapshots than intended, you can revert the changes using your VCS and selectively apply updates by diffing the validation and output directories.