Automated Jest snapshot testing addon for Storybook stories across multiple frameworks
—
Story-to-snapshot file conversion system with configurable naming conventions and directory structures. The Stories2SnapsConverter class handles the mapping between story files and their corresponding snapshot files.
Handles conversion between story files and snapshot files with configurable options.
/**
* Converts between story files and snapshot files
* @param options - Configuration options for file conversion
*/
class Stories2SnapsConverter {
constructor(options?: Partial<Stories2SnapsConverterOptions>);
/** Get the snapshot file extension */
getSnapshotExtension(): string;
/** Convert story file path to snapshot file path */
getStoryshotFile(fileName: string): string;
/** Get snapshot filename from story context */
getSnapshotFileName(context: { fileName?: string; kind: any }): string | undefined;
/** Get possible story files from snapshot file path */
getPossibleStoriesFiles(storyshotFile: string): string[];
}Usage Examples:
import { Stories2SnapsConverter } from "@storybook/addon-storyshots";
// Default configuration
const converter = new Stories2SnapsConverter();
// Custom configuration
const customConverter = new Stories2SnapsConverter({
snapshotExtension: ".snap",
snapshotsDirName: "snapshots",
storiesExtensions: [".js", ".jsx", ".ts", ".tsx"]
});
// Use with initStoryshots
import initStoryshots from "@storybook/addon-storyshots";
initStoryshots({
stories2snapsConverter: customConverter
});Configure file naming and directory conventions.
interface Stories2SnapsConverterOptions {
/** Supported story file extensions */
storiesExtensions: string[]; // Default: ['.js', '.jsx', '.ts', '.tsx', '.mdx']
/** Snapshot file extension */
snapshotExtension: string; // Default: '.storyshot'
/** Snapshot directory name */
snapshotsDirName: string; // Default: '__snapshots__'
}Default Options:
const defaultOptions = {
snapshotsDirName: "__snapshots__",
snapshotExtension: ".storyshot",
storiesExtensions: [".js", ".jsx", ".ts", ".tsx", ".mdx"]
};Returns the configured snapshot file extension.
/**
* Get the snapshot file extension
* @returns Snapshot extension string
*/
getSnapshotExtension(): string;Usage Example:
const converter = new Stories2SnapsConverter({
snapshotExtension: ".snap"
});
console.log(converter.getSnapshotExtension()); // ".snap"Converts a story file path to its corresponding snapshot file path.
/**
* Convert story file path to snapshot file path
* @param fileName - Path to the story file
* @returns Path to the corresponding snapshot file
*/
getStoryshotFile(fileName: string): string;Usage Examples:
const converter = new Stories2SnapsConverter();
// Convert relative path
const snapshotPath = converter.getStoryshotFile("components/Button.stories.js");
// Returns: "components/__snapshots__/Button.storyshot"
// Convert absolute path
const absolutePath = converter.getStoryshotFile("/project/src/Button.stories.tsx");
// Returns: "/project/src/__snapshots__/Button.storyshot"Gets snapshot filename from story context, used for multi-snapshot testing.
/**
* Get snapshot filename from story context
* @param context - Story context containing fileName and kind
* @returns Snapshot filename or undefined if no fileName available
*/
getSnapshotFileName(context: { fileName?: string; kind: any }): string | undefined;Usage Examples:
const converter = new Stories2SnapsConverter();
// With filename in context
const context1 = {
fileName: "/project/src/Button.stories.js",
kind: "Button"
};
const filename1 = converter.getSnapshotFileName(context1);
// Returns: "/project/src/__snapshots__/Button.storyshot"
// Without filename (will log warning)
const context2 = {
kind: "Button"
};
const filename2 = converter.getSnapshotFileName(context2);
// Returns: undefined
// Logs warning about missing filenameGets possible story file paths from a snapshot file path.
/**
* Get possible story files from snapshot file path
* @param storyshotFile - Path to snapshot file
* @returns Array of possible story file paths
*/
getPossibleStoriesFiles(storyshotFile: string): string[];Usage Example:
const converter = new Stories2SnapsConverter();
const snapshotFile = "/project/src/__snapshots__/Button.storyshot";
const possibleStories = converter.getPossibleStoriesFiles(snapshotFile);
// Returns:
// [
// "/project/src/Button.js",
// "/project/src/Button.jsx",
// "/project/src/Button.ts",
// "/project/src/Button.tsx",
// "/project/src/Button.mdx"
// ]Different configurations produce different file structures:
Default Configuration:
src/
├── components/
│ ├── Button.stories.js
│ └── __snapshots__/
│ └── Button.storyshotCustom Configuration:
new Stories2SnapsConverter({
snapshotsDirName: "tests/snapshots",
snapshotExtension: ".snap"
});src/
├── components/
│ ├── Button.stories.js
│ └── tests/
│ └── snapshots/
│ └── Button.snapFor proper filename detection, configure Jest transform:
// jest.config.js
module.exports = {
transform: {
// Must be before other JS transforms
"^.+\\.stories\\.(js|jsx|ts|tsx)$": "@storybook/addon-storyshots/injectFileName",
"^.+\\.(js|jsx|ts|tsx)$": "babel-jest",
},
};The injectFileName transform adds filename metadata to story exports:
// Automatically injected by transform
exports.default.parameters = exports.default.parameters || {};
exports.default.parameters.fileName = '/absolute/path/to/Story.stories.js';File converter supports integrity testing to ensure snapshot-story consistency:
import initStoryshots, { multiSnapshotWithOptions } from "@storybook/addon-storyshots";
initStoryshots({
test: multiSnapshotWithOptions(),
integrityOptions: {
cwd: __dirname,
ignore: ["**/deprecated/**"]
},
stories2snapsConverter: new Stories2SnapsConverter({
snapshotExtension: ".snap"
})
});This verifies that:
Install with Tessl CLI
npx tessl i tessl/npm-storybook--addon-storyshots