new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Storybook · Writing and testing · all subjects

play function

39 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Play function debugging

You can interact with and debug your story's play function in the interactions panel.

Play function definition

Storybook's play function is a helper method to test component scenarios that otherwise require user intervention. Play functions are small code snippets that execute once your story renders. For example, you can use play functions to validate form components by simulating user interactions like filling in inputs.

Play functions execute after story renders

Play functions are small snippets of code executed after the story renders. They enable you to interact with your components and test scenarios that otherwise require user intervention.

Play functions run without user intervention

When Storybook finishes rendering the story, it executes the steps defined within the play function, interacting with the component automatically. All of this happens without the need for user intervention.

Interactions panel shows play function execution

The interactions panel provides visibility into play function execution, showing the step-by-step flow of interactions as they are performed on the component.

Canvas object in play function context

The play function receives a context that includes a canvas object. This canvas object allows you to query the DOM of the rendered story and provides a scoped version of the Testing Library queries.

Screen object for queries outside canvas

The screen object is available from 'storybook/test' and can be used to query outside of the canvas scope. This is useful for testing components that appear outside of the story root, such as dialogs.

Play functions can be composed across stories

Thanks to the Component Story Format (CSF), play functions can be combined similarly to other Storybook features like args. This allows you to compose stories to recreate entire component workflows while reducing boilerplate code.

Play functions enable automated interaction testing

Play functions allow you to build component interactions and test scenarios that were impossible without user intervention, such as validating a registration form automatically.

play-fn tag automatically applied

The play-fn tag is automatically applied to stories that have a play function defined.

Play functions contain snippets of code that run after story renders

The play function contains small snippets of code that run after the story renders. It allows you to sequence interactions in stories, enabling simulation of user behavior and interactions within test scenarios.

Play functions for interaction testing

Play functions are used for testing stateful components or verifying interactive behavior. They can be used for setting up state, creating spies, mocking out the network, simulating user interactions with components, and asserting output.

Stories tested as smoke test and play function validation

Stories are tested in two ways: a smoke test to ensure it renders, and if a play function is defined, that function is run and any assertions made within it are validated.

fn() mocks are automatically restored

It is not necessary to manually restore fn() mocks, as Storybook automatically restores them before rendering a story. This is controlled by the parameters.test.restoreMocks API.

Interaction tests structure: story + play function + assertions

In Storybook, interaction tests are built as part of a story. The story renders the component with necessary props and context to place it in an initial state. A play function is then used to simulate user behavior like clicks, typing, and form submission, followed by assertions on the end result.

Canvas query parameter in play function

The canvas parameter in a play function is a queryable element containing the story under test. It can be used to find specific elements to interact with or assert on. All query methods come from Testing Library and take the form of <type><subject>.

Testing Library query types and their behavior

Query types in Testing Library have different behaviors: getBy throws on 0 or >1 matches, queryBy returns null on 0 matches, findBy throws on 0 or >1 matches and is awaited. For multiple elements: getAllBy throws on 0 matches, queryAllBy returns empty array on 0 matches, findAllBy throws on 0 matches and is awaited. Single element queries throw error on >1 matches, while multiple element queries return array. Only findBy and findAllBy are awaited.

Testing Library query subjects

Testing Library provides eight query subjects: ByRole (find elements by accessible role), ByLabelText (by associated label text), ByPlaceholderText (by placeholder value), ByText (by text content), ByDisplayValue (by current value of input/textarea/select), ByAltText (by alt attribute), ByTitle (by title attribute), ByTestId (by data-testid attribute). Query preference order emphasizes accessibility: ByRole is preferred over ByTestId.

Canvas query examples

Example canvas queries include: await canvas.findByRole('button', { name: 'Submit' }) to find first button with accessible name "Submit", canvas.getByText('An example heading') to get first element with that text, and canvas.getAllByRole('listitem') to get all elements with listitem role.

userEvent methods for simulating user interactions

userEvent provides methods to simulate user behavior: click (clicks element), dblClick (double clicks), hover (hovers element), unhover (unhovers), tab (presses tab key), type (writes text in inputs/textareas), keyboard (simulates keyboard events), selectOptions (selects options in select element), deselectOptions (removes selection from option), clear (deletes text in inputs/textareas). All userEvent methods must be awaited in play functions.

userEvent methods must be awaited

All userEvent methods should always be awaited inside the play function. This ensures they can be properly logged and debugged in the Interactions panel.

Import expect from storybook/test module

The expect utility for assertions in interaction tests is available via the storybook/test module: import { expect } from 'storybook/test';. This combines methods from Vitest's expect and @testing-library/jest-dom.

