aria-ease 6.4.10 → 6.5.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 (23) hide show
  1. package/bin/{chunk-GFKAJHCS.js → chunk-AUJAN4RK.js} +34 -18
  2. package/bin/cli.cjs +67 -35
  3. package/bin/cli.js +1 -1
  4. package/{dist/contractTestRunnerPlaywright-7BCEDPZF.js → bin/contractTestRunnerPlaywright-7F756CFB.js} +26 -12
  5. package/bin/{test-JGKWOL6J.js → test-C3CMRHSI.js} +7 -5
  6. package/dist/{chunk-GFKAJHCS.js → chunk-AUJAN4RK.js} +34 -18
  7. package/{bin/contractTestRunnerPlaywright-7BCEDPZF.js → dist/contractTestRunnerPlaywright-7F756CFB.js} +26 -12
  8. package/dist/index.cjs +148 -106
  9. package/dist/index.js +89 -77
  10. package/dist/src/block/index.cjs +1 -6
  11. package/dist/src/block/index.js +72 -1
  12. package/dist/src/menu/index.cjs +79 -147
  13. package/dist/src/menu/index.js +79 -23
  14. package/dist/src/utils/test/{contracts/AccordionContract.json → aria-contracts/accordion/accordion.contract.json} +21 -8
  15. package/dist/src/utils/test/{contracts/ComboboxContract.json → aria-contracts/combobox/combobox.listbox.contract.json} +18 -18
  16. package/dist/src/utils/test/{contracts/MenuContract.json → aria-contracts/menu/menu.contract.json} +43 -2
  17. package/dist/src/utils/test/{contracts/TabsContract.json → aria-contracts/tabs/tabs.contract.json} +21 -8
  18. package/dist/src/utils/test/{chunk-GFKAJHCS.js → chunk-AUJAN4RK.js} +33 -17
  19. package/dist/src/utils/test/{contractTestRunnerPlaywright-O7FF3X67.js → contractTestRunnerPlaywright-HL73FADJ.js} +25 -11
  20. package/dist/src/utils/test/index.cjs +65 -33
  21. package/dist/src/utils/test/index.js +6 -4
  22. package/package.json +2 -2
  23. package/dist/src/chunk-ZJXZZDUR.js +0 -127
@@ -1,24 +1,24 @@
1
1
  // src/utils/test/contract/contract.json
