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.
Files changed (40) hide show
  1. package/README.md +68 -6
  2. package/bin/AccordionComponentStrategy-4ZEIQ2V6.js +42 -0
  3. package/bin/ComboboxComponentStrategy-OGRVZXAF.js +64 -0
  4. package/bin/MenuComponentStrategy-JAMTCSNF.js +81 -0
  5. package/bin/TabsComponentStrategy-3SQURPMX.js +29 -0
  6. package/bin/buildContracts-GBOY7UXG.js +437 -0
  7. package/bin/{chunk-VPBHLMAS.js → chunk-LMSKLN5O.js} +21 -0
  8. package/bin/chunk-PK5L2SAF.js +17 -0
  9. package/bin/{chunk-2TOYEY5L.js → chunk-XERMSYEH.js} +12 -3
  10. package/bin/cli.cjs +991 -128
  11. package/bin/cli.js +33 -2
  12. package/bin/{configLoader-XRF6VM4J.js → configLoader-Q6A4JLKW.js} +1 -1
  13. package/{dist/contractTestRunnerPlaywright-UAOFNS7Z.js → bin/contractTestRunnerPlaywright-ZZNWDUYP.js} +270 -219
  14. package/bin/{test-WRIJHN6H.js → test-OND56UUL.js} +97 -10
  15. package/dist/AccordionComponentStrategy-4ZEIQ2V6.js +42 -0
  16. package/dist/ComboboxComponentStrategy-OGRVZXAF.js +64 -0
  17. package/dist/MenuComponentStrategy-JAMTCSNF.js +81 -0
  18. package/dist/TabsComponentStrategy-3SQURPMX.js +29 -0
  19. package/dist/chunk-PK5L2SAF.js +17 -0
  20. package/dist/{chunk-2TOYEY5L.js → chunk-XERMSYEH.js} +12 -3
  21. package/dist/{configLoader-IT4PWCJB.js → configLoader-WTGJAP4Z.js} +21 -0
  22. package/{bin/contractTestRunnerPlaywright-UAOFNS7Z.js → dist/contractTestRunnerPlaywright-XBWJZMR3.js} +270 -219
  23. package/dist/index.cjs +794 -90
  24. package/dist/index.d.cts +136 -1
  25. package/dist/index.d.ts +136 -1
  26. package/dist/index.js +415 -10
  27. package/dist/src/utils/test/AccordionComponentStrategy-WRHZOEN6.js +38 -0
  28. package/dist/src/utils/test/ComboboxComponentStrategy-5AECQSRN.js +60 -0
  29. package/dist/src/utils/test/MenuComponentStrategy-VKZQYLBE.js +77 -0
  30. package/dist/src/utils/test/TabsComponentStrategy-BKG53SEV.js +26 -0
  31. package/dist/src/utils/test/{chunk-2TOYEY5L.js → chunk-XERMSYEH.js} +12 -3
  32. package/dist/src/utils/test/{configLoader-LD4RV2WQ.js → configLoader-YE2CYGDG.js} +21 -0
  33. package/dist/src/utils/test/{contractTestRunnerPlaywright-IRJOAEMT.js → contractTestRunnerPlaywright-LC5OAVXB.js} +262 -200
  34. package/dist/src/utils/test/dsl/index.cjs +320 -0
  35. package/dist/src/utils/test/dsl/index.d.cts +136 -0
  36. package/dist/src/utils/test/dsl/index.d.ts +136 -0
  37. package/dist/src/utils/test/dsl/index.js +318 -0
  38. package/dist/src/utils/test/index.cjs +472 -88
  39. package/dist/src/utils/test/index.js +97 -12
  40. package/package.json +9 -3
@@ -1,6 +1,7 @@
1
- import { normalizeStrictness, closeSharedBrowser, ContractReporter, contract_default, normalizeLevel, resolveEnforcement } from './chunk-2TOYEY5L.js';
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].assertions.length + componentContract.dynamic.length;
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
- if (options.strictness === void 0 && typeof window === "undefined") {
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-LD4RV2WQ.js');
136
- const { config } = await loadConfig(process.cwd());
137
- const componentStrictness = config.test?.components?.find((comp) => comp?.name === componentName)?.strictness;
138
- strictness = normalizeStrictness(componentStrictness ?? config.test?.strictness);
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 = "balanced";
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-IRJOAEMT.js');
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.8.0",
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": [