aria-ease 6.4.10 → 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.
Files changed (38) 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 +73 -41
  9. package/dist/index.js +14 -12
  10. package/dist/src/{Types.d-DYfYR3Vc.d.cts → Types.d-yGC2bBaB.d.cts} +1 -1
  11. package/dist/src/{Types.d-DYfYR3Vc.d.ts → Types.d-yGC2bBaB.d.ts} +1 -1
  12. package/dist/src/accordion/index.d.cts +1 -1
  13. package/dist/src/accordion/index.d.ts +1 -1
  14. package/dist/src/block/index.d.cts +1 -1
  15. package/dist/src/block/index.d.ts +1 -1
  16. package/dist/src/checkbox/index.d.cts +1 -1
  17. package/dist/src/checkbox/index.d.ts +1 -1
  18. package/dist/src/combobox/index.d.cts +1 -1
  19. package/dist/src/combobox/index.d.ts +1 -1
  20. package/dist/src/menu/index.cjs +7 -7
  21. package/dist/src/menu/index.d.cts +1 -1
  22. package/dist/src/menu/index.d.ts +1 -1
  23. package/dist/src/menu/index.js +7 -7
  24. package/dist/src/radio/index.d.cts +1 -1
  25. package/dist/src/radio/index.d.ts +1 -1
  26. package/dist/src/tabs/index.d.cts +1 -1
  27. package/dist/src/tabs/index.d.ts +1 -1
  28. package/dist/src/toggle/index.d.cts +1 -1
  29. package/dist/src/toggle/index.d.ts +1 -1
  30. package/dist/src/utils/test/{contracts/AccordionContract.json → aria-contracts/accordion/accordion.contract.json} +20 -7
  31. package/dist/src/utils/test/{contracts/ComboboxContract.json → aria-contracts/combobox/combobox.listbox.contract.json} +17 -17
  32. package/dist/src/utils/test/{contracts/MenuContract.json → aria-contracts/menu/menu.contract.json} +42 -1
  33. package/dist/src/utils/test/{contracts/TabsContract.json → aria-contracts/tabs/tabs.contract.json} +20 -7
  34. package/dist/src/utils/test/{chunk-GFKAJHCS.js → chunk-AUJAN4RK.js} +33 -17
  35. package/dist/src/utils/test/{contractTestRunnerPlaywright-O7FF3X67.js → contractTestRunnerPlaywright-HL73FADJ.js} +25 -11
  36. package/dist/src/utils/test/index.cjs +65 -33
  37. package/dist/src/utils/test/index.js +6 -4
  38. package/package.json +2 -2
