aria-ease 6.8.0 → 6.9.1
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 +68 -6
- package/bin/AccordionComponentStrategy-4ZEIQ2V6.js +42 -0
- package/bin/ComboboxComponentStrategy-OGRVZXAF.js +64 -0
- package/bin/MenuComponentStrategy-JAMTCSNF.js +81 -0
- package/bin/TabsComponentStrategy-3SQURPMX.js +29 -0
- package/bin/buildContracts-GBOY7UXG.js +437 -0
- package/bin/{chunk-VPBHLMAS.js → chunk-LMSKLN5O.js} +21 -0
- package/bin/chunk-PK5L2SAF.js +17 -0
- package/bin/{chunk-2TOYEY5L.js → chunk-XERMSYEH.js} +12 -3
- package/bin/cli.cjs +991 -128
- package/bin/cli.js +33 -2
- package/bin/{configLoader-XRF6VM4J.js → configLoader-Q6A4JLKW.js} +1 -1
- package/{dist/contractTestRunnerPlaywright-UAOFNS7Z.js → bin/contractTestRunnerPlaywright-ZZNWDUYP.js} +270 -219
- package/bin/{test-WRIJHN6H.js → test-OND56UUL.js} +97 -10
- package/dist/AccordionComponentStrategy-4ZEIQ2V6.js +42 -0
- package/dist/ComboboxComponentStrategy-OGRVZXAF.js +64 -0
- package/dist/MenuComponentStrategy-JAMTCSNF.js +81 -0
- package/dist/TabsComponentStrategy-3SQURPMX.js +29 -0
- package/dist/chunk-PK5L2SAF.js +17 -0
- package/dist/{chunk-2TOYEY5L.js → chunk-XERMSYEH.js} +12 -3
- package/dist/{configLoader-IT4PWCJB.js → configLoader-WTGJAP4Z.js} +21 -0
- package/{bin/contractTestRunnerPlaywright-UAOFNS7Z.js → dist/contractTestRunnerPlaywright-XBWJZMR3.js} +270 -219
- package/dist/index.cjs +794 -90
- package/dist/index.d.cts +136 -1
- package/dist/index.d.ts +136 -1
- package/dist/index.js +415 -10
- package/dist/src/utils/test/AccordionComponentStrategy-WRHZOEN6.js +38 -0
- package/dist/src/utils/test/ComboboxComponentStrategy-5AECQSRN.js +60 -0
- package/dist/src/utils/test/MenuComponentStrategy-VKZQYLBE.js +77 -0
- package/dist/src/utils/test/TabsComponentStrategy-BKG53SEV.js +26 -0
- package/dist/src/utils/test/{chunk-2TOYEY5L.js → chunk-XERMSYEH.js} +12 -3
- package/dist/src/utils/test/{configLoader-LD4RV2WQ.js → configLoader-YE2CYGDG.js} +21 -0
- package/dist/src/utils/test/{contractTestRunnerPlaywright-IRJOAEMT.js → contractTestRunnerPlaywright-LC5OAVXB.js} +262 -200
- package/dist/src/utils/test/dsl/index.cjs +320 -0
- package/dist/src/utils/test/dsl/index.d.cts +136 -0
- package/dist/src/utils/test/dsl/index.d.ts +136 -0
- package/dist/src/utils/test/dsl/index.js +318 -0
- package/dist/src/utils/test/index.cjs +472 -88
- package/dist/src/utils/test/index.js +97 -12
- package/package.json +9 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { normalizeStrictness, closeSharedBrowser, ContractReporter, contract_default, normalizeLevel, resolveEnforcement } from './chunk-
|
|
1
|
+
import { normalizeStrictness, closeSharedBrowser, ContractReporter, contract_default, normalizeLevel, resolveEnforcement } from './chunk-XERMSYEH.js';
|
|
2
2
|
import { axe } from 'jest-axe';
|
|
3
3
|
import fs from 'fs/promises';
|
|
4
|
+
import path from 'path';
|
|
4
5
|
|
|
5
6
|
async function runContractTests(componentName, component, strictness) {
|
|
6
7
|
const reporter = new ContractReporter(false);
|
|
@@ -13,7 +14,7 @@ async function runContractTests(componentName, component, strictness) {
|
|
|
13
14
|
const resolvedPath = new URL(contractPath, import.meta.url).pathname;
|
|
14
15
|
const contractData = await fs.readFile(resolvedPath, "utf-8");
|
|
15
16
|
const componentContract = JSON.parse(contractData);
|
|
16
|
-
const totalTests = componentContract.static[0]
|
|
17
|
+
const totalTests = (componentContract.relationships?.length || 0) + (componentContract.static[0]?.assertions.length || 0) + componentContract.dynamic.length;
|
|
17
18
|
reporter.start(componentName, totalTests);
|
|
18
19
|
const failures = [];
|
|
19
20
|
const passes = [];
|
|
@@ -37,6 +38,82 @@ async function runContractTests(componentName, component, strictness) {
|
|
|
37
38
|
let staticPassed = 0;
|
|
38
39
|
let staticFailed = 0;
|
|
39
40
|
let staticWarnings = 0;
|
|
41
|
+
for (const rel of componentContract.relationships || []) {
|
|
42
|
+
const relationshipLevel = normalizeLevel(rel.level);
|
|
43
|
+
if (rel.type === "aria-reference") {
|
|
44
|
+
const fromSelector = componentContract.selectors[rel.from];
|
|
45
|
+
const toSelector = componentContract.selectors[rel.to];
|
|
46
|
+
const relDescription = `${rel.from}.${rel.attribute} references ${rel.to}`;
|
|
47
|
+
if (!fromSelector || !toSelector) {
|
|
48
|
+
const outcome = classifyFailure(`Relationship selector missing: from="${rel.from}" or to="${rel.to}" not found in selectors.`, rel.level);
|
|
49
|
+
if (outcome.status === "fail") staticFailed += 1;
|
|
50
|
+
if (outcome.status === "warn") staticWarnings += 1;
|
|
51
|
+
reporter.reportStaticTest(relDescription, outcome.status, outcome.detail, outcome.level);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const fromTarget = component.querySelector(fromSelector);
|
|
55
|
+
const toTarget = component.querySelector(toSelector);
|
|
56
|
+
if (!fromTarget || !toTarget) {
|
|
57
|
+
const outcome = classifyFailure(`Relationship target not found: ${!fromTarget ? rel.from : rel.to}.`, rel.level);
|
|
58
|
+
if (outcome.status === "fail") staticFailed += 1;
|
|
59
|
+
if (outcome.status === "warn") staticWarnings += 1;
|
|
60
|
+
reporter.reportStaticTest(relDescription, outcome.status, outcome.detail, outcome.level);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const toId = toTarget.getAttribute("id");
|
|
64
|
+
const attrValue = fromTarget.getAttribute(rel.attribute) || "";
|
|
65
|
+
if (!toId) {
|
|
66
|
+
const outcome = classifyFailure(`Relationship target "${rel.to}" must have an id for ${rel.attribute} validation.`, rel.level);
|
|
67
|
+
if (outcome.status === "fail") staticFailed += 1;
|
|
68
|
+
if (outcome.status === "warn") staticWarnings += 1;
|
|
69
|
+
reporter.reportStaticTest(relDescription, outcome.status, outcome.detail, outcome.level);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const references = attrValue.split(/\s+/).filter(Boolean);
|
|
73
|
+
if (!references.includes(toId)) {
|
|
74
|
+
const outcome = classifyFailure(`Expected ${rel.from} ${rel.attribute} to reference id "${toId}", found "${attrValue}".`, rel.level);
|
|
75
|
+
if (outcome.status === "fail") staticFailed += 1;
|
|
76
|
+
if (outcome.status === "warn") staticWarnings += 1;
|
|
77
|
+
reporter.reportStaticTest(relDescription, outcome.status, outcome.detail, outcome.level);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
passes.push(`Relationship valid: ${rel.from}.${rel.attribute} -> ${rel.to} (id=${toId}).`);
|
|
81
|
+
staticPassed += 1;
|
|
82
|
+
reporter.reportStaticTest(relDescription, "pass", void 0, relationshipLevel);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (rel.type === "contains") {
|
|
86
|
+
const parentSelector = componentContract.selectors[rel.parent];
|
|
87
|
+
const childSelector = componentContract.selectors[rel.child];
|
|
88
|
+
const relDescription = `${rel.parent} contains ${rel.child}`;
|
|
89
|
+
if (!parentSelector || !childSelector) {
|
|
90
|
+
const outcome = classifyFailure(`Relationship selector missing: parent="${rel.parent}" or child="${rel.child}" not found in selectors.`, rel.level);
|
|
91
|
+
if (outcome.status === "fail") staticFailed += 1;
|
|
92
|
+
if (outcome.status === "warn") staticWarnings += 1;
|
|
93
|
+
reporter.reportStaticTest(relDescription, outcome.status, outcome.detail, outcome.level);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const parentTarget = component.querySelector(parentSelector);
|
|
97
|
+
if (!parentTarget) {
|
|
98
|
+
const outcome = classifyFailure(`Relationship parent target not found: ${rel.parent}.`, rel.level);
|
|
99
|
+
if (outcome.status === "fail") staticFailed += 1;
|
|
100
|
+
if (outcome.status === "warn") staticWarnings += 1;
|
|
101
|
+
reporter.reportStaticTest(relDescription, outcome.status, outcome.detail, outcome.level);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const nestedChild = parentTarget.querySelector(childSelector);
|
|
105
|
+
if (!nestedChild) {
|
|
106
|
+
const outcome = classifyFailure(`Expected ${rel.parent} to contain descendant matching selector for ${rel.child}.`, rel.level);
|
|
107
|
+
if (outcome.status === "fail") staticFailed += 1;
|
|
108
|
+
if (outcome.status === "warn") staticWarnings += 1;
|
|
109
|
+
reporter.reportStaticTest(relDescription, outcome.status, outcome.detail, outcome.level);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
passes.push(`Relationship valid: ${rel.parent} contains ${rel.child}.`);
|
|
113
|
+
staticPassed += 1;
|
|
114
|
+
reporter.reportStaticTest(relDescription, "pass", void 0, relationshipLevel);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
40
117
|
for (const test of componentContract.static[0].assertions) {
|
|
41
118
|
if (test.target !== "relative") {
|
|
42
119
|
const staticLevel = normalizeLevel(test.level);
|
|
@@ -90,8 +167,6 @@ async function runContractTests(componentName, component, strictness) {
|
|
|
90
167
|
reporter.summary(failures);
|
|
91
168
|
return { passes, failures, skipped, warnings };
|
|
92
169
|
}
|
|
93
|
-
|
|
94
|
-
// src/utils/test/src/test.ts
|
|
95
170
|
async function testUiComponent(componentName, component, url, options = {}) {
|
|
96
171
|
if (!componentName || typeof componentName !== "string") {
|
|
97
172
|
throw new Error("\u274C testUiComponent requires a valid componentName (string)");
|
|
@@ -130,14 +205,24 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
130
205
|
return null;
|
|
131
206
|
}
|
|
132
207
|
let strictness = normalizeStrictness(options.strictness);
|
|
133
|
-
|
|
208
|
+
let config = {};
|
|
209
|
+
let configBaseDir = typeof process !== "undefined" ? process.cwd() : "";
|
|
210
|
+
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
134
211
|
try {
|
|
135
|
-
const { loadConfig } = await import('./configLoader-
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
212
|
+
const { loadConfig } = await import('./configLoader-YE2CYGDG.js');
|
|
213
|
+
const result2 = await loadConfig(process.cwd());
|
|
214
|
+
config = result2.config;
|
|
215
|
+
if (result2.configPath) {
|
|
216
|
+
configBaseDir = path.dirname(result2.configPath);
|
|
217
|
+
}
|
|
218
|
+
if (options.strictness === void 0) {
|
|
219
|
+
const componentStrictness = config.test?.components?.find((comp) => comp?.name === componentName)?.strictness;
|
|
220
|
+
strictness = normalizeStrictness(componentStrictness ?? config.test?.strictness);
|
|
221
|
+
}
|
|
139
222
|
} catch {
|
|
140
|
-
strictness
|
|
223
|
+
if (options.strictness === void 0) {
|
|
224
|
+
strictness = "balanced";
|
|
225
|
+
}
|
|
141
226
|
}
|
|
142
227
|
}
|
|
143
228
|
let contract;
|
|
@@ -146,8 +231,8 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
146
231
|
const devServerUrl = await checkDevServer(url);
|
|
147
232
|
if (devServerUrl) {
|
|
148
233
|
console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
|
|
149
|
-
const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-
|
|
150
|
-
contract = await runContractTestsPlaywright(componentName, devServerUrl, strictness);
|
|
234
|
+
const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-LC5OAVXB.js');
|
|
235
|
+
contract = await runContractTestsPlaywright(componentName, devServerUrl, strictness, config, configBaseDir);
|
|
151
236
|
} else {
|
|
152
237
|
throw new Error(
|
|
153
238
|
`\u274C Dev server not running at ${url}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aria-ease",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.9.1",
|
|
4
4
|
"description": "Accessibility infrastructure for the entire frontend engineering lifecycle. Build accessible patterns, run automated audits, verify component interactions, and gate deployments — all in one system.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
"release:major": "standard-version --release-as major",
|
|
19
19
|
"clean": "rm -rf dist bin",
|
|
20
20
|
"build:core": "tsup ./index.ts --format esm,cjs --dts --outDir dist --external jest-axe --external @testing-library/react --external @axe-core/playwright --external playwright",
|
|
21
|
-
"build:modules": "tsup ./src/combobox/index.ts ./src/accordion/index.ts ./src/block/index.ts ./src/checkbox/index.ts ./src/menu/index.ts ./src/tabs/index.ts ./src/radio/index.ts ./src/toggle/index.ts --format esm,cjs --dts --treeshake --outDir dist/src",
|
|
21
|
+
"build:modules": "tsup ./src/combobox/index.ts ./src/accordion/index.ts ./src/block/index.ts ./src/checkbox/index.ts ./src/menu/index.ts ./src/tabs/index.ts ./src/radio/index.ts ./src/toggle/index.ts ./src/contracts/index.ts --format esm,cjs --dts --treeshake --outDir dist/src",
|
|
22
22
|
"build:test": "tsup ./src/utils/test/index.ts --format esm,cjs --dts --treeshake --external jest-axe --external @testing-library/react --external playwright --external @playwright/test --outDir dist/src/utils/test",
|
|
23
|
+
"build:dsl": "tsup ./src/utils/test/dsl/index.ts --format esm,cjs --dts --treeshake --outDir dist/src/utils/test/dsl",
|
|
23
24
|
"build:cli": "tsup ./src/utils/cli/cli.ts --format esm,cjs --dts --outDir bin --external commander --external chalk --external jest-axe --external @testing-library/react --external @axe-core/playwright --external playwright",
|
|
24
25
|
"build:contracts": "mkdir -p ./dist/src/utils/test && cp -r ./src/utils/test/contract/aria-contracts ./dist/src/utils/test/",
|
|
25
|
-
"build": "npm run clean && npm run build:core && npm run build:modules && npm run build:test && npm run build:cli && npm run build:contracts"
|
|
26
|
+
"build": "npm run clean && npm run build:core && npm run build:modules && npm run build:test && npm run build:dsl && npm run build:cli && npm run build:contracts"
|
|
26
27
|
},
|
|
27
28
|
"repository": {
|
|
28
29
|
"type": "git",
|
|
@@ -117,6 +118,11 @@
|
|
|
117
118
|
"types": "./dist/src/tabs/index.d.ts",
|
|
118
119
|
"import": "./dist/src/tabs/index.js",
|
|
119
120
|
"require": "./dist/src/tabs/index.cjs"
|
|
121
|
+
},
|
|
122
|
+
"./contract": {
|
|
123
|
+
"types": "./dist/src/utils/test/dsl/index.d.ts",
|
|
124
|
+
"import": "./dist/src/utils/test/dsl/index.js",
|
|
125
|
+
"require": "./dist/src/utils/test/dsl/index.cjs"
|
|
120
126
|
}
|
|
121
127
|
},
|
|
122
128
|
"files": [
|