A set of utility functions for expect and related packages
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Functions for comparing values and generating visual diffs for test output, helping developers understand exactly how expected and received values differ.
Generates diff output between two values when appropriate, with automatic detection of diffable types.
/**
* Generate diff between two values
* @param a - First value to compare
* @param b - Second value to compare
* @param options - Diff generation options
* @returns Diff output string or null if not diffable
*/
function diff(
a: unknown,
b: unknown,
options?: DiffOptions
): string | null;
type DiffOptions = {
aAnnotation?: string;
bAnnotation?: string;
changeColor?: (arg: string) => string;
changeLineTrailingSpaceColor?: (arg: string) => string;
commonColor?: (arg: string) => string;
commonLineTrailingSpaceColor?: (arg: string) => string;
contextLines?: number;
expand?: boolean;
includeChangeCounts?: boolean;
omitAnnotationLines?: boolean;
patchColor?: (arg: string) => string;
};Usage Examples:
import { diff } from "jest-matcher-utils";
// Basic object diff
const expected = { name: "Alice", age: 25, city: "NYC" };
const received = { name: "Alice", age: 30, city: "LA" };
const diffResult = diff(expected, received);
// Result: Colorized diff showing changed properties
// Array diff
const expectedArray = [1, 2, 3, 4];
const receivedArray = [1, 2, 5, 4];
const arrayDiff = diff(expectedArray, receivedArray);
// Result: Shows element differences
// String diff
const expectedText = "Hello world";
const receivedText = "Hello earth";
const textDiff = diff(expectedText, receivedText);
// Result: Character-level diff highlighting changes
// Returns null for non-diffable types
const numDiff = diff(5, 10);
// Result: null (numbers don't generate useful diffs)
// With options
const customDiff = diff(expected, received, {
expand: true,
includeChangeCounts: true
});Generates comprehensive diff output or falls back to stringified comparison when diff is not useful.
/**
* Generate diff output or stringify values for comparison
* @param expected - Expected value
* @param received - Received value
* @param expectedLabel - Label for expected value
* @param receivedLabel - Label for received value
* @param expand - Whether to expand diff output
* @returns Formatted diff or comparison string
*/
function printDiffOrStringify(
expected: unknown,
received: unknown,
expectedLabel: string,
receivedLabel: string,
expand: boolean
): string;Usage Examples:
import { printDiffOrStringify } from "jest-matcher-utils";
// Object comparison with labels
const expected = { user: "Alice", role: "admin" };
const received = { user: "Alice", role: "user" };
const comparison = printDiffOrStringify(
expected,
received,
"Expected",
"Received",
false
);
// Result: Labeled diff output showing role change
// String comparison with multiline
const expectedText = `Line 1
Line 2
Line 3`;
const receivedText = `Line 1
Modified Line 2
Line 3`;
const textComparison = printDiffOrStringify(
expectedText,
receivedText,
"Expected",
"Received",
true // expanded output
);
// Result: Unified diff format with line numbers
// Falls back to stringify for incomparable types
const numComparison = printDiffOrStringify(
42,
43,
"Expected",
"Received",
false
);
// Result: 'Expected: 42\nReceived: 43'
// Handles identical values that serialize differently
const date1 = new Date('2024-01-01');
const date2 = new Date('2024-01-01');
const sameComparison = printDiffOrStringify(
date1,
date2,
"Expected",
"Received",
false
);
// Result: 'Expected: ...\nReceived: serializes to the same string'Advanced function for replacing matched values with asymmetric matchers during comparison, handling Jest's expect.any(), expect.objectContaining(), etc.
/**
* Replace matched values with asymmetric matchers for comparison
* @param replacedExpected - Expected value to process
* @param replacedReceived - Received value to process
* @param expectedCycles - Cycle detection for expected value
* @param receivedCycles - Cycle detection for received value
* @returns Object with processed expected and received values
*/
function replaceMatchedToAsymmetricMatcher(
replacedExpected: unknown,
replacedReceived: unknown,
expectedCycles: Array<unknown>,
receivedCycles: Array<unknown>
): {replacedExpected: unknown; replacedReceived: unknown};Usage Examples:
import { replaceMatchedToAsymmetricMatcher } from "jest-matcher-utils";
// Handle asymmetric matchers in expected values
const expected = {
id: expect.any(Number),
name: "Alice",
metadata: expect.objectContaining({ version: "1.0" })
};
const received = {
id: 123,
name: "Alice",
metadata: { version: "1.0", extra: "data" }
};
const {replacedExpected, replacedReceived} = replaceMatchedToAsymmetricMatcher(
expected,
received,
[], // expectedCycles
[] // receivedCycles
);
// Result: Asymmetric matchers that match are replaced in received,
// making diff output cleaner by showing what actually differs
// Handles circular references
const circular = { prop: null };
circular.prop = circular;
const processed = replaceMatchedToAsymmetricMatcher(
circular,
{ prop: { prop: "different" } },
[circular], // Track circular reference
[]
);
// Prevents infinite recursion during processing
// Used internally by Jest matchers
function customMatcher(received: unknown, expected: unknown) {
const {replacedExpected, replacedReceived} = replaceMatchedToAsymmetricMatcher(
expected,
received,
[],
[]
);
// Generate cleaner diff with processed values
const diffOutput = diff(replacedExpected, replacedReceived);
return diffOutput;
}The diff generation system uses intelligent strategies:
String Diffs: Character-level and line-level diffs for strings
Object/Array Diffs: Structured comparison
Type-Based Logic: Different approaches per type
Asymmetric Matcher Support:
Performance Limits:
The system automatically chooses the most informative representation for any value comparison, ensuring developers get the clearest possible view of test failures.