2
2
  var contract_default = {
3
3
  menu: {
4
- path: "./contracts/MenuContract.json",
4
+ path: "./aria-contracts/menu/menu.contract.json",
5
5
  component: "menu"
6
6
  },
7
- combobox: {
8
- path: "./contracts/ComboboxContract.json",
9
- component: "combobox"
7
+ "combobox.listbox": {
8
+ path: "./aria-contracts/combobox/combobox.listbox.contract.json",
9
+ component: "combobox.listbox"
10
10
  },
11
11
  accordion: {
12
- path: "./contracts/AccordionContract.json",
12
+ path: "./aria-contracts/accordion/accordion.contract.json",
13
13
  component: "accordion"
14
14
  },
15
15
  tabs: {
16
- path: "./contracts/TabsContract.json",
16
+ path: "./aria-contracts/tabs/tabs.contract.json",
17
17
  component: "tabs"
18
18
  }
19
19
  };
20
20
 
21
- // src/utils/test/contract/ContractReporter.ts
21
+ // src/utils/test/src/ContractReporter.ts
22
22
  var ContractReporter = class {
23
23
  startTime = 0;
24
24
  componentName = "";
@@ -30,6 +30,8 @@ var ContractReporter = class {
30
30
  optionalSuggestions = 0;
31
31
  isPlaywright = false;
32
32
  apgUrl = "https://www.w3.org/WAI/ARIA/apg/";
33
+ hasPrintedStaticSection = false;
34
+ hasPrintedDynamicSection = false;
33
35
  constructor(isPlaywright = false) {
34
36
  this.isPlaywright = isPlaywright;
35
37
  }
@@ -40,30 +42,32 @@ var ContractReporter = class {
40
42
  this.startTime = Date.now();
41
43
  this.componentName = componentName;
42
44
  this.totalTests = totalTests;
45
+ this.hasPrintedStaticSection = false;
46
+ this.hasPrintedDynamicSection = false;
43
47
  if (apgUrl) {
44
48
  this.apgUrl = apgUrl;
45
49
  }
46
50
  const mode = this.isPlaywright ? "Playwright (Real Browser)" : "jsdom (Fast)";
47
51
  this.log(`
48
52
  ${"\u2550".repeat(60)}`);
49
- this.log(`\u{1F50D} Testing ${componentName} Component - ${mode}`);
53
+ this.log(`\u{1F50D} Testing ${componentName.charAt(0).toUpperCase() + componentName.slice(1)} Component - ${mode}`);
50
54
  this.log(`${"\u2550".repeat(60)}
51
55
  `);
52
56
  }
53
57
  reportStatic(passes, failures) {
54
58
  this.staticPasses = passes;
55
59
  this.staticFailures = failures;
56
- const icon = failures === 0 ? "\u2705" : "\u274C";
57
- const status = failures === 0 ? "PASS" : "FAIL";
58
- this.log("");
59
- this.log(`${icon} Static ARIA Tests: ${status}`);
60
- this.log(` ${passes}/${passes + failures} required attributes present
61
- `);
62
60
  }
63
61
  /**
64
62
  * Report individual static test pass
65
63
  */
66
64
  reportStaticTest(description, passed, failureMessage) {
65
+ if (!this.hasPrintedStaticSection) {
66
+ this.log(`${"\u2500".repeat(60)}`);
67
+ this.log(`\u{1F9EA} Static Assertions`);
68
+ this.log(`${"\u2500".repeat(60)}`);
69
+ this.hasPrintedStaticSection = true;
70
+ }
67
71
  const icon = passed ? "\u2713" : "\u2717";
68
72
  this.log(` ${icon} ${description}`);
69
73
  if (!passed && failureMessage) {
@@ -74,6 +78,13 @@ ${"\u2550".repeat(60)}`);
74
78
  * Report individual dynamic test result
75
79
  */
76
80
  reportTest(test, status, failureMessage) {
81
+ if (!this.hasPrintedDynamicSection) {
82
+ this.log("");
83
+ this.log(`${"\u2500".repeat(60)}`);
84
+ this.log(`\u2328\uFE0F Dynamic Interaction Tests`);
85
+ this.log(`${"\u2500".repeat(60)}`);
86
+ this.hasPrintedDynamicSection = true;
87
+ }
77
88
  const result = {
78
89
  description: test.description,
79
90
  status,
@@ -160,7 +171,7 @@ ${"\u2500".repeat(60)}`);
160
171
  });
161
172
  this.log(`
162
173
  \u{1F4A1} Run with Playwright for full validation:`);
163
- this.log(` testUiComponent('${this.componentName}', component, 'http://localhost:5173/')
174
+ this.log(` testUiComponent('${this.componentName}', null, 'http://localhost:5173/test-harness?component=component_name')
164
175
  `);
165
176
  }
166
177
  /**
@@ -184,9 +195,14 @@ ${"\u2500".repeat(60)}`);
184
195
  ${"\u2550".repeat(60)}`);
185
196
  this.log(`\u{1F4CA} Summary
186
197
  `);
198
+ const staticIcon = this.staticFailures === 0 ? "\u2705" : "\u274C";
199
+ const staticStatus = this.staticFailures === 0 ? "PASS" : "FAIL";
200
+ this.log(`${staticIcon} Static ARIA Tests: ${staticStatus}`);
201
+ this.log(` ${this.staticPasses}/${this.staticPasses + this.staticFailures} required attributes present`);
202
+ this.log("");
187
203
  if (totalFailures === 0 && this.skipped === 0 && this.optionalSuggestions === 0) {
188
204
  this.log(`\u2705 All ${totalRun} tests passed!`);
189
- this.log(` ${this.componentName} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
205
+ this.log(` ${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
190
206
  } else if (totalFailures === 0) {
191
207
  this.log(`\u2705 ${totalPasses}/${totalRun} required tests passed`);
192
208
  if (this.skipped > 0) {
@@ -195,7 +211,7 @@ ${"\u2550".repeat(60)}`);
195
211
  if (this.optionalSuggestions > 0) {
196
212
  this.log(`\u{1F4A1} ${this.optionalSuggestions} optional enhancement${this.optionalSuggestions > 1 ? "s" : ""} suggested`);
197
213
  }
198
- this.log(` ${this.componentName} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
214
+ this.log(` ${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
199
215
  } else {
200
216
  this.log(`\u274C ${totalFailures} test${totalFailures > 1 ? "s" : ""} failed`);
201
217
  this.log(`\u2705 ${totalPasses} test${totalPasses > 1 ? "s" : ""} passed`);
@@ -239,7 +255,7 @@ ${"\u2550".repeat(60)}`);
239
255
  }
240
256
  };
241
257
 
242
- // src/utils/test/contract/playwrightTestHarness.ts
258
+ // src/utils/test/src/playwrightTestHarness.ts
243
259
  import { chromium } from "playwright";
244
260
  var sharedBrowser = null;
245
261
  var sharedContext = null;
@@ -2,13 +2,13 @@ import {
2
2
  ContractReporter,
3
3
  contract_default,
4
4
  createTestPage
5
- } from "./chunk-GFKAJHCS.js";
5
+ } from "./chunk-AUJAN4RK.js";
6
6
  import {
7
7
  __export,
8
8
  __reExport
9
9
  } from "./chunk-I2KLQ2HA.js";
10
10
 
11
- // src/utils/test/contract/contractTestRunnerPlaywright.ts
11
+ // src/utils/test/src/contractTestRunnerPlaywright.ts
12
12
  import { readFileSync as readFileSync2 } from "fs";
13
13
 
14
14
  // node_modules/@playwright/test/index.mjs
@@ -233,7 +233,7 @@ var ComponentDetector = class {
233
233
  const contractData = readFileSync(resolvedPath, "utf-8");
234
234
  const componentContract = JSON.parse(contractData);
235
235
  const selectors = componentContract.selectors;
236
- if (componentName === "combobox") {
236
+ if (componentName.includes("combobox")) {
237
237
  const mainSelector = selectors.input || selectors.container;
238
238
  return new ComboboxComponentStrategy(mainSelector, selectors, actionTimeoutMs, assertionTimeoutMs);
239
239
  }
@@ -732,7 +732,7 @@ var AssertionRunner = class {
732
732
  }
733
733
  };
734
734
 
735
- // src/utils/test/contract/contractTestRunnerPlaywright.ts
735
+ // src/utils/test/src/contractTestRunnerPlaywright.ts
736
736
  async function runContractTestsPlaywright(componentName, url) {
737
737
  const reporter = new ContractReporter(true);
738
738
  const actionTimeoutMs = 400;
@@ -772,7 +772,7 @@ async function runContractTestsPlaywright(componentName, url) {
772
772
  throw new Error(`CRITICAL: No selector found in contract for ${componentName}`);
773
773
  }
774
774
  try {
775
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 28e3 });
775
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
776
776
  } catch (error) {
777
777
  throw new Error(
778
778
  `
@@ -787,24 +787,29 @@ This usually means:
787
787
  reporter.start(componentName, totalTests, apgUrl);
788
788
  if (componentName === "menu" && componentContract.selectors.trigger) {
789
789
  await page.locator(componentContract.selectors.trigger).first().waitFor({
790
- state: "visible",
790
+ state: "attached",
791
791
  timeout: 5e3
792
792
  }).catch(() => {
793
- console.warn("Menu trigger not visible, continuing with tests...");
794
793
  });
795
794
  }
795
+ const failuresBeforeStatic = failures.length;
796
796
  const staticAssertionRunner = new AssertionRunner(page, componentContract.selectors, assertionTimeoutMs);
797
797
  for (const test of componentContract.static[0]?.assertions || []) {
798
798
  if (test.target === "relative") continue;
799
+ const staticDescription = `${test.target}${test.attribute ? ` (${test.attribute})` : ""}`;
799
800
  const targetSelector = componentContract.selectors[test.target];
800
801
  if (!targetSelector) {
801
- failures.push(`Selector for target ${test.target} not found.`);
802
+ const failure = `Selector for target ${test.target} not found.`;
803
+ failures.push(failure);
804
+ reporter.reportStaticTest(staticDescription, false, failure);
802
805
  continue;
803
806
  }
804
807
  const target = page.locator(targetSelector).first();
805
808
  const exists = await target.count() > 0;
806
809
  if (!exists) {
807
- failures.push(`Target ${test.target} not found.`);
810
+ const failure = `Target ${test.target} not found.`;
811
+ failures.push(failure);
812
+ reporter.reportStaticTest(staticDescription, false, failure);
808
813
  continue;
809
814
  }
810
815
  const isRedundantCheck = (selector, attrName, expectedVal) => {
@@ -838,13 +843,19 @@ This usually means:
838
843
  }
839
844
  }
840
845
  if (!hasAny && !allRedundant) {
841
- failures.push(test.failureMessage + ` None of the attributes "${test.attribute}" are present.`);
846
+ const failure = test.failureMessage + ` None of the attributes "${test.attribute}" are present.`;
847
+ failures.push(failure);
848
+ reporter.reportStaticTest(staticDescription, false, failure);
842
849
  } else if (!allRedundant && hasAny) {
843
850
  passes.push(`At least one of the attributes "${test.attribute}" exists on the element.`);
851
+ reporter.reportStaticTest(staticDescription, true);
852
+ } else {
853
+ reporter.reportStaticTest(staticDescription, true);
844
854
  }
845
855
  } else {
846
856
  if (isRedundantCheck(targetSelector, test.attribute, test.expectedValue)) {
847
857
  passes.push(`${test.attribute}="${test.expectedValue}" on ${test.target} verified by selector (already present in: ${targetSelector}).`);
858
+ reporter.reportStaticTest(staticDescription, true);
848
859
  } else {
849
860
  const result = await staticAssertionRunner.validateAttribute(
850
861
  target,
@@ -856,8 +867,10 @@ This usually means:
856
867
  );
857
868
  if (result.success && result.passMessage) {
858
869
  passes.push(result.passMessage);
870
+ reporter.reportStaticTest(staticDescription, true);
859
871
  } else if (!result.success && result.failMessage) {
860
872
  failures.push(result.failMessage);
873
+ reporter.reportStaticTest(staticDescription, false, result.failMessage);
861
874
  }
862
875
  }
863
876
  }
@@ -936,8 +949,9 @@ This usually means:
936
949
  reporter.reportTest(dynamicTest, testPassed ? "pass" : "fail", failureMessage);
937
950
  }
938
951
  }
939
- const staticPassed = componentContract.static[0].assertions.length;
940
- const staticFailed = 0;
952
+ const staticTotal = componentContract.static[0].assertions.length;
953
+ const staticFailed = failures.length - failuresBeforeStatic;
954
+ const staticPassed = Math.max(0, staticTotal - staticFailed);
941
955
  reporter.reportStatic(staticPassed, staticFailed);
942
956
  reporter.summary(failures);
943
957
  } catch (error) {