Jest Snapshot Diffing Utility
snapshot-diff is a utility library for Jest that facilitates the creation of diff snapshots between two values, particularly useful for comparing states of React components. The current stable version is 0.10.0. The library's release cadence is tightly coupled with Jest's major releases, leading to frequent breaking changes primarily due to updates in its Jest peer dependencies. It offers both a direct `snapshotDiff` function and a custom Jest matcher, `toMatchDiffSnapshot`, to integrate seamlessly into Jest tests. A key differentiator is its ability to provide readable, Git-style diff output for complex data structures by leveraging Jest's serialization mechanisms and supporting custom serializers.
Common errors
-
TypeError: expect.extend is not a function
cause The Jest `expect` object was not correctly extended with the `toMatchDiffSnapshot` custom matcher.fixEnsure you either `import { toMatchDiffSnapshot } from 'snapshot-diff'; expect.extend({ toMatchDiffSnapshot });` or `import 'snapshot-diff/extend-expect';` in your Jest setup file or relevant test files. -
Invariant Violation: `ReactTestRenderer` is a dependency of `react-test-renderer`
cause This error typically occurs when React Test Renderer dependencies are misconfigured or multiple versions exist, often in conjunction with snapshot testing utilities.fixEnsure `react-test-renderer` is correctly installed as a development dependency. If using Yarn or PNPM, check for hoisted dependencies or use `resolutions` to enforce a single version. Clearing `node_modules` and `package-lock.json`/`yarn.lock` and reinstalling often resolves this. -
TS2307: Cannot find module 'snapshot-diff' or its corresponding type declarations.
cause TypeScript compiler cannot locate the package's type definitions.fixEnsure `snapshot-diff` is installed and that `@types/jest` (if Jest is a peer dependency) is also installed. Verify your `tsconfig.json` includes `node_modules/@types` in `typeRoots` and `types` arrays are correctly configured, or that it is implicitly picked up. -
Error: Jest: a snapshot serializer must be an object with a `print` method.
cause A custom serializer provided to `expect.addSnapshotSerializer` or `snapshotDiff.setSerializers` does not conform to Jest's `SnapshotSerializer` interface.fixReview your custom serializer implementation. It must export an object with at least `test` and `print` methods, and optionally `serialize` and `deserialize`.
Warnings
- breaking snapshot-diff frequently introduces breaking changes tied to Jest major version upgrades. Always check the release notes when updating `jest` or `snapshot-diff` as peer dependency ranges often tighten.
- breaking TypeScript users experienced breaking changes in type definitions due to updates to `@types/jest` and internal type refactorings.
- gotcha Jest's default snapshot serialization can add extra quotes around string diffs, making output noisy and less readable. `snapshot-diff` provides a specific serializer to address this.
- gotcha When setting custom serializers with `setSerializers`, the default React serializer is replaced. If you intend to diff React components, you must explicitly include `defaultSerializers`.
Install
-
npm install snapshot-diff -
yarn add snapshot-diff -
pnpm add snapshot-diff
Imports
- snapshotDiff
import { snapshotDiff } from 'snapshot-diff';import snapshotDiff from 'snapshot-diff';
- toMatchDiffSnapshot
import toMatchDiffSnapshot from 'snapshot-diff';
import { toMatchDiffSnapshot } from 'snapshot-diff'; - extend-expect (side-effect)
require('snapshot-diff/extend-expect');import 'snapshot-diff/extend-expect';
- getSnapshotDiffSerializer
const { getSnapshotDiffSerializer } = require('snapshot-diff');import { getSnapshotDiffSerializer } from 'snapshot-diff'; - defaultSerializers
const { defaultSerializers } = require('snapshot-diff');import { defaultSerializers } from 'snapshot-diff';
Quickstart
import React from 'react';
import { toMatchDiffSnapshot, getSnapshotDiffSerializer } from 'snapshot-diff';
// Extend Jest's expect with the custom matcher
expect.extend({ toMatchDiffSnapshot });
// Add the custom serializer to prevent extra quotes in snapshots
expect.addSnapshotSerializer(getSnapshotDiffSerializer());
// Define a simple React component for demonstration
interface ComponentProps {
value: string;
}
const MyComponent: React.FC<ComponentProps> = ({ value }) => {
return (
<div>
<p>Current value: {value}</p>
<button onClick={() => console.log('clicked')}>Click Me</button>
</div>
);
};
describe('snapshot-diff usage', () => {
test('should diff changes in React component props', () => {
const initialElement = <MyComponent value="initial" />;
const updatedElement = <MyComponent value="changed" />;
// Compare the two React elements directly with the custom matcher
expect(initialElement).toMatchDiffSnapshot(updatedElement);
});
test('should diff differences between two strings', () => {
const stringA = 'The quick brown fox jumps over the lazy dog.';
const stringB = 'The quick red fox jumps over the sleeping cat.';
// Compare two strings directly
expect(stringA).toMatchDiffSnapshot(stringB);
});
test('should diff two plain objects', () => {
const objA = { id: 1, name: 'Alice', age: 30 };
const objB = { id: 1, name: 'Alicia', age: 31, city: 'NY' };
// Compare two plain objects
expect(objA).toMatchDiffSnapshot(objB);
});
});