关于 storybook-stories
面向前端开发者的 Storybook 指导技能,用于隔离展示和测试 UI 组件,重点涵盖 CSF3 故事、交互测试、无障碍检查与视觉回归流程。
主要功能
- 01CSF3 故事编写模式
- 02使用 play 函数进行交互测试
- 03组件无障碍检查
- 04自动文档与控件配置
- 05Chromatic 视觉快照
适用场景
- 01用实时示例编写组件文档
- 02测试组件交互
- 03验证无障碍名称
- 04排查视觉回归失败
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ oakoss/ agent-skills --skill storybook-stories安装后在 Claude Code 中输入/storybook-stories确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/component-documentation.mdinteraction-tests.mdstory-writing.mdvisual-testing.md详细介绍
Storybook 故事
概述
Storybook 是一个用于独立构建 UI 组件的前端工作台。故事采用 Component Story Format 3(CSF3)编写,该格式使用带有 args 的对象语法,为组件文档和测试提供类型安全保障。
适用场景: 通过实时示例编写组件文档、使用 play 函数进行交互测试、视觉回归测试、无障碍验证、设计系统维护、独立开发组件。
不适用场景: 端到端测试(使用 Playwright/Cypress)、API 集成测试(使用 Vitest/Jest)、完整应用测试(使用浏览器自动化)、性能测试(使用 Lighthouse/WebPageTest)。
快速参考
| 模式 | API | 要点 |
|---|---|---|
| 基本故事 | export const Default: Story = { args } | 使用 args 定义简单的单个组件 |
| 复杂故事 | export const Example: Story = { render } | 使用 render 布局多个组件 |
| Meta 配置 | const meta = { component, args } satisfies Meta | 定义默认值和 argTypes |
| 交互测试 | play: async ({ canvas, userEvent, args }) | 直接提供 canvas 和 userEvent |
| 用户交互 | await userEvent.click(element) | 始终等待 userEvent 方法完成 |
| 查询元素 | canvas.getByRole('button') | 优先使用 getByRole,而不是其他查询方式 |
| 断言 | await expect(args.onPress).toHaveBeenCalled() | 使用 storybook/test 断言 |
| beforeEach 钩子 | beforeEach: async ({ args }) => {} | 在故事渲染前设置模拟 |
| Play 组合 | await OtherStory.play?.(context) | 在多个故事间复用设置 |
| Autodocs | tags: ['autodocs'] | 启用自动文档 |
| Controls 自定义 | argTypes: { variant: { control: 'select' } } | 配置控制面板 |
| Decorators | decorators: [withTheme] | 添加包装器或上下文提供程序 |
| Parameters | parameters: { layout: 'centered' } | 配置每个故事的附加组件行为 |
| Chromatic 快照 | parameters: { chromatic: { delay: 300 } } | 控制视觉回归截图 |
| 禁用快照 | parameters: { chromatic: { disableSnapshot: true } } | 在视觉测试中跳过该故事 |
| A11y 测试 | await expect(button).toHaveAccessibleName() | 验证无障碍标签 |
常见错误
| 错误 | 正确做法 |
|---|---|
| 在多组件布局中使用 args | 对于复杂组合,使用 render |
| 未等待 userEvent 方法 | 始终等待:await userEvent.click(button) |
| 手动使用 within(canvasElement) | 直接从 play 上下文中解构 canvas |
| 优先使用 getByTestId | 优先使用 getByRole、getByLabelText、getByText |
| 在 meta 层级缺少默认 args | 在 meta 中添加 args,以避免出现占位控件 |
| 暴露不可序列化的 props | 在 argTypes 中禁用 className、ref、style |
| 未组合 play 函数 | 使用 await BaseStory.play?.(context) 复用设置 |
| 忘记模拟回调 | 使用 fn() 作为事件处理程序:args: { onPress: fn() } |
| 图标按钮缺少可访问名称 | 添加 aria-label 或使用 aria-labelledby |
| 未限定 Portal 内容的查询范围 | 使用 within(canvasElement.ownerDocument.body) |
| 使用布尔值 && 进行条件渲染 | 在 stories 中使用三元表达式,以确保快照一致 |
| 未等待动画 | 对异步状态的断言使用 waitFor 包裹 |
常见修复方法
| 问题 | 解决方案 |
|---|---|
| Controls 显示占位内容 | 在 meta 层级添加带默认值的 args |
| 序列化错误 | 在 argTypes 中禁用 className、ref、style |
| 未找到 Portal 元素 | 在 body 而非 canvas 中搜索 |
| 动画时序问题 | 使用 waitFor 包裹断言 |
| 找到多个按钮 | 将 { name: '...' } 添加到 getByRole 中 |
| A11y 测试失败 | 添加 label prop 或 aria-label |
委派
- Story 结构审查:使用
code-reviewerskill 验证 CSF3 模式 - 无障碍审计:使用
ExploreAgent 探索各个 story 中的 ARIA 模式 - 视觉回归分析:使用
TaskAgent 调查 Chromatic 失败问题
参考资料
评论
支持 Markdown