Testing utilities that allow you to reuse your stories in your unit tests
npx @tessl/cli install tessl/npm-storybook--testing-react@2.0.0Storybook Testing React provides testing utilities that allow you to reuse your existing Storybook stories directly in unit tests. It enables developers to leverage their story scenarios as test cases, automatically applying all decorators, parameters, and global configurations from story-level, meta-level, and global-level contexts.
npm install --save-dev @storybook/testing-reactimport { composeStory, composeStories, setProjectAnnotations } from "@storybook/testing-react";For CommonJS:
const { composeStory, composeStories, setProjectAnnotations } = require("@storybook/testing-react");import { render, screen } from "@testing-library/react";
import { composeStories } from "@storybook/testing-react";
import * as stories from "./Button.stories";
// Compose all stories from the stories file
const { Primary, Secondary } = composeStories(stories);
test("renders primary button with default args", () => {
render(<Primary />);
const buttonElement = screen.getByRole("button");
expect(buttonElement).toBeInTheDocument();
});
test("renders primary button with custom props", () => {
render(<Primary onClick={jest.fn()}>Custom Text</Primary>);
const buttonElement = screen.getByText("Custom Text");
expect(buttonElement).toBeInTheDocument();
});Storybook Testing React is built around several key concepts:
Core functionality for converting individual stories or entire story files into testable React components with all configurations applied.
function composeStory<GenericArgs extends Args>(
story: TestingStory<GenericArgs>,
meta: ComponentAnnotations<ReactRenderer>,
globalConfig?: ProjectAnnotations<ReactRenderer>
): ComposedStory<GenericArgs>;
function composeStories<TModule extends StoryFile>(
storiesImport: TModule,
globalConfig?: ProjectAnnotations<ReactRenderer>
): StoriesWithPartialProps<TModule>;Setup functions for applying global Storybook configuration (decorators, parameters, etc.) to all composed stories.
function setProjectAnnotations(
projectAnnotations: ProjectAnnotations<ReactRenderer> | ProjectAnnotations<ReactRenderer>[]
): void;
function setGlobalConfig(
projectAnnotations: ProjectAnnotations<ReactRenderer> | ProjectAnnotations<ReactRenderer>[]
): void;Note: setGlobalConfig is deprecated - use setProjectAnnotations instead.
type TestingStory<TArgs = Args> = StoryAnnotations<ReactRenderer, TArgs>;
type StoryFile = Store_CSFExports<ReactRenderer, any>;
type StoriesWithPartialProps<T> = {
[K in keyof T]: T[K] extends StoryAnnotations<ReactRenderer, infer P>
? ComposedStory<Partial<P>>
: number;
};
type ComposedStory<TArgs = Args> = {
/** Render the story component with optional prop overrides */
(extraArgs?: Partial<TArgs>): JSX.Element;
/** Story name from storyName property or function name */
storyName?: string;
/** Combined args from meta and story levels */
args: TArgs;
/** Play function for interaction testing */
play: (context: TestingStoryPlayContext<TArgs>) => Promise<void>;
/** Combined decorators from all levels */
decorators: DecoratorFunction<ReactRenderer, TArgs>[];
/** Combined parameters from all levels */
parameters: Parameters;
};
type TestingStoryPlayContext<TArgs = Args> = Partial<PlayFunctionContext<ReactRenderer, TArgs>> & {
canvasElement: HTMLElement;
};These types are from the Storybook ecosystem and used throughout the API:
// From @storybook/types
type Args = Record<string, any>;
type ComponentAnnotations<TRenderer> = Meta<TRenderer>;
type ProjectAnnotations<TRenderer> = Parameters & GlobalTypes & Decorators;
type DecoratorFunction<TRenderer, TArgs> = (story: StoryFn<TArgs>, context: StoryContext<TRenderer, TArgs>) => any;
// From @storybook/react
type ReactRenderer = {
component: ComponentType<any>;
storyResult: ReactElement<any, any>;
};