@@ -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) {
package/dist/index.cjs CHANGED
@@ -37,29 +37,29 @@ var init_contract = __esm({
37
37
  "src/utils/test/contract/contract.json"() {
38
38
  contract_default = {
39
39
  menu: {
40
- path: "./contracts/MenuContract.json",
40
+ path: "./aria-contracts/menu/menu.contract.json",
41
41
  component: "menu"
42
42
  },
43
- combobox: {
44
- path: "./contracts/ComboboxContract.json",
45
- component: "combobox"
43
+ "combobox.listbox": {
44
+ path: "./aria-contracts/combobox/combobox.listbox.contract.json",
45
+ component: "combobox.listbox"
46
46
  },
47
47
  accordion: {
48
- path: "./contracts/AccordionContract.json",
48
+ path: "./aria-contracts/accordion/accordion.contract.json",
49
49
  component: "accordion"
50
50
  },
51
51
  tabs: {
52
- path: "./contracts/TabsContract.json",
52
+ path: "./aria-contracts/tabs/tabs.contract.json",
53
53
  component: "tabs"
54
54
  }
55
55
  };
56
56
  }
57
57
  });
58
58
 
59
- // src/utils/test/contract/ContractReporter.ts
59
+ // src/utils/test/src/ContractReporter.ts
60
60
  var ContractReporter;
61
61
  var init_ContractReporter = __esm({
62
- "src/utils/test/contract/ContractReporter.ts"() {
62
+ "src/utils/test/src/ContractReporter.ts"() {
63
63
  "use strict";
64
64
  ContractReporter = class {
65
65
  startTime = 0;
@@ -72,6 +72,8 @@ var init_ContractReporter = __esm({
72
72
  optionalSuggestions = 0;
73
73
  isPlaywright = false;
74
74
  apgUrl = "https://www.w3.org/WAI/ARIA/apg/";
75
+ hasPrintedStaticSection = false;
76
+ hasPrintedDynamicSection = false;
75
77
  constructor(isPlaywright = false) {
76
78
  this.isPlaywright = isPlaywright;
77
79
  }
@@ -82,30 +84,32 @@ var init_ContractReporter = __esm({
82
84
  this.startTime = Date.now();
83
85
  this.componentName = componentName;
84
86
  this.totalTests = totalTests;
87
+ this.hasPrintedStaticSection = false;
88
+ this.hasPrintedDynamicSection = false;
85
89
  if (apgUrl) {
86
90
  this.apgUrl = apgUrl;
87
91
  }
88
92
  const mode = this.isPlaywright ? "Playwright (Real Browser)" : "jsdom (Fast)";
89
93
  this.log(`
90
94
  ${"\u2550".repeat(60)}`);
91
- this.log(`\u{1F50D} Testing ${componentName} Component - ${mode}`);
95
+ this.log(`\u{1F50D} Testing ${componentName.charAt(0).toUpperCase() + componentName.slice(1)} Component - ${mode}`);
92
96
  this.log(`${"\u2550".repeat(60)}
93
97
  `);
94
98
  }
95
99
  reportStatic(passes, failures) {
96
100
  this.staticPasses = passes;
97
101
  this.staticFailures = failures;
98
- const icon = failures === 0 ? "\u2705" : "\u274C";
99
- const status = failures === 0 ? "PASS" : "FAIL";
100
- this.log("");
101
- this.log(`${icon} Static ARIA Tests: ${status}`);
102
- this.log(` ${passes}/${passes + failures} required attributes present
103
- `);
104
102
  }
105
103
  /**
106
104
  * Report individual static test pass
107
105
  */
108
106
  reportStaticTest(description, passed, failureMessage) {
107
+ if (!this.hasPrintedStaticSection) {
108
+ this.log(`${"\u2500".repeat(60)}`);
109
+ this.log(`\u{1F9EA} Static Assertions`);
110
+ this.log(`${"\u2500".repeat(60)}`);
111
+ this.hasPrintedStaticSection = true;
112
+ }
109
113
  const icon = passed ? "\u2713" : "\u2717";
110
114
  this.log(` ${icon} ${description}`);
111
115
  if (!passed && failureMessage) {
@@ -116,6 +120,13 @@ ${"\u2550".repeat(60)}`);
116
120
  * Report individual dynamic test result
117
121
  */
118
122
  reportTest(test, status, failureMessage) {
123
+ if (!this.hasPrintedDynamicSection) {
124
+ this.log("");
125
+ this.log(`${"\u2500".repeat(60)}`);
126
+ this.log(`\u2328\uFE0F Dynamic Interaction Tests`);
127
+ this.log(`${"\u2500".repeat(60)}`);
128
+ this.hasPrintedDynamicSection = true;
129
+ }
119
130
  const result = {
120
131
  description: test.description,
121
132
  status,
@@ -202,7 +213,7 @@ ${"\u2500".repeat(60)}`);
202
213
  });
203
214
  this.log(`
204
215
  \u{1F4A1} Run with Playwright for full validation:`);
205
- this.log(` testUiComponent('${this.componentName}', component, 'http://localhost:5173/')
216
+ this.log(` testUiComponent('${this.componentName}', null, 'http://localhost:5173/test-harness?component=component_name')
206
217
  `);
207
218
  }
208
219
  /**
@@ -226,9 +237,14 @@ ${"\u2500".repeat(60)}`);
226
237
  ${"\u2550".repeat(60)}`);
227
238
  this.log(`\u{1F4CA} Summary
228
239
  `);
240
+ const staticIcon = this.staticFailures === 0 ? "\u2705" : "\u274C";
241
+ const staticStatus = this.staticFailures === 0 ? "PASS" : "FAIL";
242
+ this.log(`${staticIcon} Static ARIA Tests: ${staticStatus}`);
243
+ this.log(` ${this.staticPasses}/${this.staticPasses + this.staticFailures} required attributes present`);
244
+ this.log("");
229
245
  if (totalFailures === 0 && this.skipped === 0 && this.optionalSuggestions === 0) {
230
246
  this.log(`\u2705 All ${totalRun} tests passed!`);
231
- this.log(` ${this.componentName} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
247
+ this.log(` ${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
232
248
  } else if (totalFailures === 0) {
233
249
  this.log(`\u2705 ${totalPasses}/${totalRun} required tests passed`);
234
250
  if (this.skipped > 0) {
@@ -237,7 +253,7 @@ ${"\u2550".repeat(60)}`);
237
253
  if (this.optionalSuggestions > 0) {
238
254
  this.log(`\u{1F4A1} ${this.optionalSuggestions} optional enhancement${this.optionalSuggestions > 1 ? "s" : ""} suggested`);
239
255
  }
240
- this.log(` ${this.componentName} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
256
+ this.log(` ${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
241
257
  } else {
242
258
  this.log(`\u274C ${totalFailures} test${totalFailures > 1 ? "s" : ""} failed`);
243
259
  this.log(`\u2705 ${totalPasses} test${totalPasses > 1 ? "s" : ""} passed`);
@@ -283,7 +299,7 @@ ${"\u2550".repeat(60)}`);
283
299
  }
284
300
  });
285
301
 
286
- // src/utils/test/contract/playwrightTestHarness.ts
302
+ // src/utils/test/src/playwrightTestHarness.ts
287
303
  async function getOrCreateBrowser() {
288
304
  if (!sharedBrowser) {
289
305
  sharedBrowser = await import_playwright.chromium.launch({
@@ -325,7 +341,7 @@ async function closeSharedBrowser() {
325
341
  }
326
342
  var import_playwright, sharedBrowser, sharedContext;
327
343
  var init_playwrightTestHarness = __esm({
328
- "src/utils/test/contract/playwrightTestHarness.ts"() {
344
+ "src/utils/test/src/playwrightTestHarness.ts"() {
329
345
  "use strict";
330
346
  import_playwright = require("playwright");
331
347
  sharedBrowser = null;
@@ -597,7 +613,7 @@ var init_ComponentDetector = __esm({
597
613
  const contractData = (0, import_fs.readFileSync)(resolvedPath, "utf-8");
598
614
  const componentContract = JSON.parse(contractData);
599
615
  const selectors = componentContract.selectors;
600
- if (componentName === "combobox") {
616
+ if (componentName.includes("combobox")) {
601
617
  const mainSelector = selectors.input || selectors.container;
602
618
  return new ComboboxComponentStrategy(mainSelector, selectors, actionTimeoutMs, assertionTimeoutMs);
603
619
  }
@@ -1119,7 +1135,7 @@ var init_AssertionRunner = __esm({
1119
1135
  }
1120
1136
  });
1121
1137
 
1122
- // src/utils/test/contract/contractTestRunnerPlaywright.ts
1138
+ // src/utils/test/src/contractTestRunnerPlaywright.ts
1123
1139
  var contractTestRunnerPlaywright_exports = {};
1124
1140
  __export(contractTestRunnerPlaywright_exports, {
1125
1141
  runContractTestsPlaywright: () => runContractTestsPlaywright
@@ -1163,7 +1179,7 @@ async function runContractTestsPlaywright(componentName, url) {
1163
1179
  throw new Error(`CRITICAL: No selector found in contract for ${componentName}`);
1164
1180
  }
1165
1181
  try {
1166
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 28e3 });
1182
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
1167
1183
  } catch (error) {
1168
1184
  throw new Error(
1169
1185
  `
@@ -1178,24 +1194,29 @@ This usually means:
1178
1194
  reporter.start(componentName, totalTests, apgUrl);
1179
1195
  if (componentName === "menu" && componentContract.selectors.trigger) {
1180
1196
  await page.locator(componentContract.selectors.trigger).first().waitFor({
1181
- state: "visible",
1197
+ state: "attached",
1182
1198
  timeout: 5e3
1183
1199
  }).catch(() => {
1184
- console.warn("Menu trigger not visible, continuing with tests...");
1185
1200
  });
1186
1201
  }
1202
+ const failuresBeforeStatic = failures.length;
1187
1203
  const staticAssertionRunner = new AssertionRunner(page, componentContract.selectors, assertionTimeoutMs);
1188
1204
  for (const test of componentContract.static[0]?.assertions || []) {
1189
1205
  if (test.target === "relative") continue;
1206
+ const staticDescription = `${test.target}${test.attribute ? ` (${test.attribute})` : ""}`;
1190
1207
  const targetSelector = componentContract.selectors[test.target];
1191
1208
  if (!targetSelector) {
1192
- failures.push(`Selector for target ${test.target} not found.`);
1209
+ const failure = `Selector for target ${test.target} not found.`;
1210
+ failures.push(failure);
1211
+ reporter.reportStaticTest(staticDescription, false, failure);
1193
1212
  continue;
1194
1213
  }
1195
1214
  const target = page.locator(targetSelector).first();
1196
1215
  const exists = await target.count() > 0;
1197
1216
  if (!exists) {
1198
- failures.push(`Target ${test.target} not found.`);
1217
+ const failure = `Target ${test.target} not found.`;
1218
+ failures.push(failure);
1219
+ reporter.reportStaticTest(staticDescription, false, failure);
1199
1220
  continue;
1200
1221
  }
1201
1222
  const isRedundantCheck = (selector, attrName, expectedVal) => {
@@ -1229,13 +1250,19 @@ This usually means:
1229
1250
  }
1230
1251
  }
1231
1252
  if (!hasAny && !allRedundant) {
1232
- failures.push(test.failureMessage + ` None of the attributes "${test.attribute}" are present.`);
1253
+ const failure = test.failureMessage + ` None of the attributes "${test.attribute}" are present.`;
1254
+ failures.push(failure);
1255
+ reporter.reportStaticTest(staticDescription, false, failure);
1233
1256
  } else if (!allRedundant && hasAny) {
1234
1257
  passes.push(`At least one of the attributes "${test.attribute}" exists on the element.`);
1258
+ reporter.reportStaticTest(staticDescription, true);
1259
+ } else {
1260
+ reporter.reportStaticTest(staticDescription, true);
1235
1261
  }
1236
1262
  } else {
1237
1263
  if (isRedundantCheck(targetSelector, test.attribute, test.expectedValue)) {
1238
1264
  passes.push(`${test.attribute}="${test.expectedValue}" on ${test.target} verified by selector (already present in: ${targetSelector}).`);
1265
+ reporter.reportStaticTest(staticDescription, true);
1239
1266
  } else {
1240
1267
  const result = await staticAssertionRunner.validateAttribute(
1241
1268
  target,
@@ -1247,8 +1274,10 @@ This usually means:
1247
1274
  );
1248
1275
  if (result.success && result.passMessage) {
1249
1276
  passes.push(result.passMessage);
1277
+ reporter.reportStaticTest(staticDescription, true);
1250
1278
  } else if (!result.success && result.failMessage) {
1251
1279
  failures.push(result.failMessage);
1280
+ reporter.reportStaticTest(staticDescription, false, result.failMessage);
1252
1281
  }
1253
1282
  }
1254
1283
  }
@@ -1327,8 +1356,9 @@ This usually means:
1327
1356
  reporter.reportTest(dynamicTest, testPassed ? "pass" : "fail", failureMessage);
1328
1357
  }
1329
1358
  }
1330
- const staticPassed = componentContract.static[0].assertions.length;
1331
- const staticFailed = 0;
1359
+ const staticTotal = componentContract.static[0].assertions.length;
1360
+ const staticFailed = failures.length - failuresBeforeStatic;
1361
+ const staticPassed = Math.max(0, staticTotal - staticFailed);
1332
1362
  reporter.reportStatic(staticPassed, staticFailed);
1333
1363
  reporter.summary(failures);
1334
1364
  } catch (error) {
@@ -1358,7 +1388,7 @@ Make sure your dev server is running at ${url}`);
1358
1388
  }
1359
1389
  var import_fs2, import_meta3;
1360
1390
  var init_contractTestRunnerPlaywright = __esm({
1361
- "src/utils/test/contract/contractTestRunnerPlaywright.ts"() {
1391
+ "src/utils/test/src/contractTestRunnerPlaywright.ts"() {
1362
1392
  "use strict";
1363
1393
  import_fs2 = require("fs");
1364
1394
  init_contract();
@@ -2035,6 +2065,13 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
2035
2065
  };
2036
2066
  return nodeListLike;
2037
2067
  }
2068
+ function intializeMenuItems() {
2069
+ const items = getItems();
2070
+ items.forEach((item) => {
2071
+ item.setAttribute("role", "menuitem");
2072
+ });
2073
+ }
2074
+ intializeMenuItems();
2038
2075
  function isItemInNestedSubmenu(item) {
2039
2076
  let parent = item.parentElement;
2040
2077
  while (parent && parent !== menuDiv) {
@@ -2147,13 +2184,6 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId, callback }) {
2147
2184
  }
2148
2185
  }
2149
2186
  }
2150
- function intializeMenuItems() {
2151
- const items = getItems();
2152
- items.forEach((item) => {
2153
- item.setAttribute("role", "menuitem");
2154
- });
2155
- }
2156
- intializeMenuItems();
2157
2187
  function handleTriggerClick() {
2158
2188
  const isOpen = triggerButton.getAttribute("aria-expanded") === "true";
2159
2189
  if (isOpen) {
@@ -2929,7 +2959,7 @@ function makeTabsAccessible({ tabListId, tabsClass, tabPanelsClass, orientation
2929
2959
  // src/utils/test/src/test.ts
2930
2960
  var import_jest_axe = require("jest-axe");
2931
2961
 
2932
- // src/utils/test/contract/contractTestRunner.ts
2962
+ // src/utils/test/src/contractTestRunner.ts
2933
2963
  init_contract();
2934
2964
  var import_promises = __toESM(require("fs/promises"), 1);
2935
2965
  init_ContractReporter();
@@ -2949,6 +2979,7 @@ async function runContractTests(componentName, component) {
2949
2979
  const failures = [];
2950
2980
  const passes = [];
2951
2981
  const skipped = [];
2982
+ const failuresBeforeStatic = failures.length;
2952
2983
  for (const test of componentContract.static[0].assertions) {
2953
2984
  if (test.target !== "relative") {
2954
2985
  const selector = componentContract.selectors[test.target];
@@ -2987,8 +3018,9 @@ async function runContractTests(componentName, component) {
2987
3018
  skipped.push(dynamicTest.description);
2988
3019
  reporter.reportTest(dynamicTest, "skip");
2989
3020
  }
2990
- const staticPassed = componentContract.static[0].assertions.length;
2991
- const staticFailed = 0;
3021
+ const staticTotal = componentContract.static[0].assertions.length;
3022
+ const staticFailed = failures.length - failuresBeforeStatic;
3023
+ const staticPassed = Math.max(0, staticTotal - staticFailed);
2992
3024
  reporter.reportStatic(staticPassed, staticFailed);
2993
3025
  reporter.summary(failures);
2994
3026
  return { passes, failures, skipped };
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  ContractReporter,
3
3
  closeSharedBrowser,
4
4
  contract_default
5
- } from "./chunk-GFKAJHCS.js";
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/contract/contractTestRunner.ts
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 staticPassed = componentContract.static[0].assertions.length;
1492
- const staticFailed = 0;
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-7BCEDPZF.js");
1544
+ const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-7F756CFB.js");
1543
1545
  contract = await runContractTestsPlaywright(componentName, devServerUrl);
1544
1546
  } else {
1545
1547
  throw new Error(
@@ -88,4 +88,4 @@ interface MenuCallback {
88
88
  onOpenChange?: (isOpen: boolean) => void;
89
89
  }
90
90
 
91
- export type { AccordionConfig as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccessibilityInstance as a };
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 { AccordionConfig as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccessibilityInstance as a };
91
+ export type { AccessibilityInstance as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccordionConfig as a };
@@ -1,4 +1,4 @@
1
- import { A as AccordionConfig, a as AccessibilityInstance } from '../Types.d-DYfYR3Vc.cjs';
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.