aria-ease 6.4.8 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -27
- package/bin/{chunk-TQBS54MM.js → chunk-AUJAN4RK.js} +35 -19
- package/bin/cli.cjs +952 -513
- package/bin/cli.js +1 -1
- package/bin/contractTestRunnerPlaywright-7F756CFB.js +984 -0
- package/bin/{test-WICJJ62P.js → test-C3CMRHSI.js} +39 -32
- package/dist/{chunk-TQBS54MM.js → chunk-AUJAN4RK.js} +35 -19
- package/dist/contractTestRunnerPlaywright-7F756CFB.js +984 -0
- package/dist/index.cjs +958 -519
- package/dist/index.js +46 -39
- package/dist/src/{Types.d-DYfYR3Vc.d.cts → Types.d-yGC2bBaB.d.cts} +1 -1
- package/dist/src/{Types.d-DYfYR3Vc.d.ts → Types.d-yGC2bBaB.d.ts} +1 -1
- package/dist/src/accordion/index.d.cts +1 -1
- package/dist/src/accordion/index.d.ts +1 -1
- package/dist/src/block/index.d.cts +1 -1
- package/dist/src/block/index.d.ts +1 -1
- package/dist/src/checkbox/index.d.cts +1 -1
- package/dist/src/checkbox/index.d.ts +1 -1
- package/dist/src/combobox/index.d.cts +1 -1
- package/dist/src/combobox/index.d.ts +1 -1
- package/dist/src/menu/index.cjs +7 -7
- package/dist/src/menu/index.d.cts +1 -1
- package/dist/src/menu/index.d.ts +1 -1
- package/dist/src/menu/index.js +7 -7
- package/dist/src/radio/index.d.cts +1 -1
- package/dist/src/radio/index.d.ts +1 -1
- package/dist/src/tabs/index.d.cts +1 -1
- package/dist/src/tabs/index.d.ts +1 -1
- package/dist/src/toggle/index.d.cts +1 -1
- package/dist/src/toggle/index.d.ts +1 -1
- package/dist/src/utils/test/{contracts/AccordionContract.json → aria-contracts/accordion/accordion.contract.json} +20 -7
- package/dist/src/utils/test/{contracts/ComboboxContract.json → aria-contracts/combobox/combobox.listbox.contract.json} +18 -17
- package/dist/src/utils/test/{contracts/MenuContract.json → aria-contracts/menu/menu.contract.json} +42 -1
- package/dist/src/utils/test/{contracts/TabsContract.json → aria-contracts/tabs/tabs.contract.json} +20 -7
- package/dist/src/utils/test/{chunk-TQBS54MM.js → chunk-AUJAN4RK.js} +34 -18
- package/dist/src/utils/test/contractTestRunnerPlaywright-HL73FADJ.js +955 -0
- package/dist/src/utils/test/index.cjs +921 -505
- package/dist/src/utils/test/index.d.cts +6 -1
- package/dist/src/utils/test/index.d.ts +6 -1
- package/dist/src/utils/test/index.js +38 -31
- package/package.json +2 -2
- package/bin/contractTestRunnerPlaywright-D57V4RSU.js +0 -628
- package/dist/contractTestRunnerPlaywright-D57V4RSU.js +0 -628
- package/dist/src/utils/test/contractTestRunnerPlaywright-HV4EIRDH.js +0 -610
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
ContractReporter,
|
|
3
3
|
closeSharedBrowser,
|
|
4
4
|
contract_default
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AUJAN4RK.js";
|
|
6
6
|
import "./chunk-I2KLQ2HA.js";
|
|
7
7
|
|
|
8
8
|
// src/accordion/src/makeAccordionAccessible/makeAccordionAccessible.ts
|
|
@@ -539,6 +539,13 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
|
|
|
539
539
|
};
|
|
540
540
|
return nodeListLike;
|
|
541
541
|
}
|
|
542
|
+
function intializeMenuItems() {
|
|
543
|
+
const items = getItems();
|
|
544
|
+
items.forEach((item) => {
|
|
545
|
+
item.setAttribute("role", "menuitem");
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
intializeMenuItems();
|
|
542
549
|
function isItemInNestedSubmenu(item) {
|
|
543
550
|
let parent = item.parentElement;
|
|
544
551
|
while (parent && parent !== menuDiv) {
|
|
@@ -651,13 +658,6 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
|
|
|
651
658
|
}
|
|
652
659
|
}
|
|
653
660
|
}
|
|
654
|
-
function intializeMenuItems() {
|
|
655
|
-
const items = getItems();
|
|
656
|
-
items.forEach((item) => {
|
|
657
|
-
item.setAttribute("role", "menuitem");
|
|
658
|
-
});
|
|
659
|
-
}
|
|
660
|
-
intializeMenuItems();
|
|
661
661
|
function handleTriggerClick() {
|
|
662
662
|
const isOpen = triggerButton.getAttribute("aria-expanded") === "true";
|
|
663
663
|
if (isOpen) {
|
|
@@ -1433,7 +1433,7 @@ function makeTabsAccessible({ tabListId, tabsClass, tabPanelsClass, orientation
|
|
|
1433
1433
|
// src/utils/test/src/test.ts
|
|
1434
1434
|
import { axe } from "jest-axe";
|
|
1435
1435
|
|
|
1436
|
-
// src/utils/test/
|
|
1436
|
+
// src/utils/test/src/contractTestRunner.ts
|
|
1437
1437
|
import fs from "fs/promises";
|
|
1438
1438
|
async function runContractTests(componentName, component) {
|
|
1439
1439
|
const reporter = new ContractReporter(false);
|
|
@@ -1450,6 +1450,7 @@ async function runContractTests(componentName, component) {
|
|
|
1450
1450
|
const failures = [];
|
|
1451
1451
|
const passes = [];
|
|
1452
1452
|
const skipped = [];
|
|
1453
|
+
const failuresBeforeStatic = failures.length;
|
|
1453
1454
|
for (const test of componentContract.static[0].assertions) {
|
|
1454
1455
|
if (test.target !== "relative") {
|
|
1455
1456
|
const selector = componentContract.selectors[test.target];
|
|
@@ -1488,8 +1489,9 @@ async function runContractTests(componentName, component) {
|
|
|
1488
1489
|
skipped.push(dynamicTest.description);
|
|
1489
1490
|
reporter.reportTest(dynamicTest, "skip");
|
|
1490
1491
|
}
|
|
1491
|
-
const
|
|
1492
|
-
const staticFailed =
|
|
1492
|
+
const staticTotal = componentContract.static[0].assertions.length;
|
|
1493
|
+
const staticFailed = failures.length - failuresBeforeStatic;
|
|
1494
|
+
const staticPassed = Math.max(0, staticTotal - staticFailed);
|
|
1493
1495
|
reporter.reportStatic(staticPassed, staticFailed);
|
|
1494
1496
|
reporter.summary(failures);
|
|
1495
1497
|
return { passes, failures, skipped };
|
|
@@ -1539,7 +1541,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
1539
1541
|
const devServerUrl = await checkDevServer(url);
|
|
1540
1542
|
if (devServerUrl) {
|
|
1541
1543
|
console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
|
|
1542
|
-
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-
|
|
1544
|
+
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-7F756CFB.js");
|
|
1543
1545
|
contract = await runContractTestsPlaywright(componentName, devServerUrl);
|
|
1544
1546
|
} else {
|
|
1545
1547
|
throw new Error(
|
|
@@ -1594,6 +1596,11 @@ ${violationDetails}
|
|
|
1594
1596
|
return result;
|
|
1595
1597
|
}
|
|
1596
1598
|
var runTest = async () => {
|
|
1599
|
+
return {
|
|
1600
|
+
passes: [],
|
|
1601
|
+
failures: [],
|
|
1602
|
+
skipped: []
|
|
1603
|
+
};
|
|
1597
1604
|
};
|
|
1598
1605
|
if (typeof window === "undefined") {
|
|
1599
1606
|
runTest = async () => {
|
|
@@ -1601,36 +1608,36 @@ if (typeof window === "undefined") {
|
|
|
1601
1608
|
`);
|
|
1602
1609
|
const { exec } = await import("child_process");
|
|
1603
1610
|
const chalk = (await import("chalk")).default;
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
if (stdout) {
|
|
1611
|
+
return new Promise((resolve, reject) => {
|
|
1612
|
+
exec(
|
|
1613
|
+
`npx vitest --run --reporter verbose`,
|
|
1614
|
+
async (error, stdout, stderr) => {
|
|
1609
1615
|
console.log(stdout);
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1616
|
+
if (stderr) console.error(stderr);
|
|
1617
|
+
const testsPassed = !error || error.code === 0;
|
|
1618
|
+
if (testsPassed) {
|
|
1619
|
+
try {
|
|
1620
|
+
const { displayBadgeInfo, promptAddBadge } = await import("./badgeHelper-RDOMCC6E.js");
|
|
1621
|
+
displayBadgeInfo("component");
|
|
1622
|
+
await promptAddBadge("component", process.cwd());
|
|
1623
|
+
console.log(chalk.dim("\n" + "\u2500".repeat(60)));
|
|
1624
|
+
console.log(chalk.cyan("\u{1F499} Found aria-ease helpful?"));
|
|
1625
|
+
console.log(chalk.white(" \u2022 Star us on GitHub: ") + chalk.blue.underline("https://github.com/aria-ease/aria-ease"));
|
|
1626
|
+
console.log(chalk.white(" \u2022 Share feedback: ") + chalk.blue.underline("https://github.com/aria-ease/aria-ease/discussions"));
|
|
1627
|
+
console.log(chalk.dim("\u2500".repeat(60) + "\n"));
|
|
1628
|
+
} catch (badgeError) {
|
|
1629
|
+
console.error("Warning: Could not display badge prompt:", badgeError);
|
|
1630
|
+
}
|
|
1631
|
+
resolve({ passes: [], failures: [], skipped: [] });
|
|
1632
|
+
process.exit(0);
|
|
1633
|
+
} else {
|
|
1634
|
+
const exitCode = error?.code || 1;
|
|
1635
|
+
reject(new Error(`Tests failed with code ${exitCode}`));
|
|
1636
|
+
process.exit(exitCode);
|
|
1626
1637
|
}
|
|
1627
|
-
process.exit(0);
|
|
1628
|
-
} else {
|
|
1629
|
-
const exitCode = error?.code || 1;
|
|
1630
|
-
process.exit(exitCode);
|
|
1631
1638
|
}
|
|
1632
|
-
|
|
1633
|
-
);
|
|
1639
|
+
);
|
|
1640
|
+
});
|
|
1634
1641
|
};
|
|
1635
1642
|
}
|
|
1636
1643
|
async function cleanupTests() {
|
|
@@ -88,4 +88,4 @@ interface MenuCallback {
|
|
|
88
88
|
onOpenChange?: (isOpen: boolean) => void;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export type {
|
|
91
|
+
export type { AccessibilityInstance as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccordionConfig as a };
|
|
@@ -88,4 +88,4 @@ interface MenuCallback {
|
|
|
88
88
|
onOpenChange?: (isOpen: boolean) => void;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export type {
|
|
91
|
+
export type { AccessibilityInstance as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccordionConfig as a };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as AccordionConfig, A as AccessibilityInstance } from '../Types.d-yGC2bBaB.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Makes an accordion accessible by managing ARIA attributes, keyboard interaction, and state.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as AccordionConfig, A as AccessibilityInstance } from '../Types.d-yGC2bBaB.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Makes an accordion accessible by managing ARIA attributes, keyboard interaction, and state.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ComboboxConfig,
|
|
1
|
+
import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-yGC2bBaB.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Makes a Combobox accessible by adding appropriate ARIA attributes, keyboard interactions and focus management.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ComboboxConfig,
|
|
1
|
+
import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-yGC2bBaB.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Makes a Combobox accessible by adding appropriate ARIA attributes, keyboard interactions and focus management.
|
package/dist/src/menu/index.cjs
CHANGED
|
@@ -198,6 +198,13 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
|
|
|
198
198
|
};
|
|
199
199
|
return nodeListLike;
|
|
200
200
|
}
|
|
201
|
+
function intializeMenuItems() {
|
|
202
|
+
const items = getItems();
|
|
203
|
+
items.forEach((item) => {
|
|
204
|
+
item.setAttribute("role", "menuitem");
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
intializeMenuItems();
|
|
201
208
|
function isItemInNestedSubmenu(item) {
|
|
202
209
|
let parent = item.parentElement;
|
|
203
210
|
while (parent && parent !== menuDiv) {
|
|
@@ -310,13 +317,6 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
|
|
|
310
317
|
}
|
|
311
318
|
}
|
|
312
319
|
}
|
|
313
|
-
function intializeMenuItems() {
|
|
314
|
-
const items = getItems();
|
|
315
|
-
items.forEach((item) => {
|
|
316
|
-
item.setAttribute("role", "menuitem");
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
intializeMenuItems();
|
|
320
320
|
function handleTriggerClick() {
|
|
321
321
|
const isOpen = triggerButton.getAttribute("aria-expanded") === "true";
|
|
322
322
|
if (isOpen) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MenuConfig,
|
|
1
|
+
import { M as MenuConfig, A as AccessibilityInstance } from '../Types.d-yGC2bBaB.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adds keyboard interaction to toggle menu. The menu traps focus and can be interacted with using the keyboard. The first interactive item of the menu has focus when menu open.
|
package/dist/src/menu/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MenuConfig,
|
|
1
|
+
import { M as MenuConfig, A as AccessibilityInstance } from '../Types.d-yGC2bBaB.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adds keyboard interaction to toggle menu. The menu traps focus and can be interacted with using the keyboard. The first interactive item of the menu has focus when menu open.
|
package/dist/src/menu/index.js
CHANGED
|
@@ -72,6 +72,13 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
|
|
|
72
72
|
};
|
|
73
73
|
return nodeListLike;
|
|
74
74
|
}
|
|
75
|
+
function intializeMenuItems() {
|
|
76
|
+
const items = getItems();
|
|
77
|
+
items.forEach((item) => {
|
|
78
|
+
item.setAttribute("role", "menuitem");
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
intializeMenuItems();
|
|
75
82
|
function isItemInNestedSubmenu(item) {
|
|
76
83
|
let parent = item.parentElement;
|
|
77
84
|
while (parent && parent !== menuDiv) {
|
|
@@ -184,13 +191,6 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
|
|
|
184
191
|
}
|
|
185
192
|
}
|
|
186
193
|
}
|
|
187
|
-
function intializeMenuItems() {
|
|
188
|
-
const items = getItems();
|
|
189
|
-
items.forEach((item) => {
|
|
190
|
-
item.setAttribute("role", "menuitem");
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
intializeMenuItems();
|
|
194
194
|
function handleTriggerClick() {
|
|
195
195
|
const isOpen = triggerButton.getAttribute("aria-expanded") === "true";
|
|
196
196
|
if (isOpen) {
|
package/dist/src/tabs/index.d.ts
CHANGED
|
@@ -26,6 +26,26 @@
|
|
|
26
26
|
"relative": "first | last | next | previous"
|
|
27
27
|
},
|
|
28
28
|
|
|
29
|
+
"relationships": [
|
|
30
|
+
{
|
|
31
|
+
"type": "aria-reference",
|
|
32
|
+
"from": "trigger",
|
|
33
|
+
"attribute": "aria-controls",
|
|
34
|
+
"to": "panel"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"type": "aria-reference",
|
|
38
|
+
"from": "panel",
|
|
39
|
+
"attribute": "aria-labelledby",
|
|
40
|
+
"to": "trigger"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "contains",
|
|
44
|
+
"parent": "container",
|
|
45
|
+
"child": "trigger"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
|
|
29
49
|
"static": [
|
|
30
50
|
{
|
|
31
51
|
"assertions": [
|
|
@@ -42,13 +62,6 @@
|
|
|
42
62
|
"attribute": "aria-controls",
|
|
43
63
|
"failureMessage": "Accordion trigger button doesn't conform to the ARIA Accordion Button pattern as specified in APG 1.2. Accordion trigger button should have 'aria-controls' attribute that points to the id of the accordion panel div it controls with 'role=region'. This helps assistive technology to identify the accordion panel div that the button controls."
|
|
44
64
|
},
|
|
45
|
-
{
|
|
46
|
-
"target": "panel",
|
|
47
|
-
"assertion": "toHaveAttribute",
|
|
48
|
-
"attribute": "role",
|
|
49
|
-
"expectedValue": "region",
|
|
50
|
-
"failureMessage": "Accordion panel doesn't conform to the ARIA Accordion pattern as specified in APG 1.2. Each accordion panel should have 'role=region' attribute. This helps assistive technology identify the panel as a significant region of the page."
|
|
51
|
-
},
|
|
52
65
|
{
|
|
53
66
|
"target": "panel",
|
|
54
67
|
"assertion": "toHaveAttribute",
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
|
-
"id": "aria-ease.combobox",
|
|
3
|
+
"id": "aria-ease.combobox.listbox",
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"created": "11-02-2026",
|
|
6
6
|
"lastUpdated": "28-02-2026",
|
|
7
|
-
"description": "ARIA Combobox interaction contract. Validates the ARIA and interaction contract for a custom combobox component following the ARIA Authoring Practices Guide combobox with listbox popup pattern.",
|
|
7
|
+
"description": "ARIA Combobox with Listbox popup interaction contract. Validates the ARIA and interaction contract for a custom combobox with listbox component following the ARIA Authoring Practices Guide combobox with listbox popup pattern.",
|
|
8
8
|
"source": {
|
|
9
9
|
"apg": "https://www.w3.org/WAI/ARIA/apg/patterns/combobox/",
|
|
10
10
|
"wcag": ["2.2 AA"]
|
|
11
11
|
},
|
|
12
|
-
"W3CName": "Combobox"
|
|
12
|
+
"W3CName": "Combobox Listbox Popup"
|
|
13
13
|
},
|
|
14
14
|
|
|
15
15
|
"selectors": {
|
|
@@ -28,6 +28,20 @@
|
|
|
28
28
|
"relative": "first | last | next | previous"
|
|
29
29
|
},
|
|
30
30
|
|
|
31
|
+
"relationships": [
|
|
32
|
+
{
|
|
33
|
+
"type": "aria-reference",
|
|
34
|
+
"from": "input",
|
|
35
|
+
"attribute": "aria-controls",
|
|
36
|
+
"to": "listbox"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"type": "contains",
|
|
40
|
+
"parent": "listbox",
|
|
41
|
+
"child": "options"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
|
|
31
45
|
"static": [
|
|
32
46
|
{
|
|
33
47
|
"assertions": [
|
|
@@ -49,6 +63,7 @@
|
|
|
49
63
|
"target": "input",
|
|
50
64
|
"assertion": "toHaveAttribute",
|
|
51
65
|
"attribute": "aria-controls",
|
|
66
|
+
"expectedValue": "!empty",
|
|
52
67
|
"failureMessage": "Combobox input doesn't conform to the ARIA Combobox pattern. Input should have 'aria-controls' attribute that points to the id of the listbox it controls."
|
|
53
68
|
},
|
|
54
69
|
{
|
|
@@ -65,20 +80,6 @@
|
|
|
65
80
|
"expectedValue": "listbox",
|
|
66
81
|
"failureMessage": "Combobox input should have 'aria-haspopup=listbox' to indicate that it can trigger a listbox popup."
|
|
67
82
|
},
|
|
68
|
-
{
|
|
69
|
-
"target": "listbox",
|
|
70
|
-
"assertion": "toHaveAttribute",
|
|
71
|
-
"attribute": "role",
|
|
72
|
-
"expectedValue": "listbox",
|
|
73
|
-
"failureMessage": "Listbox element should have 'role=listbox' attribute."
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
"target": "options",
|
|
77
|
-
"assertion": "toHaveAttribute",
|
|
78
|
-
"attribute": "role",
|
|
79
|
-
"expectedValue": "option",
|
|
80
|
-
"failureMessage": "Each option in the listbox should have 'role=option' attribute."
|
|
81
|
-
},
|
|
82
83
|
{
|
|
83
84
|
"target": "options",
|
|
84
85
|
"assertion": "toHaveAttribute",
|
package/dist/src/utils/test/{contracts/MenuContract.json → aria-contracts/menu/menu.contract.json}
RENAMED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"trigger": "[data-test-id=menu-trigger]",
|
|
17
17
|
"container": "[role=menu]",
|
|
18
18
|
"items": "[role=menuitem], [role=menuitemradio], [role=menuitemcheckbox]",
|
|
19
|
-
"submenuTrigger": "[role=menuitem][aria-haspopup=true], [role=menuitemradio][aria-haspopup=true], [role=menuitemcheckbox][aria-haspopup=true]",
|
|
19
|
+
"submenuTrigger": "[role=menu] [role=menuitem][aria-haspopup=true], [role=menu] [role=menuitemradio][aria-haspopup=true], [role=menu] [role=menuitemcheckbox][aria-haspopup=true], [role=menu] [role=menuitem][aria-haspopup=menu], [role=menu] [role=menuitemradio][aria-haspopup=menu], [role=menu] [role=menuitemcheckbox][aria-haspopup=menu]",
|
|
20
20
|
"submenu": "[role=menu][aria-labelledby]",
|
|
21
21
|
"focusable": "[role=menuitem], [role=menuitemradio], [role=menuitemcheckbox]",
|
|
22
22
|
"relative": "[role=menuitem], [role=menuitemradio], [role=menuitemcheckbox]",
|
|
@@ -29,6 +29,26 @@
|
|
|
29
29
|
"relative": "first | last | next | previous"
|
|
30
30
|
},
|
|
31
31
|
|
|
32
|
+
"relationships": [
|
|
33
|
+
{
|
|
34
|
+
"type": "aria-reference",
|
|
35
|
+
"from": "trigger",
|
|
36
|
+
"attribute": "aria-controls",
|
|
37
|
+
"to": "container"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"type": "aria-reference",
|
|
41
|
+
"from": "container",
|
|
42
|
+
"attribute": "aria-labelledby",
|
|
43
|
+
"to": "trigger"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"type": "contains",
|
|
47
|
+
"parent": "container",
|
|
48
|
+
"child": "items"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
|
|
32
52
|
"static": [
|
|
33
53
|
{
|
|
34
54
|
"assertions": [
|
|
@@ -57,6 +77,27 @@
|
|
|
57
77
|
"assertion": "toHaveAttribute",
|
|
58
78
|
"attribute": "aria-labelledby | aria-label",
|
|
59
79
|
"failureMessage": "Menu container doesn't conform to the ARIA Menu pattern as specified in APG 1.2. Menu container should have 'aria-labelledby' attribute that points to the id of the trigger button that controls it, or 'aria-label' that describes the purpose of the container."
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"target": "container",
|
|
83
|
+
"assertion": "toHaveAttribute",
|
|
84
|
+
"attribute": "role",
|
|
85
|
+
"expectedValue": "menu",
|
|
86
|
+
"failureMessage": "Menu container doesn't conform to the ARIA Menu pattern as specified in APG 1.2. Menu container should have role of 'menu'"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"target": "items",
|
|
90
|
+
"assertion": "toHaveAttribute",
|
|
91
|
+
"attribute": "role",
|
|
92
|
+
"expectedValue": "menuitem | menuitemcheckbox | menuitemradio",
|
|
93
|
+
"failureMessage": "Menu items do not conform to the ARIA Menu pattern as specified in APG 1.2. Menu items should have role of 'menuitem', 'menuitemcheckbox', or 'menuitemradio'"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"target": "items",
|
|
97
|
+
"assertion": "toHaveAttribute",
|
|
98
|
+
"attribute": "tabindex",
|
|
99
|
+
"expectedValue": "-1",
|
|
100
|
+
"failureMessage": "Menu items do not conform to the ARIA Menu pattern as specified in APG 1.2. Menu items' tabindex should have value of '-1'. This ensures the menu items are excluded from the page's Tab sequence"
|
|
60
101
|
}
|
|
61
102
|
]
|
|
62
103
|
}
|
package/dist/src/utils/test/{contracts/TabsContract.json → aria-contracts/tabs/tabs.contract.json}
RENAMED
|
@@ -26,6 +26,26 @@
|
|
|
26
26
|
"relative": "first | last | next | previous"
|
|
27
27
|
},
|
|
28
28
|
|
|
29
|
+
"relationships": [
|
|
30
|
+
{
|
|
31
|
+
"type": "aria-reference",
|
|
32
|
+
"from": "tab",
|
|
33
|
+
"attribute": "aria-controls",
|
|
34
|
+
"to": "panel"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"type": "aria-reference",
|
|
38
|
+
"from": "panel",
|
|
39
|
+
"attribute": "aria-labelledby",
|
|
40
|
+
"to": "tab"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "contains",
|
|
44
|
+
"parent": "tablist",
|
|
45
|
+
"child": "tab"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
|
|
29
49
|
"static": [
|
|
30
50
|
{
|
|
31
51
|
"assertions": [
|
|
@@ -48,13 +68,6 @@
|
|
|
48
68
|
"attribute": "aria-controls",
|
|
49
69
|
"failureMessage": "Tab element doesn't conform to the ARIA Tab pattern as specified in APG 1.2. Tab element should have 'aria-controls' attribute that points to the id of the tab panel it controls. This helps assistive technology to associate the tab with its corresponding tab panel."
|
|
50
70
|
},
|
|
51
|
-
{
|
|
52
|
-
"target": "panel",
|
|
53
|
-
"assertion": "toHaveAttribute",
|
|
54
|
-
"attribute": "role",
|
|
55
|
-
"expectedValue": "tabpanel",
|
|
56
|
-
"failureMessage": "Tab panel doesn't conform to the ARIA Tab pattern as specified in APG 1.2. Each tab panel should have 'role=tabpanel' attribute. This helps assistive technology identify the panel as a significant region of the page."
|
|
57
|
-
},
|
|
58
71
|
{
|
|
59
72
|
"target": "panel",
|
|
60
73
|
"assertion": "toHaveAttribute",
|