Commonly used expect assertion methods

Common expect assertion methods include: toBeInTheDocument() (checks if element is in DOM), toBeVisible() (checks if element is visible to user), toHaveAttribute() (checks if element has attribute like aria-disabled), toHaveBeenCalled() (checks if spied function was called), toHaveBeenCalledWith() (checks if spied function was called with specific parameters). All expect calls should be awaited in play functions.

Expect calls must be awaited in play functions

All expect calls should always be awaited inside the play function. This ensures they can be properly logged and debugged in the Interactions panel.

Import fn utility from storybook/test for spying

The fn utility for spying on functions is available via the storybook/test module: import { fn } from 'storybook/test';. It comes from Vitest and allows assertions on function behavior. Most commonly, fn is used as an arg value when writing a story, then accessed in the play function to make assertions.

Mount function executes code before component rendering

The mount function in the play method allows executing code before rendering. It can be used to mock the Date object or other setup. Two requirements: (1) must destructure mount from context parameter to prevent premature rendering, (2) Storybook must be configured to transpile to ES2017 or newer to recognize mount usage.

Mount function with custom component data

The mount function can be used to create mock data before rendering. Create data in the play function, then call mount with a component configured with that data, forwarding the args to the component. When mount is called with no arguments, it uses the story's render function. When mount is called with a specific component, it ignores the story's render function.

beforeEach in story meta runs before each story

An asynchronous beforeEach function added to the component meta will run before each story in the file. It can set up initial state or configure modules. The beforeEach function can return a cleanup function that runs after each story when it is remounted or navigated away from.

beforeAll in preview file runs once for entire project

The beforeAll function in the preview file (.storybook/preview.*) runs once before any stories in the project and does not re-run between stories. It is useful for bootstrapping the project or running setup that the entire project depends on. It can return a cleanup function that runs before re-running beforeAll or during teardown.

beforeEach in preview file runs before each story

The beforeEach function in the preview file (.storybook/preview.*) runs before each story in the project, unlike beforeAll which runs only once. It is best for resetting state or modules used by all or most stories. It can return a cleanup function that runs after each story when remounted or navigated away.

afterEach runs after story is rendered and play function completes

The afterEach function runs after the story is rendered and the play function has completed. It can be used at project level in preview file, at component level in meta, or at story level. Like the play function, it receives the context object with args, canvas, and other story-related properties, allowing assertions or code execution after rendering and interactions.

Do not use afterEach to reset state

afterEach should not be used to reset state in tests because it runs after the story, and resetting state there could prevent seeing the correct end state. Instead, use the cleanup function returned by beforeEach, which runs only when navigating between stories to preserve the end state.

Step function groups interactions with custom labels

For complex flows, the step function allows grouping sets of related interactions together with a custom label describing that set. This displays interactions nested in a collapsible group in the Interactions panel.

Interactions panel shows step-by-step flow for debugging

The Interactions panel displays the step-by-step flow defined in the play function for each story. It provides UI controls to pause, resume, rewind, and step through each interaction. Test failures are shown here, making it easy to pinpoint the exact point of failure.

Render test definition

A render test is a simple version of an interaction test that only tests the ability of a component to render successfully in a given state. It works fine for relatively simple, static components like a Button, but more complex interactive components can use play functions for more comprehensive testing.

Combine interaction tests with visual tests for comprehensive coverage

Interaction tests can be expensive to maintain when applied to every component. It is recommended to combine them with visual testing methods for comprehensive coverage with less maintenance work.

storybook/test package exports

The storybook/test package exports instrumented versions of @vitest/spy, @vitest/expect (based on chai), @testing-library/dom, and @testing-library/user-event. These exports include expect, fn, userEvent, and within.

Instrumentation enables debugging in interactions panel

The instrumented versions of testing utilities exported from storybook/test make it possible to debug those methods in the interactions panel during play function execution.

Using storybook/test in play functions example

```ts // Button.stories.ts import { expect, fn, userEvent, within } from 'storybook/test'; import { Button } from './Button'; export default { component: Button, args: { onClick: fn(), }, }; export const Demo = { play: async ({ args, canvasElement }) => { const canvas = within(canvasElement); await userEvent.click(canvas.getByRole('button')); await expect(args.onClick).toHaveBeenCalled(); }, }; ``` This example shows how to import testing utilities from storybook/test, use fn() to create a mock function for args, use within() to query the canvas element, use userEvent to simulate interactions, and use expect() to assert that the mock function was called.

Give your agent this brain