
Storybook 8.2
迈向无妥协的组件测试

Storybook 是全球顶级设计系统(Carbon、Polaris、Fluent、Lightning 等)背后的组件工坊。因此,它通常与构建和文档化可复用的原子组件相关联。
但 UI 组件有各种尺寸和形状。
对于 Faire、Yoobic 和 Monday.com 的团队来说,Storybook 是他们首选的“产品 UI”工具,用于构建购物车、仪表盘、聊天组件、日历和完整页面等。这些是复杂、有状态的组件,高质量的测试让团队充满信心进行构建和迭代。
这就是为什么我们在 Storybook 中加强了测试能力。我很高兴宣布 Storybook 8.2 发布,这是我们迈向无妥协组件测试之旅的下一站。
- 🪝 新的测试钩子,与其他流行测试工具保持一致
- 🧳 可移植故事,可在其他测试和文档工具中复用
- 📦 包合并,减少依赖冲突
- 🛼 简化上手流程,帮助新用户快速入门
- ✨ 全新改版网站,提供更完善的框架文档
- 💯 数百项其他改进
新的测试钩子
Jest/Vitest/Playwright/Cypress 等现代测试工具都使用 Jasmine 测试结构。每种工具的语法略有不同,但都归结为以下测试钩子:before/afterAll
、before/afterEach
、describe
和 test
。
Storybook 有自己的故事语法,即组件故事格式 (CSF)。CSF 是捕获组件各种状态示例的最佳方式。在 Storybook 6.4 中,我们添加了 play
函数,使得编写交互和断言脚本成为可能。
// ToolbarMenu.stories.js
import { fn, expect } from '@storybook/test';
import { ToolbarMenu } from './ToolbarMenu';
export default { component: ToolbarMenu };
export const Disabled = {
args: { disabled: true, onSelected: fn() },
play: async ({ canvas, args }) => {
await userEvent.click(canvas.getByRole('button'));
expect(args.onSelected).not.toHaveBeenCalled();
},
};
使用 play
函数,可以在 Storybook 中创建许多 Jasmine 风格的测试。但并非所有。而且如果你是从其他测试工具转来的,将测试转换为 CSF 需要一个学习过程。
现在不再是问题。在 Storybook 8.2 中,我们引入了 before
钩子(可以返回清理函数,作为 after
钩子)以及 play
函数的一个可选 mount
参数(适用于 React、Vue 3 和 Svelte)。现在,你可以用与 Jasmine 风格工具相同的控制流编写组件测试,在单个 play
函数内完成“安排、执行和断言”。
// ToolbarMenu.stories.jsx
import { fn, expect } from '@storybook/test';
import { ToolbarMenu } from './ToolbarMenu';
export default {
component: ToolbarMenu,
};
export const Disabled = {
args: { disabled: true, onSelected: fn() },
play: async ({ mount, args }) => {
// Arrange
const items = await loadItems(10);
const canvas = await mount(<ToolbarMenu items={items} />);
// Act
await userEvent.click(canvas.getByRole('button'));
// Assert
expect(canvas.getAllByRole('button').length).toBe(items.length);
expect(args.onSelected).not.toHaveBeenCalled();
},
};
这是一项非破坏性变更,因此你现有的所有故事都可以像以前一样继续工作。推荐的故事编写方式(使用隐式挂载)也没有改变。然而,当你需要额外的能力时,新的测试钩子随时为你提供。
“第一次使用 @storybookjs 的 play 测试。天哪!🥰 从未写过这么快的测试!!”
— @brechtilliet
查看文档,并请继续关注未来几周发布的完整功能公告和更多钩子示例!
可移植故事
Storybook 是迭代构建、文档化和测试组件的最佳工具。但 JS 生态系统中还有许多其他出色的工具,我们希望你能根据需要将你的故事用于这些工具。
在 8.1 版本中,我们为 Playwright 组件测试发布了有限形式的“可移植故事”。现在,在 8.2 版本中,我很高兴推出适用于 React 和 Vue 3 的可移植故事,并提供实验性的 Svelte 支持。这使得你可以轻松地将一个故事转换为框架的“原生”组件,并打包一些额外的代码来运行故事中可能包含的任何测试钩子。
// Button.test.js
import { test, expect } from 'vitest';
import { screen } from '@testing-library/react';
import { composeStories } from '@storybook/react';
// Import all stories and the component annotations from the stories file
import * as stories from './Button.stories';
// Every component that is returned maps 1:1 with the stories,
// but they already contain all annotations from story, meta, and project levels
const { Primary, Secondary } = composeStories(stories);
test('renders primary button with default args', async () => {
/**
* Runs through story lifecycle:
* 1. loaders
* 2. beforeEach
* 3. render w/ decorators (and other annotations)
* 4. play fn (including mount, when used)
* 5. cleanup (from beforeEach, hooks)
*/
await Primary.run();
});
除了 API 之外,我们还准备了关于如何在 Vitest 和 Jest 中复用故事的额外文档。请查看文档,我们将很快发布完整功能公告。
合并依赖管理
通过对 2 万多名开发者进行调查,《JavaScript 生态系统现状报告》是 JS 生态系统的晴雨表。在 2022 年下降之后,我们为改进 Storybook 所做的努力在 2023 年取得了喜人的成果。本次最大的抱怨是糟糕的依赖管理:臃肿、安装占用空间大和版本冲突。
在 8.2 版本中,我们开始解决这个问题。我们将 18 个包合并到一个核心包 storybook
中,并为 builder/renderer/addon 提供了一组卫星包。这是一个非破坏性变更,遵循了 Vite 的包结构。此外,我们还捆绑了 Storybook 的许多依赖项,以消除版本冲突。
我们还与生态系统性能 (e18e) 项目负责人 James Garbutt 合作,将我们的实用库升级到更小/更快/更现代的版本(告别 doctrine
!👋)。
这项工作尚处于早期阶段,但到目前为止,我们已成功将安装大小/时间减少了约 20%。新的合并结构为未来的优化奠定了基础,因此请密切关注 8.3 及更高版本中更大的改进。
简化上手流程
我们关注的另一个领域是上手体验。每周有数千名开发者尝试 Storybook,但从安装到成为成功用户的道路充满了陷阱。在 Storybook 8.2 中,我们改进了上手体验,并将其从 React 扩展到 Vue 3 和 Angular,以帮助用户找到正确的方向。
请继续关注我们在 8.x 版本中进一步改进此体验,使 Storybook 更易于在你的项目中配置。
全新改版的文档网站
Storybook 有了一个全新的文档网站!它包括:
- ✨ 新首页,配有全新的、完全响应式的动画,能更好地展示 Storybook 的众多功能
- 📚 新的文档主页,为每个框架(Next.js、SvelteKit 等)提供专门的着陆页
- 🌙 文档亮/暗模式以匹配你的系统设置
- 🧱 基础工作,为进一步改进和更快迭代奠定基础

