Instrumented version of Testing Library for Storybook Interactions addon
npx @tessl/cli install tessl/npm-storybook--testing-library@0.2.0Storybook Testing Library is an instrumented version of Testing Library specifically designed for Storybook's Interactions addon. It wraps @testing-library/dom and @testing-library/user-event with Storybook's instrumentation layer to enable interaction testing within Storybook stories, providing all standard Testing Library functionality while capturing interactions for the Storybook UI.
npm install @storybook/testing-libraryimport {
screen,
within,
waitFor,
userEvent,
fireEvent,
getByText,
findByRole,
queryByTestId
} from "@storybook/testing-library";For CommonJS:
const {
screen,
within,
waitFor,
userEvent,
fireEvent,
getByText,
findByRole,
queryByTestId
} = require("@storybook/testing-library");import { within, userEvent, waitFor } from "@storybook/testing-library";
export const InteractiveExample = {
play: async ({ canvasElement }) => {
// Use within instead of screen for Storybook compatibility
const canvas = within(canvasElement);
// Find elements using queries
const button = canvas.getByRole('button', { name: /click me/i });
const input = canvas.getByLabelText(/username/i);
// Simulate user interactions
await userEvent.type(input, 'john@example.com');
await userEvent.click(button);
// Wait for changes and assert results
await waitFor(() => {
expect(canvas.getByText('Welcome, john@example.com')).toBeInTheDocument();
});
},
};Storybook Testing Library consists of several key components:
within(canvasElement) insteadwaitFor and waitForElementToBeRemoved functionsfireEvent object for direct DOM event triggeringThe instrumentation captures all interactions for display in Storybook's Interactions addon, allowing developers to see and replay user actions.
Complete set of Testing Library query functions for finding elements in the DOM. All queries are instrumented for Storybook interaction tracking.
// Synchronous queries that throw if not found
function getByRole(container: HTMLElement, role: string, options?: ByRoleOptions): HTMLElement;
function getByText(container: HTMLElement, text: string | RegExp, options?: SelectorMatcherOptions): HTMLElement;
function getByTestId(container: HTMLElement, testId: string, options?: SelectorMatcherOptions): HTMLElement;
// Synchronous queries that return null if not found
function queryByRole(container: HTMLElement, role: string, options?: ByRoleOptions): HTMLElement | null;
function queryByText(container: HTMLElement, text: string | RegExp, options?: SelectorMatcherOptions): HTMLElement | null;
// Asynchronous queries that wait and resolve/reject
function findByRole(container: HTMLElement, role: string, options?: ByRoleOptions): Promise<HTMLElement>;
function findByText(container: HTMLElement, text: string | RegExp, options?: SelectorMatcherOptions): Promise<HTMLElement>;Instrumented user-event functionality for simulating realistic user interactions with full keyboard, mouse, and input device support.
interface UserEvent {
click(element: Element, options?: ClickOptions): Promise<void>;
type(element: Element, text: string, options?: TypeOptions): Promise<void>;
clear(element: Element): Promise<void>;
selectOptions(element: Element, values: string | string[], options?: SelectOptions): Promise<void>;
upload(element: Element, file: File | File[]): Promise<void>;
}
declare const userEvent: UserEvent;Scoping utilities for limiting queries to specific DOM containers, essential for Storybook story isolation.
function within(element: HTMLElement): BoundFunctions;
interface BoundFunctions {
getByRole(role: string, options?: ByRoleOptions): HTMLElement;
queryByRole(role: string, options?: ByRoleOptions): HTMLElement | null;
findByRole(role: string, options?: ByRoleOptions): Promise<HTMLElement>;
// ... all query functions bound to the container
}Asynchronous utilities for waiting for DOM changes and element state transitions, with instrumentation for Storybook interaction tracking.
function waitFor<T>(
callback: () => T | Promise<T>,
options?: WaitForOptions
): Promise<T>;
function waitForElementToBeRemoved<T>(
callback: (() => T) | T,
options?: WaitForOptions
): Promise<void>;
interface WaitForOptions {
timeout?: number;
interval?: number;
onTimeout?: (error: Error) => Error;
}Direct DOM event triggering capabilities for lower-level interaction testing, with full instrumentation support.
interface FireEvent {
(element: Element, event: Event): boolean;
click(element: Element, options?: MouseEventInit): boolean;
change(element: Element, options?: EventInit): boolean;
input(element: Element, options?: EventInit): boolean;
keyDown(element: Element, options?: KeyboardEventInit): boolean;
keyUp(element: Element, options?: KeyboardEventInit): boolean;
focus(element: Element, options?: FocusEventInit): boolean;
blur(element: Element, options?: FocusEventInit): boolean;
}
declare const fireEvent: FireEvent;Configuration options and utility functions for customizing Testing Library behavior and building custom queries.
function configure(options: ConfigureOptions): void;
function buildQueries<T extends (...args: any[]) => HTMLElement[]>(
queryAllBy: T,
getMultipleError: (container: HTMLElement, ...args: Parameters<T>) => string,
getMissingError: (container: HTMLElement, ...args: Parameters<T>) => string
): QueryHelpers<T>;
interface ConfigureOptions {
testIdAttribute?: string;
asyncUtilTimeout?: number;
computedStyleSupportsPseudoElements?: boolean;
defaultHidden?: boolean;
showOriginalStackTrace?: boolean;
}interface ByRoleOptions {
hidden?: boolean;
name?: string | RegExp;
description?: string | RegExp;
queryFallbacks?: boolean;
selected?: boolean;
checked?: boolean;
pressed?: boolean;
current?: boolean | string;
expanded?: boolean;
level?: number;
}
interface SelectorMatcherOptions {
exact?: boolean;
normalizer?: (text: string) => string;
trim?: boolean;
collapseWhitespace?: boolean;
ignore?: string | boolean;
timeout?: number;
}
interface ClickOptions {
button?: number;
ctrlKey?: boolean;
shiftKey?: boolean;
altKey?: boolean;
metaKey?: boolean;
}
interface TypeOptions {
delay?: number;
skipClick?: boolean;
skipAutoClose?: boolean;
initialSelectionStart?: number;
initialSelectionEnd?: number;
}The screen object is available but shows a deprecation warning encouraging use of within(canvasElement) instead:
// Deprecated: Shows warning message
const button = screen.getByRole('button');
// Recommended: Use within() for Storybook compatibility
const canvas = within(canvasElement);
const button = canvas.getByRole('button');This package is deprecated in favor of @storybook/test for Storybook 8 and later versions, but remains functional for earlier Storybook versions requiring instrumented testing capabilities.