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.
- package/bin/{chunk-GFKAJHCS.js → chunk-AUJAN4RK.js} +34 -18
- package/bin/cli.cjs +67 -35
- package/bin/cli.js +1 -1
- package/{dist/contractTestRunnerPlaywright-7BCEDPZF.js → bin/contractTestRunnerPlaywright-7F756CFB.js} +26 -12
- package/bin/{test-JGKWOL6J.js → test-C3CMRHSI.js} +7 -5
- package/dist/{chunk-GFKAJHCS.js → chunk-AUJAN4RK.js} +34 -18
- package/{bin/contractTestRunnerPlaywright-7BCEDPZF.js → dist/contractTestRunnerPlaywright-7F756CFB.js} +26 -12
- package/dist/index.cjs +148 -106
- package/dist/index.js +89 -77
- package/dist/src/block/index.cjs +1 -6
- package/dist/src/block/index.js +72 -1
- package/dist/src/menu/index.cjs +79 -147
- package/dist/src/menu/index.js +79 -23
- package/dist/src/utils/test/{contracts/AccordionContract.json → aria-contracts/accordion/accordion.contract.json} +21 -8
- package/dist/src/utils/test/{contracts/ComboboxContract.json → aria-contracts/combobox/combobox.listbox.contract.json} +18 -18
- package/dist/src/utils/test/{contracts/MenuContract.json → aria-contracts/menu/menu.contract.json} +43 -2
- package/dist/src/utils/test/{contracts/TabsContract.json → aria-contracts/tabs/tabs.contract.json} +21 -8
- package/dist/src/utils/test/{chunk-GFKAJHCS.js → chunk-AUJAN4RK.js} +33 -17
- package/dist/src/utils/test/{contractTestRunnerPlaywright-O7FF3X67.js → contractTestRunnerPlaywright-HL73FADJ.js} +25 -11
- package/dist/src/utils/test/index.cjs +65 -33
- package/dist/src/utils/test/index.js +6 -4
- package/package.json +2 -2
- 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/
|
|
4
|
+
path: "./aria-contracts/menu/menu.contract.json",
|
|
5
5
|
component: "menu"
|
|
6
6
|
},
|
|
7
|
-
combobox: {
|
|
8
|
-
path: "./contracts/
|
|
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/
|
|
12
|
+
path: "./aria-contracts/accordion/accordion.contract.json",
|
|
13
13
|
component: "accordion"
|
|
14
14
|
},
|
|
15
15
|
tabs: {
|
|
16
|
-
path: "./contracts/
|
|
16
|
+
path: "./aria-contracts/tabs/tabs.contract.json",
|
|
17
17
|
component: "tabs"
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
// src/utils/test/
|
|
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}',
|
|
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/
|
|
258
|
+
// src/utils/test/src/playwrightTestHarness.ts
|
|
243
259
|
import { chromium } from "playwright";
|
|
244
260
|
var sharedBrowser = null;
|
|
245
261
|
var sharedContext = null;
|
package/bin/cli.cjs
CHANGED
|
@@ -403,29 +403,29 @@ var init_contract = __esm({
|
|
|
403
403
|
"src/utils/test/contract/contract.json"() {
|
|
404
404
|
contract_default = {
|
|
405
405
|
menu: {
|
|
406
|
-
path: "./contracts/
|
|
406
|
+
path: "./aria-contracts/menu/menu.contract.json",
|
|
407
407
|
component: "menu"
|
|
408
408
|
},
|
|
409
|
-
combobox: {
|
|
410
|
-
path: "./contracts/
|
|
411
|
-
component: "combobox"
|
|
409
|
+
"combobox.listbox": {
|
|
410
|
+
path: "./aria-contracts/combobox/combobox.listbox.contract.json",
|
|
411
|
+
component: "combobox.listbox"
|
|
412
412
|
},
|
|
413
413
|
accordion: {
|
|
414
|
-
path: "./contracts/
|
|
414
|
+
path: "./aria-contracts/accordion/accordion.contract.json",
|
|
415
415
|
component: "accordion"
|
|
416
416
|
},
|
|
417
417
|
tabs: {
|
|
418
|
-
path: "./contracts/
|
|
418
|
+
path: "./aria-contracts/tabs/tabs.contract.json",
|
|
419
419
|
component: "tabs"
|
|
420
420
|
}
|
|
421
421
|
};
|
|
422
422
|
}
|
|
423
423
|
});
|
|
424
424
|
|
|
425
|
-
// src/utils/test/
|
|
425
|
+
// src/utils/test/src/ContractReporter.ts
|
|
426
426
|
var ContractReporter;
|
|
427
427
|
var init_ContractReporter = __esm({
|
|
428
|
-
"src/utils/test/
|
|
428
|
+
"src/utils/test/src/ContractReporter.ts"() {
|
|
429
429
|
"use strict";
|
|
430
430
|
ContractReporter = class {
|
|
431
431
|
startTime = 0;
|
|
@@ -438,6 +438,8 @@ var init_ContractReporter = __esm({
|
|
|
438
438
|
optionalSuggestions = 0;
|
|
439
439
|
isPlaywright = false;
|
|
440
440
|
apgUrl = "https://www.w3.org/WAI/ARIA/apg/";
|
|
441
|
+
hasPrintedStaticSection = false;
|
|
442
|
+
hasPrintedDynamicSection = false;
|
|
441
443
|
constructor(isPlaywright = false) {
|
|
442
444
|
this.isPlaywright = isPlaywright;
|
|
443
445
|
}
|
|
@@ -448,30 +450,32 @@ var init_ContractReporter = __esm({
|
|
|
448
450
|
this.startTime = Date.now();
|
|
449
451
|
this.componentName = componentName;
|
|
450
452
|
this.totalTests = totalTests;
|
|
453
|
+
this.hasPrintedStaticSection = false;
|
|
454
|
+
this.hasPrintedDynamicSection = false;
|
|
451
455
|
if (apgUrl) {
|
|
452
456
|
this.apgUrl = apgUrl;
|
|
453
457
|
}
|
|
454
458
|
const mode = this.isPlaywright ? "Playwright (Real Browser)" : "jsdom (Fast)";
|
|
455
459
|
this.log(`
|
|
456
460
|
${"\u2550".repeat(60)}`);
|
|
457
|
-
this.log(`\u{1F50D} Testing ${componentName} Component - ${mode}`);
|
|
461
|
+
this.log(`\u{1F50D} Testing ${componentName.charAt(0).toUpperCase() + componentName.slice(1)} Component - ${mode}`);
|
|
458
462
|
this.log(`${"\u2550".repeat(60)}
|
|
459
463
|
`);
|
|
460
464
|
}
|
|
461
465
|
reportStatic(passes, failures) {
|
|
462
466
|
this.staticPasses = passes;
|
|
463
467
|
this.staticFailures = failures;
|
|
464
|
-
const icon = failures === 0 ? "\u2705" : "\u274C";
|
|
465
|
-
const status = failures === 0 ? "PASS" : "FAIL";
|
|
466
|
-
this.log("");
|
|
467
|
-
this.log(`${icon} Static ARIA Tests: ${status}`);
|
|
468
|
-
this.log(` ${passes}/${passes + failures} required attributes present
|
|
469
|
-
`);
|
|
470
468
|
}
|
|
471
469
|
/**
|
|
472
470
|
* Report individual static test pass
|
|
473
471
|
*/
|
|
474
472
|
reportStaticTest(description, passed, failureMessage) {
|
|
473
|
+
if (!this.hasPrintedStaticSection) {
|
|
474
|
+
this.log(`${"\u2500".repeat(60)}`);
|
|
475
|
+
this.log(`\u{1F9EA} Static Assertions`);
|
|
476
|
+
this.log(`${"\u2500".repeat(60)}`);
|
|
477
|
+
this.hasPrintedStaticSection = true;
|
|
478
|
+
}
|
|
475
479
|
const icon = passed ? "\u2713" : "\u2717";
|
|
476
480
|
this.log(` ${icon} ${description}`);
|
|
477
481
|
if (!passed && failureMessage) {
|
|
@@ -482,6 +486,13 @@ ${"\u2550".repeat(60)}`);
|
|
|
482
486
|
* Report individual dynamic test result
|
|
483
487
|
*/
|
|
484
488
|
reportTest(test, status, failureMessage) {
|
|
489
|
+
if (!this.hasPrintedDynamicSection) {
|
|
490
|
+
this.log("");
|
|
491
|
+
this.log(`${"\u2500".repeat(60)}`);
|
|
492
|
+
this.log(`\u2328\uFE0F Dynamic Interaction Tests`);
|
|
493
|
+
this.log(`${"\u2500".repeat(60)}`);
|
|
494
|
+
this.hasPrintedDynamicSection = true;
|
|
495
|
+
}
|
|
485
496
|
const result = {
|
|
486
497
|
description: test.description,
|
|
487
498
|
status,
|
|
@@ -568,7 +579,7 @@ ${"\u2500".repeat(60)}`);
|
|
|
568
579
|
});
|
|
569
580
|
this.log(`
|
|
570
581
|
\u{1F4A1} Run with Playwright for full validation:`);
|
|
571
|
-
this.log(` testUiComponent('${this.componentName}',
|
|
582
|
+
this.log(` testUiComponent('${this.componentName}', null, 'http://localhost:5173/test-harness?component=component_name')
|
|
572
583
|
`);
|
|
573
584
|
}
|
|
574
585
|
/**
|
|
@@ -592,9 +603,14 @@ ${"\u2500".repeat(60)}`);
|
|
|
592
603
|
${"\u2550".repeat(60)}`);
|
|
593
604
|
this.log(`\u{1F4CA} Summary
|
|
594
605
|
`);
|
|
606
|
+
const staticIcon = this.staticFailures === 0 ? "\u2705" : "\u274C";
|
|
607
|
+
const staticStatus = this.staticFailures === 0 ? "PASS" : "FAIL";
|
|
608
|
+
this.log(`${staticIcon} Static ARIA Tests: ${staticStatus}`);
|
|
609
|
+
this.log(` ${this.staticPasses}/${this.staticPasses + this.staticFailures} required attributes present`);
|
|
610
|
+
this.log("");
|
|
595
611
|
if (totalFailures === 0 && this.skipped === 0 && this.optionalSuggestions === 0) {
|
|
596
612
|
this.log(`\u2705 All ${totalRun} tests passed!`);
|
|
597
|
-
this.log(` ${this.componentName} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
|
|
613
|
+
this.log(` ${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
|
|
598
614
|
} else if (totalFailures === 0) {
|
|
599
615
|
this.log(`\u2705 ${totalPasses}/${totalRun} required tests passed`);
|
|
600
616
|
if (this.skipped > 0) {
|
|
@@ -603,7 +619,7 @@ ${"\u2550".repeat(60)}`);
|
|
|
603
619
|
if (this.optionalSuggestions > 0) {
|
|
604
620
|
this.log(`\u{1F4A1} ${this.optionalSuggestions} optional enhancement${this.optionalSuggestions > 1 ? "s" : ""} suggested`);
|
|
605
621
|
}
|
|
606
|
-
this.log(` ${this.componentName} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
|
|
622
|
+
this.log(` ${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)} component meets WAI-ARIA expectations for Roles, States, Properties, and Keyboard Interactions \u2713`);
|
|
607
623
|
} else {
|
|
608
624
|
this.log(`\u274C ${totalFailures} test${totalFailures > 1 ? "s" : ""} failed`);
|
|
609
625
|
this.log(`\u2705 ${totalPasses} test${totalPasses > 1 ? "s" : ""} passed`);
|
|
@@ -649,7 +665,7 @@ ${"\u2550".repeat(60)}`);
|
|
|
649
665
|
}
|
|
650
666
|
});
|
|
651
667
|
|
|
652
|
-
// src/utils/test/
|
|
668
|
+
// src/utils/test/src/contractTestRunner.ts
|
|
653
669
|
async function runContractTests(componentName, component) {
|
|
654
670
|
const reporter = new ContractReporter(false);
|
|
655
671
|
const contractTyped = contract_default;
|
|
@@ -665,6 +681,7 @@ async function runContractTests(componentName, component) {
|
|
|
665
681
|
const failures = [];
|
|
666
682
|
const passes = [];
|
|
667
683
|
const skipped = [];
|
|
684
|
+
const failuresBeforeStatic = failures.length;
|
|
668
685
|
for (const test of componentContract.static[0].assertions) {
|
|
669
686
|
if (test.target !== "relative") {
|
|
670
687
|
const selector = componentContract.selectors[test.target];
|
|
@@ -703,15 +720,16 @@ async function runContractTests(componentName, component) {
|
|
|
703
720
|
skipped.push(dynamicTest.description);
|
|
704
721
|
reporter.reportTest(dynamicTest, "skip");
|
|
705
722
|
}
|
|
706
|
-
const
|
|
707
|
-
const staticFailed =
|
|
723
|
+
const staticTotal = componentContract.static[0].assertions.length;
|
|
724
|
+
const staticFailed = failures.length - failuresBeforeStatic;
|
|
725
|
+
const staticPassed = Math.max(0, staticTotal - staticFailed);
|
|
708
726
|
reporter.reportStatic(staticPassed, staticFailed);
|
|
709
727
|
reporter.summary(failures);
|
|
710
728
|
return { passes, failures, skipped };
|
|
711
729
|
}
|
|
712
730
|
var import_promises, import_meta;
|
|
713
731
|
var init_contractTestRunner = __esm({
|
|
714
|
-
"src/utils/test/
|
|
732
|
+
"src/utils/test/src/contractTestRunner.ts"() {
|
|
715
733
|
"use strict";
|
|
716
734
|
init_contract();
|
|
717
735
|
import_promises = __toESM(require("fs/promises"), 1);
|
|
@@ -720,7 +738,7 @@ var init_contractTestRunner = __esm({
|
|
|
720
738
|
}
|
|
721
739
|
});
|
|
722
740
|
|
|
723
|
-
// src/utils/test/
|
|
741
|
+
// src/utils/test/src/playwrightTestHarness.ts
|
|
724
742
|
async function getOrCreateBrowser() {
|
|
725
743
|
if (!sharedBrowser) {
|
|
726
744
|
sharedBrowser = await import_playwright3.chromium.launch({
|
|
@@ -762,7 +780,7 @@ async function closeSharedBrowser() {
|
|
|
762
780
|
}
|
|
763
781
|
var import_playwright3, sharedBrowser, sharedContext;
|
|
764
782
|
var init_playwrightTestHarness = __esm({
|
|
765
|
-
"src/utils/test/
|
|
783
|
+
"src/utils/test/src/playwrightTestHarness.ts"() {
|
|
766
784
|
"use strict";
|
|
767
785
|
import_playwright3 = require("playwright");
|
|
768
786
|
sharedBrowser = null;
|
|
@@ -1034,7 +1052,7 @@ var init_ComponentDetector = __esm({
|
|
|
1034
1052
|
const contractData = (0, import_fs.readFileSync)(resolvedPath, "utf-8");
|
|
1035
1053
|
const componentContract = JSON.parse(contractData);
|
|
1036
1054
|
const selectors = componentContract.selectors;
|
|
1037
|
-
if (componentName
|
|
1055
|
+
if (componentName.includes("combobox")) {
|
|
1038
1056
|
const mainSelector = selectors.input || selectors.container;
|
|
1039
1057
|
return new ComboboxComponentStrategy(mainSelector, selectors, actionTimeoutMs, assertionTimeoutMs);
|
|
1040
1058
|
}
|
|
@@ -1556,7 +1574,7 @@ var init_AssertionRunner = __esm({
|
|
|
1556
1574
|
}
|
|
1557
1575
|
});
|
|
1558
1576
|
|
|
1559
|
-
// src/utils/test/
|
|
1577
|
+
// src/utils/test/src/contractTestRunnerPlaywright.ts
|
|
1560
1578
|
var contractTestRunnerPlaywright_exports = {};
|
|
1561
1579
|
__export(contractTestRunnerPlaywright_exports, {
|
|
1562
1580
|
runContractTestsPlaywright: () => runContractTestsPlaywright
|
|
@@ -1600,7 +1618,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
1600
1618
|
throw new Error(`CRITICAL: No selector found in contract for ${componentName}`);
|
|
1601
1619
|
}
|
|
1602
1620
|
try {
|
|
1603
|
-
await page.locator(mainSelector).first().waitFor({ state: "attached", timeout:
|
|
1621
|
+
await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
|
|
1604
1622
|
} catch (error) {
|
|
1605
1623
|
throw new Error(
|
|
1606
1624
|
`
|
|
@@ -1615,24 +1633,29 @@ This usually means:
|
|
|
1615
1633
|
reporter.start(componentName, totalTests, apgUrl);
|
|
1616
1634
|
if (componentName === "menu" && componentContract.selectors.trigger) {
|
|
1617
1635
|
await page.locator(componentContract.selectors.trigger).first().waitFor({
|
|
1618
|
-
state: "
|
|
1636
|
+
state: "attached",
|
|
1619
1637
|
timeout: 5e3
|
|
1620
1638
|
}).catch(() => {
|
|
1621
|
-
console.warn("Menu trigger not visible, continuing with tests...");
|
|
1622
1639
|
});
|
|
1623
1640
|
}
|
|
1641
|
+
const failuresBeforeStatic = failures.length;
|
|
1624
1642
|
const staticAssertionRunner = new AssertionRunner(page, componentContract.selectors, assertionTimeoutMs);
|
|
1625
1643
|
for (const test of componentContract.static[0]?.assertions || []) {
|
|
1626
1644
|
if (test.target === "relative") continue;
|
|
1645
|
+
const staticDescription = `${test.target}${test.attribute ? ` (${test.attribute})` : ""}`;
|
|
1627
1646
|
const targetSelector = componentContract.selectors[test.target];
|
|
1628
1647
|
if (!targetSelector) {
|
|
1629
|
-
|
|
1648
|
+
const failure = `Selector for target ${test.target} not found.`;
|
|
1649
|
+
failures.push(failure);
|
|
1650
|
+
reporter.reportStaticTest(staticDescription, false, failure);
|
|
1630
1651
|
continue;
|
|
1631
1652
|
}
|
|
1632
1653
|
const target = page.locator(targetSelector).first();
|
|
1633
1654
|
const exists = await target.count() > 0;
|
|
1634
1655
|
if (!exists) {
|
|
1635
|
-
|
|
1656
|
+
const failure = `Target ${test.target} not found.`;
|
|
1657
|
+
failures.push(failure);
|
|
1658
|
+
reporter.reportStaticTest(staticDescription, false, failure);
|
|
1636
1659
|
continue;
|
|
1637
1660
|
}
|
|
1638
1661
|
const isRedundantCheck = (selector, attrName, expectedVal) => {
|
|
@@ -1666,13 +1689,19 @@ This usually means:
|
|
|
1666
1689
|
}
|
|
1667
1690
|
}
|
|
1668
1691
|
if (!hasAny && !allRedundant) {
|
|
1669
|
-
|
|
1692
|
+
const failure = test.failureMessage + ` None of the attributes "${test.attribute}" are present.`;
|
|
1693
|
+
failures.push(failure);
|
|
1694
|
+
reporter.reportStaticTest(staticDescription, false, failure);
|
|
1670
1695
|
} else if (!allRedundant && hasAny) {
|
|
1671
1696
|
passes.push(`At least one of the attributes "${test.attribute}" exists on the element.`);
|
|
1697
|
+
reporter.reportStaticTest(staticDescription, true);
|
|
1698
|
+
} else {
|
|
1699
|
+
reporter.reportStaticTest(staticDescription, true);
|
|
1672
1700
|
}
|
|
1673
1701
|
} else {
|
|
1674
1702
|
if (isRedundantCheck(targetSelector, test.attribute, test.expectedValue)) {
|
|
1675
1703
|
passes.push(`${test.attribute}="${test.expectedValue}" on ${test.target} verified by selector (already present in: ${targetSelector}).`);
|
|
1704
|
+
reporter.reportStaticTest(staticDescription, true);
|
|
1676
1705
|
} else {
|
|
1677
1706
|
const result = await staticAssertionRunner.validateAttribute(
|
|
1678
1707
|
target,
|
|
@@ -1684,8 +1713,10 @@ This usually means:
|
|
|
1684
1713
|
);
|
|
1685
1714
|
if (result.success && result.passMessage) {
|
|
1686
1715
|
passes.push(result.passMessage);
|
|
1716
|
+
reporter.reportStaticTest(staticDescription, true);
|
|
1687
1717
|
} else if (!result.success && result.failMessage) {
|
|
1688
1718
|
failures.push(result.failMessage);
|
|
1719
|
+
reporter.reportStaticTest(staticDescription, false, result.failMessage);
|
|
1689
1720
|
}
|
|
1690
1721
|
}
|
|
1691
1722
|
}
|
|
@@ -1764,8 +1795,9 @@ This usually means:
|
|
|
1764
1795
|
reporter.reportTest(dynamicTest, testPassed ? "pass" : "fail", failureMessage);
|
|
1765
1796
|
}
|
|
1766
1797
|
}
|
|
1767
|
-
const
|
|
1768
|
-
const staticFailed =
|
|
1798
|
+
const staticTotal = componentContract.static[0].assertions.length;
|
|
1799
|
+
const staticFailed = failures.length - failuresBeforeStatic;
|
|
1800
|
+
const staticPassed = Math.max(0, staticTotal - staticFailed);
|
|
1769
1801
|
reporter.reportStatic(staticPassed, staticFailed);
|
|
1770
1802
|
reporter.summary(failures);
|
|
1771
1803
|
} catch (error) {
|
|
@@ -1795,7 +1827,7 @@ Make sure your dev server is running at ${url}`);
|
|
|
1795
1827
|
}
|
|
1796
1828
|
var import_fs2, import_meta3;
|
|
1797
1829
|
var init_contractTestRunnerPlaywright = __esm({
|
|
1798
|
-
"src/utils/test/
|
|
1830
|
+
"src/utils/test/src/contractTestRunnerPlaywright.ts"() {
|
|
1799
1831
|
"use strict";
|
|
1800
1832
|
import_fs2 = require("fs");
|
|
1801
1833
|
init_contract();
|
package/bin/cli.js
CHANGED
|
@@ -237,7 +237,7 @@ program.command("audit").description("Run axe-core powered accessibility audit o
|
|
|
237
237
|
process.exit(1);
|
|
238
238
|
});
|
|
239
239
|
program.command("test").description("Run core a11y accessibility standard tests on UI components").action(async () => {
|
|
240
|
-
const { runTest } = await import("./test-
|
|
240
|
+
const { runTest } = await import("./test-C3CMRHSI.js");
|
|
241
241
|
runTest();
|
|
242
242
|
});
|
|
243
243
|
program.command("help").description("Display help information").action(() => {
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
ContractReporter,
|
|
3
3
|
contract_default,
|
|
4
4
|
createTestPage
|
|
5
|
-
} from "./chunk-
|
|
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/
|
|
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
|
|
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/
|
|
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:
|
|
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: "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
940
|
-
const staticFailed =
|
|
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) {
|
|
@@ -2,13 +2,13 @@ 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/utils/test/src/test.ts
|
|
9
9
|
import { axe } from "jest-axe";
|
|
10
10
|
|
|
11
|
-
// src/utils/test/
|
|
11
|
+
// src/utils/test/src/contractTestRunner.ts
|
|
12
12
|
import fs from "fs/promises";
|
|
13
13
|
async function runContractTests(componentName, component) {
|
|
14
14
|
const reporter = new ContractReporter(false);
|
|
@@ -25,6 +25,7 @@ async function runContractTests(componentName, component) {
|
|
|
25
25
|
const failures = [];
|
|
26
26
|
const passes = [];
|
|
27
27
|
const skipped = [];
|
|
28
|
+
const failuresBeforeStatic = failures.length;
|
|
28
29
|
for (const test of componentContract.static[0].assertions) {
|
|
29
30
|
if (test.target !== "relative") {
|
|
30
31
|
const selector = componentContract.selectors[test.target];
|
|
@@ -63,8 +64,9 @@ async function runContractTests(componentName, component) {
|
|
|
63
64
|
skipped.push(dynamicTest.description);
|
|
64
65
|
reporter.reportTest(dynamicTest, "skip");
|
|
65
66
|
}
|
|
66
|
-
const
|
|
67
|
-
const staticFailed =
|
|
67
|
+
const staticTotal = componentContract.static[0].assertions.length;
|
|
68
|
+
const staticFailed = failures.length - failuresBeforeStatic;
|
|
69
|
+
const staticPassed = Math.max(0, staticTotal - staticFailed);
|
|
68
70
|
reporter.reportStatic(staticPassed, staticFailed);
|
|
69
71
|
reporter.summary(failures);
|
|
70
72
|
return { passes, failures, skipped };
|
|
@@ -114,7 +116,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
114
116
|
const devServerUrl = await checkDevServer(url);
|
|
115
117
|
if (devServerUrl) {
|
|
116
118
|
console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
|
|
117
|
-
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-
|
|
119
|
+
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-7F756CFB.js");
|
|
118
120
|
contract = await runContractTestsPlaywright(componentName, devServerUrl);
|
|
119
121
|
} else {
|
|
120
122
|
throw new Error(
|