Use when adding interaction testing to Storybook stories. Enables automated testing of component behavior, user interactions, and state changes directly in stories.
View on GitHubTheBushidoCollective/han
jutsu-storybook
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-storybook/skills/storybook-play-functions/SKILL.md -a claude-code --skill storybook-play-functionsInstallation paths:
.claude/skills/storybook-play-functions/# Storybook - Play Functions
Write automated interaction tests within stories using play functions to verify component behavior, simulate user actions, and test edge cases.
## Key Concepts
### Play Functions
Play functions run after a story renders, allowing you to simulate user interactions:
```typescript
import { within, userEvent, expect } from '@storybook/test';
import type { Meta, StoryObj } from '@storybook/react';
import { LoginForm } from './LoginForm';
const meta = {
component: LoginForm,
} satisfies Meta<typeof LoginForm>;
export default meta;
type Story = StoryObj<typeof meta>;
export const FilledForm: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.type(canvas.getByLabelText('Email'), 'user@example.com');
await userEvent.type(canvas.getByLabelText('Password'), 'password123');
await userEvent.click(canvas.getByRole('button', { name: /submit/i }));
await expect(canvas.getByText('Welcome!')).toBeInTheDocument();
},
};
```
### Testing Library Integration
Storybook integrates with Testing Library for queries and interactions:
- `within(canvasElement)` - Scopes queries to the story
- `userEvent` - Simulates realistic user interactions
- `expect` - Jest-compatible assertions
- `waitFor` - Waits for async changes
### Test Execution
Play functions execute:
- When viewing a story in Storybook
- During visual regression testing
- In test runners for automated testing
- On story hot-reload during development
## Best Practices
### 1. Use Testing Library Queries
Use semantic queries to find elements:
```typescript
export const SearchFlow: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
// Good - Semantic queries
const searchInput = canvas.getByRole('searchbox');
const submitButton = canvas.getByRole('button', { name: /search/i });
const results = canvas.getByRole('list', { name: /results/i });
await userEve