使用 Cypress 测试可访问性
在上一篇文章中,我们创建了一个可访问的 React 折叠面板组件。现在来测试一下。我觉得为这种组件编写单元测试没什么意义。快照测试也没什么用。我认为端到端 (e2e) 测试是最佳选择(但对于测试钩子,我更喜欢单元测试)。
将尝试使用Cypress进行测试。Cypress 使用 Headless Chrome,它有一个 devtools 协议,据说比以前的类似解决方案具有更好的集成度。
安装 Cypress
一旦了解如何启动,Cypress 就很容易上手。我花了……比我预想的要多得多的时间才搞清楚如何开始。他们的文档非常多,很难浏览(至少对我来说)。
有时,过多的文档与过少的文档一样糟糕
但我经过一些实验后找到了答案。安装 Cypress
yarn add cypress --dev
首次运行
yarn cypress open
它会创建很多文件。关闭 Cypress 窗口。删除 中的所有内容cypress/integration
。
添加cypress.json
到项目的根目录。
{
"baseUrl": "http://localhost:3000/"
}
现在,您可以在一个终端中启动开发服务器yarn start
,在第二个终端中启动 Cypressyarn cypress open
并开始编写测试。
配置 Cypress
但是如何在 CI 中运行测试呢?为此,你需要另一个 npm 包:
yarn add --dev start-server-and-test
改变package.json
"scripts": {
"test": "yarn test:e2e && yarn test:unit",
"test:unit": "react-scripts test",
"cypress-run": "cypress run",
"test:e2e": "start-server-and-test start http://localhost:3000 cypress-run"
}
快完成了。再添加一个包
yarn add cypress-plugin-tab --dev
在cypress/support/index.js
import "./commands";
import "cypress-plugin-tab";
添加.gitignore
cypress/screenshots
cypress/videos
现在我们完成了。
规划测试
我喜欢这部分。
让我们创建测试文件cypress/integration/Accordion.js
:
describe("Accordion", () => {
before(() => {
cy.visit("/");
});
// your tests here
});
它将在测试之前打开服务器的根页面(我们将使用开发服务器)。
我们在上一篇文章中看到了WAI-ARIA 创作实践 1.1。
- 空格或 Enter
- 当焦点位于折叠部分的手风琴标题上时,展开该部分。
- Tab
- 将焦点移动到下一个可聚焦元素。
- 手风琴面板中所有可聚焦元素均包含在页面 Tab 序列中。
describe("Space or Enter", () => {
xit("When focus is on the accordion header of a collapsed section, expands the section", () => {});
});
describe("Tab", () => {
xit("Moves focus to the next focusable element.", () => {});
xit("All focusable elements in the accordion are included in the page Tab sequence.", () => {});
});
describe
- 向层次结构中添加一个级别(可选)。xit
- 将被跳过的测试,一旦我们实施实际测试,我们将把它更改为it
it
- 测试,it("name of the test", <body of the test>)
是不是很漂亮?我们可以直接从 WAI-ARIA 规范中复制粘贴测试定义。
编写测试
让我们编写实际测试。
首先,我们需要就测试页面的假设达成一致:
- 只有一个 accordion 组件
- 其中有三个部分:“第 1 部分”、“第 2 部分”、“第 3 部分”
- 第 2 部分已展开,其他部分已折叠
- 第 2 部分有一个链接
- 手风琴后面有一个按钮
第一个测试:“空格或回车键,当焦点位于折叠部分的手风琴标题上时,展开该部分”。
让我们找到 accordion 中的第一个面板,并检查它是否已折叠。根据规范,我们知道该面板应该包含role=region
一个参数,如果它已折叠,则应该包含hidden
一个参数:
cy.get("body")
.find("[role=region]")
.first()
.should("have.attr", "hidden");
我们先找到对应的 header eg。根据规范,我们知道它应该包含role=button
一个参数。我们模拟focus
事件,因为用户会用它Tab
来访问它。
cy.get("body")
.find("[role=button]")
.first()
.focus();
现在让我们在焦点元素中输入空格
cy.focused().type(" ");
让我们检查一下扩展的部分(与第一个动作相反):
cy.get("body")
.find("[role=region]")
.first()
.should("not.have.attr", "hidden");
我想这很简单(如果您熟悉任何 e2e 测试工具,它们都有类似的 API)。
根据鼠标的规格和规格编写所有测试很容易。
不稳定的测试
唯一不太稳定的地方是当我们使用 React 切换焦点时,例如向上箭头、向下箭头、结束、主页。在这种情况下,焦点的改变不是即时的(与浏览器相比Tab
)。所以我被迫添加了一个小小的延迟来解决这个问题:
describe("Home", () => {
it("When focus is on an accordion header, moves focus to the first accordion header.", () => {
cy.contains("section 2").focus();
cy.focused().type("{home}");
cy.wait(100); // we need to wait to make sure React has enough time to switch focus
cy.focused().contains("section 1");
});
});
结论
我喜欢规范可以直接转化为端到端测试。这是编写 a11y 组件的好处之一——所有行为都已描述,测试也已规划好。我想尝试用 BDD 风格(测试优先)编写下一个组件。
文章来源:https://dev.to/stereobooster/testing-accessibility-with-cypress-2dfo