Jest snapshot testing utilities that enable capturing component output, API responses, or any serializable values as snapshots for regression testing and change detection
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Pluggable serialization system for customizing how values are converted to snapshot strings. Supports built-in serializers for common data types and custom serializers for domain-specific objects.
Functions for managing snapshot serialization plugins that control how different types of values are converted to string representations.
/**
* Adds a custom serializer plugin to the beginning of the plugin list
* Plugins added later take precedence over earlier ones
* @param plugin - PrettyFormat plugin for custom serialization
*/
function addSerializer(plugin: PrettyFormatPlugin): void;
/**
* Gets all registered serializer plugins in priority order
* @returns Array of all registered plugins, with custom plugins first
*/
function getSerializers(): PrettyFormatPlugins;
type PrettyFormatPlugin = {
test: (val: unknown) => boolean;
serialize: (
val: unknown,
config: Config,
indentation: string,
depth: number,
refs: Refs,
printer: Printer
) => string;
};
type PrettyFormatPlugins = Array<PrettyFormatPlugin>;Usage Examples:
import { addSerializer, getSerializers } from "jest-snapshot";
// Custom serializer for Date objects
const dateSerializer = {
test: (val) => val instanceof Date,
serialize: (val) => `Date("${val.toISOString()}")`
};
addSerializer(dateSerializer);
// Custom serializer for database models
const modelSerializer = {
test: (val) => val && typeof val === 'object' && val.constructor.name === 'User',
serialize: (val, config, indentation, depth, refs, printer) => {
return `User(${printer(val.id, config, indentation, depth, refs)})`;
}
};
addSerializer(modelSerializer);
// Get all serializers (custom ones first)
const allSerializers = getSerializers();
console.log(allSerializers.length); // Built-in + custom serializersJest Snapshot includes several built-in serializers that handle common data types:
React Components:
ReactElement - Serializes React elements and JSXReactTestComponent - Handles React test renderer componentsDOM Elements:
DOMElement - Serializes DOM nodes and HTML elementsDOMCollection - Handles NodeLists, HTMLCollections, etc.Data Structures:
Immutable - Serializes Immutable.js data structuresAsymmetricMatcher - Handles Jest's expect.any(), expect.objectContaining(), etc.Jest Specific:
jestMockSerializer - Serializes Jest mock functions with call informationCreate custom serializers for domain-specific objects or to customize existing type serialization:
// Custom serializer for URL objects
const urlSerializer = {
test: (val) => val instanceof URL,
serialize: (val) => `URL("${val.href}")`
};
addSerializer(urlSerializer);
// Before: URL { href: "https://example.com", protocol: "https:", ... }
// After: URL("https://example.com")
// Custom serializer for Error objects with stack traces
const errorSerializer = {
test: (val) => val instanceof Error,
serialize: (val, config, indentation, depth, refs, printer) => {
const name = val.constructor.name;
const message = val.message;
const stack = val.stack ? `\n${val.stack}` : '';
return `${name}: ${message}${stack}`;
}
};
addSerializer(errorSerializer);
// Complex custom serializer with nested printing
const apiResponseSerializer = {
test: (val) => val && typeof val === 'object' && val.type === 'api-response',
serialize: (val, config, indentation, depth, refs, printer) => {
const status = val.status;
const data = printer(val.data, config, indentation, depth, refs);
return `ApiResponse(${status}) ${data}`;
}
};
addSerializer(apiResponseSerializer);Serializers are tested in order, with the first matching serializer being used:
// Order matters - first matching test() wins
addSerializer(specificSerializer); // Added last, tested first
addSerializer(generalSerializer); // Added earlier, tested later
// Built-in serializers are tested after all custom serializers
// Default object/primitive serialization happens lastSerializers include a test function that determines whether they should handle a specific value:
const customSerializer = {
// Test function - return true to handle this value
test: (val) => {
return val &&
typeof val === 'object' &&
val.constructor.name === 'CustomClass' &&
typeof val.serialize === 'function';
},
// Serialize function - convert value to string
serialize: (val, config, indentation, depth, refs, printer) => {
// Use the object's own serialize method
return val.serialize();
}
};Nested Object Printing: Use the printer function to serialize nested values:
const wrapperSerializer = {
test: (val) => val && val.type === 'wrapper',
serialize: (val, config, indentation, depth, refs, printer) => {
// Use printer for nested values to maintain formatting
const content = printer(val.content, config, indentation, depth, refs);
return `Wrapper(${content})`;
}
};Depth and Reference Handling: Handle circular references and depth limits:
const circularSafeSerializer = {
test: (val) => val && val.type === 'node',
serialize: (val, config, indentation, depth, refs, printer) => {
if (depth > 5) {
return '[Deep Object]';
}
const children = val.children.map(child =>
printer(child, config, indentation, depth + 1, refs)
);
return `Node(${children.join(', ')})`;
}
};Configuration-aware Serialization: Access pretty-format configuration:
const configAwareSerializer = {
test: (val) => val instanceof Map,
serialize: (val, config, indentation, depth, refs, printer) => {
const entries = Array.from(val.entries());
if (config.min) {
// Compact format for min config
return `Map(${entries.length})`;
}
// Full format
const items = entries.map(([key, value]) => {
const k = printer(key, config, indentation, depth, refs);
const v = printer(value, config, indentation, depth, refs);
return `${k} => ${v}`;
});
return `Map {\n${indentation} ${items.join(`,\n${indentation} `)}\n${indentation}}`;
}
};There's currently no built-in way to remove serializers, but you can work around this:
// Get current serializers
const currentSerializers = getSerializers();
// Find built-in serializers (after your custom ones)
const builtInSerializers = currentSerializers.slice(customSerializerCount);
// Clear and re-add only desired serializers
// (This is a workaround - not officially supported)Serializers work with Jest's snapshot formatting options:
// Snapshot format affects serializer output
const snapshotFormat = {
indent: 2,
printWidth: 80,
min: false,
escapeRegex: false,
escapeString: true,
plugins: getSerializers() // Your custom serializers included
};interface PrettyFormatPlugin {
test: (val: unknown) => boolean;
serialize: (
val: unknown,
config: Config,
indentation: string,
depth: number,
refs: Refs,
printer: Printer
) => string;
}
type PrettyFormatPlugins = Array<PrettyFormatPlugin>;
type Config = {
callToJSON: boolean;
compareKeys: undefined;
escapeRegex: boolean;
escapeString: boolean;
highlight: boolean;
indent: string;
maxDepth: number;
min: boolean;
plugins: PrettyFormatPlugins;
printBasicPrototype: boolean;
printFunctionName: boolean;
spacingInner: string;
spacingOuter: string;
theme: Theme;
};
type Printer = (
val: unknown,
config: Config,
indentation: string,
depth: number,
refs: Refs
) => string;
type Refs = Set<unknown>;
interface Theme {
comment: string;
content: string;
prop: string;
tag: string;
value: string;
}