加入直播会话:美国东部时间周四上午 11 点,Storybook 9 发布 & AMA

测试工具,允许您在单元测试中重用您的故事

在 Github 上查看

⚠️ 此库适用于 Vue 3 项目。如果您正在 Storybook 与 Vue 2 一起使用,请改用 @storybook/testing-vue

为什么要这个分支?

您可以在测试运行器中调用故事上的 play 方法。如果您已经在使用 Storybook 交互插件,这将非常有用。

安装

此库应作为您项目的 devDependencies 之一安装

通过 npm

npm install --save-dev @storybook/testing-vue3

或通过 yarn

yarn add --dev @storybook/testing-vue3

设置

Storybook CSF

此库要求您使用 Storybook 的 组件故事格式 (CSF)hoisted CSF annotations,这是自 Storybook 6 以来推荐的故事编写方式。

本质上,如果您的故事看起来与此类似,那么您就可以开始了!

// CSF: default export (meta) + named exports (stories)
export default {
  title: "Example/Button",
  component: Button
};

export const Primary = () => ({
  template: "<my-button primary />"
});

全局配置

这是可选步骤。如果您没有全局装饰器(global decorators),则无需执行此操作。但是,如果您有,这是应用全局装饰器的必要步骤。

如果您有全局装饰器/参数等,并希望在测试故事时应用它们,则首先需要进行设置。您可以通过添加或创建 jest setup file 来实现

// setupFile.js <-- this will run before the tests in jest.
import { setGlobalConfig } from "@storybook/testing-vue3";
import * as globalStorybookConfig from "./.storybook/preview"; // path of your preview.js file

setGlobalConfig(globalStorybookConfig);

为了让 setup file 生效,您需要在测试命令中将其作为选项传递给 jest

// package.json
{
  "test": "jest --setupFiles ./setupFile.js"
}

使用

composeStories

composeStories 将处理您指定的组件的所有故事,在所有故事中组合 args/装饰器,并返回一个包含组合故事的对象。

如果您使用组合故事(例如 PrimaryButton),该组件将使用故事中传递的 args 进行渲染。但是,您可以自由地在组件顶部传递任何 props,这些 props 将覆盖故事 args 中传递的默认值。

import { render, screen } from "@testing-library/vue";
import { composeStories } from "@storybook/testing-vue3";
import * as stories from "./Button.stories"; // import all stories from the stories file

// Every component that is returned maps 1:1 with the stories, but they already contain all decorators from story level, meta level and global level.
const { Primary, Secondary } = composeStories(stories);

test("renders primary button with default args", () => {
  render(Primary());
  const buttonElement = screen.getByText(
    /Text coming from args in stories file!/i
  );
  expect(buttonElement).not.toBeNull();
});

test("renders primary button with overriden props", () => {
  render(Secondary({ label: "Hello world" })); // you can override props and they will get merged with values from the Story's args
  const buttonElement = screen.getByText(/Hello world/i);
  expect(buttonElement).not.toBeNull();
});

composeStory

如果您希望仅应用于单个故事而不是所有故事,可以使用 composeStory。您还需要传递 meta(默认导出)。

import { render, screen } from "@testing-library/vue";
import { composeStory } from "@storybook/testing-vue3";
import Meta, { Primary as PrimaryStory } from "./Button.stories";

// Returns a component that already contain all decorators from story level, meta level and global level.
const Primary = composeStory(PrimaryStory, Meta);

test("onclick handler is called", async () => {
  const onClickSpy = jest.fn();
  render(Primary({ onClick: onClickSpy }));
  const buttonElement = screen.getByRole("button");
  buttonElement.click();
  expect(onClickSpy).toHaveBeenCalled();
});

许可证

MIT