Skip to content

Commit a3c2cd7

Browse files
committed
automate all aria roles for cucumber tests
1 parent 8a2da1f commit a3c2cd7

File tree

6 files changed

+76
-2
lines changed

6 files changed

+76
-2
lines changed

cucumber.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ module.exports = {
44
require: [
55
"tests/bdd/support/world.ts",
66
"tests/bdd/support/hooks.ts",
7+
"tests/bdd/support/roles.ts",
8+
"tests/bdd/support/parameter-types.ts",
79
"tests/bdd/steps/**/*.ts",
810
],
911
paths: ["tests/bdd/features/**/*.feature"],

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"@types/react": "^19",
6262
"@types/react-dom": "^19",
6363
"@vitejs/plugin-react": "^5.1.1",
64+
"aria-query": "^5.3.2",
6465
"babel-plugin-react-compiler": "1.0.0",
6566
"concurrently": "^9.2.1",
6667
"dotenv": "^17.2.3",

pnpm-lock.yaml

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/bdd/steps/global.steps.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import { Given, Then, When } from "@cucumber/cucumber";
2-
import { expect } from "@playwright/test";
2+
import { type AriaRole, expect } from "@playwright/test";
33
import type { PlaywrightWorld } from "../support/world";
44

55
Given("I am on {string}", async function (this: PlaywrightWorld, path: string) {
66
await this.page.goto(`${this.baseUrl}${path}`);
77
});
88

9+
// Generic click step using a custom {role} parameter type
10+
When(
11+
'I click the "{string}" {role}',
12+
async function (this: PlaywrightWorld, label: string, role: AriaRole) {
13+
await this.page.getByRole(role, { name: label }).click();
14+
},
15+
);
16+
17+
// Backward-compatible convenience wrapper for "button" steps
918
When(
1019
"I click the {string} button",
1120
async function (this: PlaywrightWorld, label: string) {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { defineParameterType } from "@cucumber/cucumber";
2+
import type { AriaRole } from "@playwright/test";
3+
import { roleAliases, validAriaRoles } from "./roles.ts";
4+
5+
defineParameterType({
6+
name: "role",
7+
// Match human-written role text, e.g., "menu item", "radio button", "checkbox"
8+
regexp: /[A-Za-z ][A-Za-z -]*/,
9+
transformer: (text: string): AriaRole => {
10+
const input = text.trim().toLowerCase();
11+
12+
// 1) Exact match
13+
if (validAriaRoles.has(input)) {
14+
return input as AriaRole;
15+
}
16+
17+
// 2) Compact variant: remove spaces and hyphens
18+
const compact = input.replace(/[\s-]+/g, "");
19+
if (validAriaRoles.has(compact)) {
20+
return compact as AriaRole;
21+
}
22+
23+
// 3) Aliases
24+
const alias = roleAliases[input];
25+
if (alias) {
26+
return alias;
27+
}
28+
29+
// 4) Helpful error
30+
const sample = Array.from(validAriaRoles).slice(0, 15).join(", ");
31+
throw new Error(
32+
`Unknown role "${text}".\n` +
33+
`- Tried: "${input}" and "${compact}".\n` +
34+
"- Add an alias in roleAliases if this is a valid custom phrase.\n" +
35+
`- Example known roles: ${sample} ...`,
36+
);
37+
},
38+
});

tests/bdd/support/roles.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { AriaRole } from "@playwright/test";
2+
import { roles as ariaRolesMap } from "aria-query";
3+
4+
// Set of all valid ARIA roles sourced from aria-query
5+
export const validAriaRoles = new Set<string>([...ariaRolesMap.keys()]);
6+
7+
// Map human-friendly phrases to real ARIA roles (keep this minimal and sensible)
8+
export const roleAliases: Record<string, AriaRole> = {
9+
"menu item": "menuitem",
10+
"radio button": "radio",
11+
"check box": "checkbox",
12+
// common synonyms
13+
dropdown: "combobox",
14+
"list box": "listbox",
15+
};

0 commit comments

Comments
 (0)