数百项其他改进
除了上述功能之外,每个 Storybook 版本都包含了各个层面的数百项改进和错误修复。一些亮点:
- ✅ Webpack5/Vite:修复 sourcemaps - #27171,感谢 @valentinpalkovic!
- ✅ Angular:允许配置源代码预览格式 - #28305,感谢 @64BitAsura!
- ✅ CLI:为
init
添加--no-dev
选项 - #26918,感谢 @fastfrwrd! - ✅ CLI:在新项目中包含
@storybook/addon-svelte-csf
- #27070,感谢 @benmccann - ✅ Core:修复
watchStorySpecifiers
导致的启动卡顿 - #27016,感谢 @heyimalex! - ✅ Vue3:启用新的 hydration mismatch 编译时标志 - #27192,感谢 @Cherry
立即试用!
Storybook 8.2 今日发布。在新项目中试用:
npx storybook@latest init
或升级现有项目:
npx storybook@latest upgrade
如果你从 7.x 版本升级,我们提供了一个指南来帮助你。我们还有一份从更旧版本迁移的指南。
未来展望
我们正在为 8.3 版本准备一系列新内容:
- 集成 Vitest,实现闪电般的组件测试速度
- 为 Next.js 框架添加 Vite 支持,以实现 Vitest 兼容性和更好的开发者体验 (DX)
- 故事标签及用于交互式侧边栏筛选的 UI
- 进一步减小安装体积(试用 8.3-alpha 版本,又小了 40%!)
- 故事全局变量,一种更清晰的方式来编写针对特定视口、主题和区域设置的故事
要了解我们正在进行和考虑的工作的最新情况,请查看 Storybook 的新路线图。
致谢
特别感谢 39 位贡献者,他们的 PR 在 Storybook 8.2 中得以体现!
@43081j @64bitasura @alexatvista @alirezaebrahimkhani @benmccann @cdedreuille @cherry @cosielq @dario-baumberger @deiga @dexofthewild @edoardocavazza @ghengeveld @girgetto @jonniebigodes @jreinhold @kasperpeulen @kevinfoerster @kongallis @kylegach @mnigh @ndelangen @pl12133 @rocktakey @seanparmelee @shilman @simenb @sinnedh @sni-j @superhermione @tmeasday @tobiasdiez @tony19 @valentinpalkovic @vanessayuenn @yannbf @yk-kd @yuheiy
Storybook 8.2 现已发布!😃
— Storybook (@storybookjs) 2024年7月24日
它专注于更可靠、灵活和全面的组件测试。
🪝 更多测试钩子
🧳 可移植故事
📦 包合并
🛼 简化上手流程
✨ 全新网站
💯 还有更多!https://#/lmFgYvi8kk