Storybook 组件测试
概述
Nightwatch 可以通过我们的官方 @nightwatch/storybook
插件与 Storybook 集成,该插件为 React 现有 Storybook 项目运行组件测试提供了多种重要功能。
无需编写额外的测试并导入故事。Nightwatch 支持 组件故事格式 (CSF),因此它可以直接运行故事。
工作原理
Nightwatch 能够检测并运行任何现有的 交互测试 (使用 play()
函数) 和 可访问性测试,这些测试是在组件故事中定义的。
此外,Nightwatch 提供了一个 test()
函数,该函数可以访问其自己的 API。
import Form from '../components/Form.jsx';
export default {
title: 'Form Stories',
component: Form
}
const Template = (args) =< <Form {...args} />
export const FilledForm = Template.bind({});
// Runs in the browser context
FilledForm.play = async ({ canvasElement }) =< {
};
// Runs in the Nightwatch context
FilledForm.test = async (browser, { component }) =< {
}
安装
Nightwatch 的 Storybook 插件可以通过 NPM 安装:
然后在您的 nightwatch.conf.js
中添加插件:
module.exports = {
plugins: [
//...
'@nightwatch/storybook'
]
}
用法
该插件可以在 React 的 现有 Storybook 项目中使用。
设置 Storybook
在现有的 React 项目中,运行:
有关更多详细信息,请访问 Storybook 的 安装指南。
我们还建议安装一些必要的 Storybook 附加组件:
运行故事
默认情况下,Nightwatch 将在目标浏览器中挂载组件故事并执行基本的可见性断言。然后,根据下面定义的内容,它将:
- 如果定义了
play()
函数,则运行任何交互测试; - 运行可访问性测试
- 运行测试钩子(如果在
default
故事导出中定义了以下任何一个):setup (browser)
teardown (browser)
preRender (browser, {id, title, name})
postRender (browser, {id, title, name})
所有测试钩子都是 async
。
此外,Nightwatch 提供了使用其自己的 test()
函数扩展组件故事的功能,如下所示:
test(browser, { component })
阅读更多内容:
示例
考虑一个基本的 Form.jsx
组件,以下是其 Form.stories.jsx
故事的外观,使用 CSF 编写并扩展了 Nightwatch 功能:
import { userEvent, within } from '@storybook/testing-library';
import Form from './Form.jsx';
export default {
title: 'Form',
component: Form,
async setup(browser) {
console.log('setup hook', browser.capabilities)
},
async preRender(browser) {
console.log('preRender hook')
},
async postRender(browser) {
console.log('postRender hook')
},
async teardown(browser) {
console.log('teardown hook')
},
}
const Template = (args) =< <Form {...args} />;
// Component story for an empty form
export const EmptyForm = Template.bind({});
// Component story simulating filling in the form
export const FilledForm = Template.bind({});
FilledForm.play = async ({ canvasElement }) =< {
// Starts querying the component from its root element
const canvas = within(canvasElement);
// 👇 Simulate interactions with the component
await userEvent.type(canvas.getByTestId('new-todo-input'), 'outdoors hike');
await userEvent.click(canvas.getByRole('button'));
};
FilledForm.test = async (browser, { component }) =< {
// 👇 Run commands and assertions in the Nightwatch context
await expect(component).to.be.visible;
}
配置
@nightwatch/storybook
插件支持一些配置选项。编辑您的 nightwatch.conf.js
并按如下方式配置它:
src_folders
默认情况下,Nightwatch 尝试使用故事书配置文件夹中main.js
中定义的位置。这可以定义故事所在位置的特定位置。
以下选项需要在特定的 '@nightwatch/storybook'
字典下设置:
start_storybook
– Nightwatch 是否应该自动管理 Storybook 服务器(默认值为false
)storybook_url
– 如果 Storybook 在不同的端口/主机名上运行,则可以更改此选项(默认值为https://127.0.0.1:6006/
)storybook_config_dir
- 默认值为.storybook
hide_csf_errors
- Nightwatch 尝试忽略 CSF 解析错误并显示警告;将其设置为true
将隐藏这些警告(默认值为false
)show_browser_console
- 默认情况下,当使用 Chrome 或 Edge 浏览器时,浏览器控制台日志将显示在 Nightwatch 控制台中(使用[browser]
前缀);此选项将禁用此功能。
module.exports = {
src_folders: ['src/stories/*.stories.jsx'],
'@nightwatch/storybook': {
start_storybook: false,
storybook_url: 'https://127.0.0.1:6006/',
storybook_config_dir: '.storybook', // default storybook config directory
hide_csf_errors: false,
show_browser_console: true
}
}
使用 Nightwatch 运行故事
之前的 Form.stories.jsx
示例包含两个故事,可以作为常规测试由 Nightwatch 运行。
为了获得目前最佳的开发人员体验,我们建议使用 Chrome,但是您也可以使用 Nightwatch 支持的任何其他浏览器。
运行特定故事
您可以使用 --story
CLI 参数从给定的 .stories.jsx
文件中运行特定故事。
假设您只想运行 FilledForm
故事。这将挂载它并相应地执行 play()
和 test()
函数:
并行运行故事
使用现有的 Nightwatch 选项使用测试工作程序并行运行,可以并行运行故事以优化执行速度。实际上,从 Nightwatch v2.4 开始,默认情况下启用了使用测试工作程序并行运行。
预览故事
Nightwatch 提供了使用预览模式运行 .stories.jsx
文件的功能(使用 --preview
CLI 参数),这将只打开 Storybook 渲染器并无限期地暂停执行。
这在开发过程中可能很有用,因为 Storybook 渲染器能够通过其内置的热模块替换 (HMR) 功能自动重新加载组件。
要以预览模式启动 FilledForm
故事,请运行:
您可以使用 Nightwatch 内置的并行性在 Firefox 和 Chrome 中打开故事:
调试故事
除了预览故事之外,还可以使用 Nightwatch 调试故事。为此,请启用 --debug
和 --devtools
CLI 标志,并使用 debugger
在 play()
函数中添加断点。
示例
import { userEvent, within } from '@storybook/testing-library';
import Form from './Form.jsx';
export default {
title: 'Form',
component: Form,
}
const Template = (args) =< <Form {...args} />
// Component story for an empty form
export const EmptyForm = Template.bind({});
// Component story simulating filling in the form
export const FilledForm = Template.bind({});
FilledForm.play = async ({ canvasElement }) =< {
// Starts querying the component from its root element
const canvas = within(canvasElement);
debugger;
// 👇 Simulate interactions with the component
await userEvent.type(canvas.getByTestId('new-todo-input'), 'outdoors hike');
await userEvent.click(canvas.getByRole('button'));
};
FilledForm.test = async (browser, { component }) =< {
// 👇 Run commands and assertions in the Nightwatch context
await expect(component).to.be.visible;
}
运行示例并观察 Chrome devtools 控制台中的断点。
您还可以使用 集成调试控制台 从 Nightwatch 中发出命令。
可访问性测试
Storybook 和 Nightwatch 内部都依赖于由 Deque Systems 开发并在 NPM 中发布的相同可访问性测试工具,发布为 axe-core
库。
要开始在 Storybook 中进行 A11y 测试,请安装附加组件:
将此行添加到您的 main.js
文件中(如果需要,请在您的 Storybook 配置目录中创建此文件)。
module.exports = {
addons: ['@storybook/addon-a11y']
};
更多详细信息可以在 Storybook 文档中找到:
示例
考虑捆绑的示例 Button.jsx
组件和 Button.stories.jsx
,它们在您设置 Storybook 时预先安装。
为可访问性测试添加以下规则:
import React from 'react';
import { Button } from './Button';
export default {
title: "Example/Button",
component: Button,
argTypes: {
backgroundColor: { control: "color" },
},
parameters: {
a11y: {
// Optional selector to inspect
element: '#root',
// Show the individual axe-rules as Nightwatch assertions (can be verbose if there are many violations)
runAssertions: false,
// Show the complete Acccessibilty test report (by default, only rule violations will be shown)
verbose: false,
config: {
rules: [
{
// The autocomplete rule will not run based on the CSS selector provided
id: 'autocomplete-valid',
selector: '*:not([autocomplete="nope"])',
},
{
// Setting the enabled option to false will disable checks for this particular rule on all stories.
id: 'image-alt',
enabled: false,
},
{
id: 'input-button-name',
enabled: true
},
{
id: 'color-contrast',
enabled: true
}
],
},
options: {},
manual: true
}
}
};
const Template = (args) =< <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
export const Secondary = Template.bind({});
Secondary.args = {
label: 'Button',
};
export const Large = Template.bind({});
Large.args = {
size: 'large',
label: 'Button',
};
export const Small = Template.bind({});
Small.args = {
size: 'small',
label: 'Button',
};
Nightwatch 将自动从故事配置中获取 A11y 规则并使用它们运行自己的可访问性测试命令。
Button 组件故事之一将无法通过 Axe-core 库定义的 "color-contrast"
可访问性规则。
运行以下命令查看结果:
Nightwatch 的输出应为:
要查看整个报告(包括所有评估的规则),请在故事参数中传递 verbose: true
:
import React from 'react';
import { Button } from './Button';
export default {
parameters: {
a11y: {
// Show the complete Accessibility test report (by default, only rule violations will be shown)
verbose: false,
// ...
}
}
}