aria-ease 2.2.2 → 2.3.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 (101) hide show
  1. package/README.md +387 -30
  2. package/bin/cli.cjs +475 -0
  3. package/bin/cli.cjs.map +1 -0
  4. package/bin/cli.d.ts.map +1 -0
  5. package/bin/cli.js +452 -0
  6. package/bin/cli.js.map +1 -0
  7. package/bin/{audit-cli.ts → cli.ts} +35 -26
  8. package/bin/configLoader.d.ts +19 -0
  9. package/bin/configLoader.d.ts.map +1 -0
  10. package/bin/configLoader.js +155 -0
  11. package/bin/configLoader.ts +170 -0
  12. package/bin/contractTestRunnerPlaywright-2LQHVMXT.js +426 -0
  13. package/bin/contractTestRunnerPlaywright-2LQHVMXT.js.map +1 -0
  14. package/dist/chunk-4F6O5RKZ.js +207 -0
  15. package/dist/chunk-4F6O5RKZ.js.map +1 -0
  16. package/dist/contractTestRunnerPlaywright-FM6MK6DY.js +255 -0
  17. package/dist/contractTestRunnerPlaywright-FM6MK6DY.js.map +1 -0
  18. package/dist/index.cjs +13642 -233
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +100 -7
  21. package/dist/index.d.ts +100 -7
  22. package/dist/index.js +13189 -7
  23. package/dist/index.js.map +1 -1
  24. package/dist/{Types.d-p85gN5m_.d.cts → src/Types.d-BbztRe-S.d.cts} +0 -5
  25. package/dist/{Types.d-p85gN5m_.d.ts → src/Types.d-BbztRe-S.d.ts} +0 -5
  26. package/dist/src/accordion/index.cjs +25 -19
  27. package/dist/src/accordion/index.cjs.map +1 -1
  28. package/dist/src/accordion/index.d.cts +1 -1
  29. package/dist/src/accordion/index.d.ts +1 -1
  30. package/dist/src/accordion/index.js +28 -1
  31. package/dist/src/accordion/index.js.map +1 -1
  32. package/dist/src/block/index.cjs +98 -99
  33. package/dist/src/block/index.cjs.map +1 -1
  34. package/dist/src/block/index.d.cts +2 -2
  35. package/dist/src/block/index.d.ts +2 -2
  36. package/dist/src/block/index.js +41 -2
  37. package/dist/src/block/index.js.map +1 -1
  38. package/dist/src/checkbox/index.cjs +30 -13
  39. package/dist/src/checkbox/index.cjs.map +1 -1
  40. package/dist/src/checkbox/index.d.cts +1 -1
  41. package/dist/src/checkbox/index.d.ts +1 -1
  42. package/dist/src/checkbox/index.js +33 -1
  43. package/dist/src/checkbox/index.js.map +1 -1
  44. package/dist/src/chunk-MNMWQWXH.js +117 -0
  45. package/dist/src/chunk-MNMWQWXH.js.map +1 -0
  46. package/dist/src/menu/index.cjs +208 -130
  47. package/dist/src/menu/index.cjs.map +1 -1
  48. package/dist/src/menu/index.d.cts +9 -3
  49. package/dist/src/menu/index.d.ts +9 -3
  50. package/dist/src/menu/index.js +118 -2
  51. package/dist/src/menu/index.js.map +1 -1
  52. package/dist/src/radio/index.cjs +29 -16
  53. package/dist/src/radio/index.cjs.map +1 -1
  54. package/dist/src/radio/index.d.cts +1 -1
  55. package/dist/src/radio/index.d.ts +1 -1
  56. package/dist/src/radio/index.js +32 -1
  57. package/dist/src/radio/index.js.map +1 -1
  58. package/dist/src/toggle/index.cjs +26 -16
  59. package/dist/src/toggle/index.cjs.map +1 -1
  60. package/dist/src/toggle/index.d.cts +1 -1
  61. package/dist/src/toggle/index.d.ts +1 -1
  62. package/dist/src/toggle/index.js +29 -1
  63. package/dist/src/toggle/index.js.map +1 -1
  64. package/dist/src/utils/test/chunk-UAS6V5MH.js +203 -0
  65. package/dist/src/utils/test/chunk-UAS6V5MH.js.map +1 -0
  66. package/dist/src/utils/test/contractTestRunnerPlaywright-IBC4FHWK.js +251 -0
  67. package/dist/src/utils/test/contractTestRunnerPlaywright-IBC4FHWK.js.map +1 -0
  68. package/dist/src/utils/test/contracts/MenuContract.json +343 -0
  69. package/dist/src/utils/test/index.cjs +13092 -0
  70. package/dist/src/utils/test/index.cjs.map +1 -0
  71. package/dist/src/utils/test/index.d.cts +16 -0
  72. package/dist/src/utils/test/index.d.ts +16 -0
  73. package/dist/src/utils/test/index.js +12608 -0
  74. package/dist/src/utils/test/index.js.map +1 -0
  75. package/package.json +27 -12
  76. package/bin/audit-cli.cjs +0 -841
  77. package/bin/audit-cli.cjs.map +0 -1
  78. package/bin/audit-cli.js +0 -744
  79. package/bin/audit-cli.js.map +0 -1
  80. package/dist/chunk-4366LRNM.js +0 -38
  81. package/dist/chunk-4366LRNM.js.map +0 -1
  82. package/dist/chunk-5HQ6LLC5.js +0 -21
  83. package/dist/chunk-5HQ6LLC5.js.map +0 -1
  84. package/dist/chunk-FBQ5LF2T.js +0 -21
  85. package/dist/chunk-FBQ5LF2T.js.map +0 -1
  86. package/dist/chunk-KVTLMA4J.js +0 -58
  87. package/dist/chunk-KVTLMA4J.js.map +0 -1
  88. package/dist/chunk-MEA5U2G4.js +0 -24
  89. package/dist/chunk-MEA5U2G4.js.map +0 -1
  90. package/dist/chunk-RK3JUAFZ.js +0 -18
  91. package/dist/chunk-RK3JUAFZ.js.map +0 -1
  92. package/dist/chunk-RT5IROW4.js +0 -99
  93. package/dist/chunk-RT5IROW4.js.map +0 -1
  94. package/dist/src/utils/audit/audit.cjs +0 -234
  95. package/dist/src/utils/audit/audit.cjs.map +0 -1
  96. package/dist/src/utils/audit/audit.d.cts +0 -5
  97. package/dist/src/utils/audit/audit.d.ts +0 -5
  98. package/dist/src/utils/audit/audit.js +0 -227
  99. package/dist/src/utils/audit/audit.js.map +0 -1
  100. /package/bin/{audit-cli.d.cts → cli.d.cts} +0 -0
  101. /package/bin/{audit-cli.d.ts → cli.d.ts} +0 -0
@@ -0,0 +1,207 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // src/utils/test/contract/contract.json
28
+ var contract_default = {
29
+ menu: {
30
+ path: "./contracts/MenuContract.json",
31
+ component: "menu"
32
+ }
33
+ };
34
+
35
+ // src/utils/test/contract/ContractReporter.ts
36
+ var ContractReporter = class {
37
+ startTime = 0;
38
+ componentName = "";
39
+ staticPasses = 0;
40
+ staticFailures = 0;
41
+ dynamicResults = [];
42
+ totalTests = 0;
43
+ skipped = 0;
44
+ isPlaywright = false;
45
+ constructor(isPlaywright = false) {
46
+ this.isPlaywright = isPlaywright;
47
+ }
48
+ log(message) {
49
+ process.stderr.write(message + "\n");
50
+ }
51
+ start(componentName, totalTests) {
52
+ this.startTime = Date.now();
53
+ this.componentName = componentName;
54
+ this.totalTests = totalTests;
55
+ const mode = this.isPlaywright ? "Playwright (Real Browser)" : "jsdom (Fast)";
56
+ this.log(`
57
+ ${"\u2550".repeat(60)}`);
58
+ this.log(`\u{1F50D} Testing ${componentName} Component - ${mode}`);
59
+ this.log(`${"\u2550".repeat(60)}
60
+ `);
61
+ }
62
+ reportStatic(passes, failures) {
63
+ this.staticPasses = passes;
64
+ this.staticFailures = failures;
65
+ const icon = failures === 0 ? "\u2705" : "\u274C";
66
+ const status = failures === 0 ? "PASS" : "FAIL";
67
+ this.log(`${icon} Static ARIA Tests: ${status}`);
68
+ this.log(` ${passes}/${passes + failures} required attributes present
69
+ `);
70
+ }
71
+ /**
72
+ * Report individual dynamic test result
73
+ */
74
+ reportTest(test, status, failureMessage) {
75
+ const result = {
76
+ description: test.description,
77
+ status,
78
+ failureMessage
79
+ };
80
+ if (status === "skip" && test.requiresBrowser) {
81
+ result.skipReason = "Requires real browser (addEventListener events)";
82
+ }
83
+ this.dynamicResults.push(result);
84
+ const icons = { pass: "\u2713", fail: "\u2717", skip: "\u25CB" };
85
+ this.log(` ${icons[status]} ${test.description}`);
86
+ if (status === "skip" && !this.isPlaywright) {
87
+ this.log(` \u21B3 Skipped in jsdom (runs in Playwright)`);
88
+ }
89
+ if (status === "fail" && failureMessage) {
90
+ this.log(` \u21B3 ${failureMessage}`);
91
+ }
92
+ }
93
+ /**
94
+ * Report all failures with actionable context
95
+ */
96
+ reportFailures(failures) {
97
+ if (failures.length === 0) return;
98
+ this.log(`
99
+ ${"\u2500".repeat(60)}`);
100
+ this.log(`\u274C Failures (${failures.length}):
101
+ `);
102
+ failures.forEach((failure, index) => {
103
+ this.log(`${index + 1}. ${failure}`);
104
+ if (failure.includes("aria-")) {
105
+ this.log(` \u{1F4A1} Add the missing ARIA attribute to improve screen reader support`);
106
+ } else if (failure.includes("focus")) {
107
+ this.log(` \u{1F4A1} Check keyboard event handlers and focus management`);
108
+ } else if (failure.includes("visible")) {
109
+ this.log(` \u{1F4A1} Verify display/visibility styles and state management`);
110
+ }
111
+ this.log("");
112
+ });
113
+ }
114
+ /**
115
+ * Report skipped tests with helpful context
116
+ */
117
+ reportSkipped() {
118
+ if (this.skipped === 0 || this.isPlaywright) return;
119
+ const skippedTests = this.dynamicResults.filter((r) => r.status === "skip");
120
+ this.log(`
121
+ ${"\u2500".repeat(60)}`);
122
+ this.log(`\u2139\uFE0F Skipped Tests (${this.skipped}):
123
+ `);
124
+ this.log(`These tests use native keyboard events via addEventListener,`);
125
+ this.log(`which jsdom cannot simulate. They run successfully in Playwright.
126
+ `);
127
+ skippedTests.forEach((test, index) => {
128
+ this.log(`${index + 1}. ${test.description}`);
129
+ });
130
+ this.log(`
131
+ \u{1F4A1} Run with Playwright for full validation:`);
132
+ this.log(` testUiComponent('${this.componentName}', component, 'http://localhost:5173/')
133
+ `);
134
+ }
135
+ /**
136
+ * Generate final summary with statistics
137
+ */
138
+ summary(failures) {
139
+ const duration = Date.now() - this.startTime;
140
+ const dynamicPasses = this.dynamicResults.filter((r) => r.status === "pass").length;
141
+ const dynamicFailures = this.dynamicResults.filter((r) => r.status === "fail").length;
142
+ this.skipped = this.dynamicResults.filter((r) => r.status === "skip").length;
143
+ const totalPasses = this.staticPasses + dynamicPasses;
144
+ const totalFailures = this.staticFailures + dynamicFailures;
145
+ const totalRun = totalPasses + totalFailures;
146
+ if (failures.length > 0) {
147
+ this.reportFailures(failures);
148
+ }
149
+ this.reportSkipped();
150
+ this.log(`
151
+ ${"\u2550".repeat(60)}`);
152
+ this.log(`\u{1F4CA} Summary
153
+ `);
154
+ if (totalFailures === 0 && this.skipped === 0) {
155
+ this.log(`\u2705 All ${totalRun} tests passed!`);
156
+ this.log(` ${this.componentName} component meets APG and WCAG guidelines \u2713`);
157
+ } else if (totalFailures === 0) {
158
+ this.log(`\u2705 ${totalPasses}/${totalRun} tests passed`);
159
+ this.log(`\u25CB ${this.skipped} tests skipped (jsdom limitation)`);
160
+ this.log(` ${this.componentName} component works correctly`);
161
+ } else {
162
+ this.log(`\u274C ${totalFailures} test${totalFailures > 1 ? "s" : ""} failed`);
163
+ this.log(`\u2705 ${totalPasses} test${totalPasses > 1 ? "s" : ""} passed`);
164
+ if (this.skipped > 0) {
165
+ this.log(`\u25CB ${this.skipped} test${this.skipped > 1 ? "s" : ""} skipped`);
166
+ }
167
+ }
168
+ this.log(`\u23F1\uFE0F Duration: ${duration}ms`);
169
+ this.log(`${"\u2550".repeat(60)}
170
+ `);
171
+ if (totalFailures > 0) {
172
+ this.log(`\u{1F527} Next Steps:`);
173
+ this.log(` 1. Review the failures above`);
174
+ this.log(` 2. Fix ARIA attributes and keyboard handlers`);
175
+ this.log(` 3. Re-run tests to verify fixes
176
+ `);
177
+ } else if (!this.isPlaywright && this.skipped > 0) {
178
+ this.log(`\u2728 Optional: Run Playwright tests for complete validation
179
+ `);
180
+ }
181
+ return {
182
+ passes: totalPasses,
183
+ failures: totalFailures,
184
+ skipped: this.skipped,
185
+ duration
186
+ };
187
+ }
188
+ /**
189
+ * Report an error during test execution
190
+ */
191
+ error(message, context) {
192
+ this.log(`
193
+ \u274C Error: ${message}`);
194
+ if (context) {
195
+ this.log(` Context: ${context}`);
196
+ }
197
+ this.log("");
198
+ }
199
+ };
200
+
201
+ export {
202
+ __commonJS,
203
+ __toESM,
204
+ contract_default,
205
+ ContractReporter
206
+ };
207
+ //# sourceMappingURL=chunk-4F6O5RKZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/test/contract/contract.json","../src/utils/test/contract/ContractReporter.ts"],"sourcesContent":["{\n \"menu\": {\n \"path\": \"./contracts/MenuContract.json\",\n \"component\": \"menu\"\n }\n}","/**\n * Contract Test Reporter - Vitest-style output for accessibility contract tests\n * Provides clear, actionable feedback with proper formatting and context\n */\n\ninterface TestResult {\n description: string;\n status: 'pass' | 'fail' | 'skip';\n failureMessage?: string;\n skipReason?: string;\n}\n\nexport class ContractReporter {\n private startTime: number = 0;\n private componentName: string = '';\n private staticPasses: number = 0;\n private staticFailures: number = 0;\n private dynamicResults: TestResult[] = [];\n private totalTests: number = 0;\n private skipped: number = 0;\n private isPlaywright: boolean = false;\n\n constructor(isPlaywright: boolean = false) {\n this.isPlaywright = isPlaywright;\n }\n\n private log(message: string) {\n process.stderr.write(message + '\\n');\n }\n\n start(componentName: string, totalTests: number) {\n this.startTime = Date.now();\n this.componentName = componentName;\n this.totalTests = totalTests;\n \n const mode = this.isPlaywright ? 'Playwright (Real Browser)' : 'jsdom (Fast)';\n this.log(`\\n${'═'.repeat(60)}`);\n this.log(`🔍 Testing ${componentName} Component - ${mode}`);\n this.log(`${'═'.repeat(60)}\\n`);\n }\n\n reportStatic(passes: number, failures: number) {\n this.staticPasses = passes;\n this.staticFailures = failures;\n \n const icon = failures === 0 ? '✅' : '❌';\n const status = failures === 0 ? 'PASS' : 'FAIL';\n \n this.log(`${icon} Static ARIA Tests: ${status}`);\n this.log(` ${passes}/${passes + failures} required attributes present\\n`);\n }\n\n /**\n * Report individual dynamic test result\n */\n reportTest(test: { description: string; requiresBrowser?: boolean }, status: 'pass' | 'fail' | 'skip', failureMessage?: string) {\n const result: TestResult = {\n description: test.description,\n status,\n failureMessage,\n };\n\n if (status === 'skip' && test.requiresBrowser) {\n result.skipReason = 'Requires real browser (addEventListener events)';\n }\n\n this.dynamicResults.push(result);\n\n const icons = { pass: '✓', fail: '✗', skip: '○' };\n //const colors = { pass: '', fail: '', skip: '' };\n \n this.log(` ${icons[status]} ${test.description}`);\n \n if (status === 'skip' && !this.isPlaywright) {\n this.log(` ↳ Skipped in jsdom (runs in Playwright)`);\n }\n \n if (status === 'fail' && failureMessage) {\n this.log(` ↳ ${failureMessage}`);\n }\n }\n\n /**\n * Report all failures with actionable context\n */\n private reportFailures(failures: string[]) {\n if (failures.length === 0) return;\n\n this.log(`\\n${'─'.repeat(60)}`);\n this.log(`❌ Failures (${failures.length}):\\n`);\n\n failures.forEach((failure, index) => {\n this.log(`${index + 1}. ${failure}`);\n \n if (failure.includes('aria-')) {\n this.log(` 💡 Add the missing ARIA attribute to improve screen reader support`);\n } else if (failure.includes('focus')) {\n this.log(` 💡 Check keyboard event handlers and focus management`);\n } else if (failure.includes('visible')) {\n this.log(` 💡 Verify display/visibility styles and state management`);\n }\n this.log('');\n });\n }\n\n /**\n * Report skipped tests with helpful context\n */\n private reportSkipped() {\n if (this.skipped === 0 || this.isPlaywright) return;\n\n const skippedTests = this.dynamicResults.filter(r => r.status === 'skip');\n \n this.log(`\\n${'─'.repeat(60)}`);\n this.log(`ℹ️ Skipped Tests (${this.skipped}):\\n`);\n this.log(`These tests use native keyboard events via addEventListener,`);\n this.log(`which jsdom cannot simulate. They run successfully in Playwright.\\n`);\n \n skippedTests.forEach((test, index) => {\n this.log(`${index + 1}. ${test.description}`);\n });\n \n this.log(`\\n💡 Run with Playwright for full validation:`);\n this.log(` testUiComponent('${this.componentName}', component, 'http://localhost:5173/')\\n`);\n }\n\n /**\n * Generate final summary with statistics\n */\n summary(failures: string[]) {\n const duration = Date.now() - this.startTime;\n //const totalDynamic = this.dynamicResults.length;\n const dynamicPasses = this.dynamicResults.filter(r => r.status === 'pass').length;\n const dynamicFailures = this.dynamicResults.filter(r => r.status === 'fail').length;\n this.skipped = this.dynamicResults.filter(r => r.status === 'skip').length;\n \n const totalPasses = this.staticPasses + dynamicPasses;\n const totalFailures = this.staticFailures + dynamicFailures;\n const totalRun = totalPasses + totalFailures;\n\n // Report failures first\n if (failures.length > 0) {\n this.reportFailures(failures);\n }\n\n // Report skipped tests\n this.reportSkipped();\n\n // Summary section\n this.log(`\\n${'═'.repeat(60)}`);\n this.log(`📊 Summary\\n`);\n \n if (totalFailures === 0 && this.skipped === 0) {\n this.log(`✅ All ${totalRun} tests passed!`);\n this.log(` ${this.componentName} component meets APG and WCAG guidelines ✓`);\n } else if (totalFailures === 0) {\n this.log(`✅ ${totalPasses}/${totalRun} tests passed`);\n this.log(`○ ${this.skipped} tests skipped (jsdom limitation)`);\n this.log(` ${this.componentName} component works correctly`);\n } else {\n this.log(`❌ ${totalFailures} test${totalFailures > 1 ? 's' : ''} failed`);\n this.log(`✅ ${totalPasses} test${totalPasses > 1 ? 's' : ''} passed`);\n if (this.skipped > 0) {\n this.log(`○ ${this.skipped} test${this.skipped > 1 ? 's' : ''} skipped`);\n }\n }\n \n this.log(`⏱️ Duration: ${duration}ms`);\n this.log(`${'═'.repeat(60)}\\n`);\n\n // Provide next steps\n if (totalFailures > 0) {\n this.log(`🔧 Next Steps:`);\n this.log(` 1. Review the failures above`);\n this.log(` 2. Fix ARIA attributes and keyboard handlers`);\n this.log(` 3. Re-run tests to verify fixes\\n`);\n } else if (!this.isPlaywright && this.skipped > 0) {\n this.log(`✨ Optional: Run Playwright tests for complete validation\\n`);\n }\n\n return {\n passes: totalPasses,\n failures: totalFailures,\n skipped: this.skipped,\n duration,\n };\n }\n\n /**\n * Report an error during test execution\n */\n error(message: string, context?: string) {\n this.log(`\\n❌ Error: ${message}`);\n if (context) {\n this.log(` Context: ${context}`);\n }\n this.log('');\n }\n}"],"mappings":"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","names":[]}
@@ -0,0 +1,255 @@
1
+ import {
2
+ ContractReporter,
3
+ contract_default
4
+ } from "./chunk-4F6O5RKZ.js";
5
+
6
+ // src/utils/test/contract/contractTestRunnerPlaywright.ts
7
+ import { chromium } from "playwright";
8
+ import { readFileSync } from "fs";
9
+ async function runContractTestsPlaywright(componentName, url) {
10
+ const reporter = new ContractReporter(true);
11
+ const contractTyped = contract_default;
12
+ const contractPath = contractTyped[componentName]?.path;
13
+ if (!contractPath) {
14
+ throw new Error(`Contract path not found for component: ${componentName}`);
15
+ }
16
+ const resolvedPath = new URL(contractPath, import.meta.url).pathname;
17
+ const contractData = readFileSync(resolvedPath, "utf-8");
18
+ const componentContract = JSON.parse(contractData);
19
+ const totalTests = componentContract.static[0].assertions.length + componentContract.dynamic.length;
20
+ reporter.start(componentName, totalTests);
21
+ const failures = [];
22
+ const passes = [];
23
+ let browser = null;
24
+ try {
25
+ browser = await chromium.launch({ headless: true });
26
+ const context = await browser.newContext();
27
+ const page = await context.newPage();
28
+ await page.goto(url, { waitUntil: "networkidle" });
29
+ await page.waitForSelector(componentContract.selectors.trigger, { timeout: 5e3 });
30
+ async function resolveRelativeTarget(selector, relative) {
31
+ const items = await page.locator(selector).all();
32
+ switch (relative) {
33
+ case "first":
34
+ return items[0];
35
+ case "second":
36
+ return items[1];
37
+ case "last":
38
+ return items[items.length - 1];
39
+ case "next": {
40
+ const currentIndex = await page.evaluate(([sel]) => {
41
+ const items2 = Array.from(document.querySelectorAll(sel));
42
+ return items2.indexOf(document.activeElement);
43
+ }, [selector]);
44
+ const nextIndex = (currentIndex + 1) % items.length;
45
+ return items[nextIndex];
46
+ }
47
+ case "previous": {
48
+ const currentIndex = await page.evaluate(([sel]) => {
49
+ const items2 = Array.from(document.querySelectorAll(sel));
50
+ return items2.indexOf(document.activeElement);
51
+ }, [selector]);
52
+ const prevIndex = (currentIndex - 1 + items.length) % items.length;
53
+ return items[prevIndex];
54
+ }
55
+ default:
56
+ return null;
57
+ }
58
+ }
59
+ for (const test of componentContract.static[0]?.assertions || []) {
60
+ if (test.target === "relative") continue;
61
+ const targetSelector = componentContract.selectors[test.target];
62
+ if (!targetSelector) {
63
+ failures.push(`Selector for target ${test.target} not found.`);
64
+ continue;
65
+ }
66
+ const target = page.locator(targetSelector).first();
67
+ const exists = await target.count() > 0;
68
+ if (!exists) {
69
+ failures.push(`Target ${test.target} not found.`);
70
+ continue;
71
+ }
72
+ if (!test.expectedValue) {
73
+ const attributes = test.attribute.split(" | ");
74
+ let hasAny = false;
75
+ for (const attr of attributes) {
76
+ const value = await target.getAttribute(attr.trim());
77
+ if (value !== null) {
78
+ hasAny = true;
79
+ break;
80
+ }
81
+ }
82
+ if (!hasAny) {
83
+ failures.push(test.failureMessage + ` None of the attributes "${test.attribute}" are present.`);
84
+ } else {
85
+ passes.push(`At least one of the attributes "${test.attribute}" exists on the element.`);
86
+ }
87
+ } else {
88
+ const attributeValue = await target.getAttribute(test.attribute);
89
+ const expectedValues = test.expectedValue.split(" | ");
90
+ if (!attributeValue || !expectedValues.includes(attributeValue)) {
91
+ failures.push(test.failureMessage + ` Attribute value does not match expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`);
92
+ } else {
93
+ passes.push(`Attribute value matches expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`);
94
+ }
95
+ }
96
+ }
97
+ for (const dynamicTest of componentContract.dynamic || []) {
98
+ const { action, assertions } = dynamicTest;
99
+ const failuresBeforeTest = failures.length;
100
+ const containerElement = page.locator(componentContract.selectors.container).first();
101
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
102
+ const isContainerVisible = await containerElement.isVisible();
103
+ if (isContainerVisible) {
104
+ await triggerElement.click();
105
+ await page.waitForTimeout(50);
106
+ }
107
+ for (const act of action) {
108
+ if (act.type === "click") {
109
+ if (act.target === "document") {
110
+ await page.mouse.click(10, 10);
111
+ } else {
112
+ const actionSelector = componentContract.selectors[act.target];
113
+ if (!actionSelector) {
114
+ failures.push(`Selector for action target ${act.target} not found.`);
115
+ continue;
116
+ }
117
+ await page.locator(actionSelector).first().click();
118
+ await page.waitForTimeout(200);
119
+ }
120
+ }
121
+ if (act.type === "keypress" && act.key) {
122
+ const keyMap = {
123
+ "Space": "Space",
124
+ "Enter": "Enter",
125
+ "Escape": "Escape",
126
+ "Arrow Up": "ArrowUp",
127
+ "Arrow Down": "ArrowDown",
128
+ "Arrow Left": "ArrowLeft",
129
+ "Arrow Right": "ArrowRight",
130
+ "Home": "Home",
131
+ "End": "End",
132
+ "Tab": "Tab"
133
+ };
134
+ let keyValue = keyMap[act.key] || act.key;
135
+ if (keyValue === "Space") {
136
+ keyValue = " ";
137
+ } else if (keyValue.includes(" ")) {
138
+ keyValue = keyValue.replace(/ /g, "");
139
+ }
140
+ if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
141
+ await page.waitForTimeout(100);
142
+ await page.keyboard.press(keyValue);
143
+ await page.waitForTimeout(50);
144
+ } else {
145
+ const keypressSelector = componentContract.selectors[act.target];
146
+ if (!keypressSelector) {
147
+ failures.push(`Selector for keypress target ${act.target} not found.`);
148
+ continue;
149
+ }
150
+ const target = page.locator(keypressSelector).first();
151
+ await target.press(keyValue);
152
+ }
153
+ }
154
+ await page.waitForTimeout(100);
155
+ }
156
+ for (const assertion of assertions) {
157
+ let target;
158
+ if (assertion.target === "relative") {
159
+ const relativeSelector = componentContract.selectors.relative;
160
+ if (!relativeSelector) {
161
+ failures.push("Relative selector is not defined in the contract.");
162
+ continue;
163
+ }
164
+ if (!assertion.expectedValue) {
165
+ failures.push("Expected value for relative target is not defined.");
166
+ continue;
167
+ }
168
+ target = await resolveRelativeTarget(relativeSelector, assertion.expectedValue);
169
+ } else {
170
+ const assertionSelector = componentContract.selectors[assertion.target];
171
+ if (!assertionSelector) {
172
+ failures.push(`Selector for assertion target ${assertion.target} not found.`);
173
+ continue;
174
+ }
175
+ target = page.locator(assertionSelector).first();
176
+ }
177
+ if (!target) {
178
+ failures.push(`Target ${assertion.target} not found.`);
179
+ continue;
180
+ }
181
+ if (assertion.assertion === "toBeVisible") {
182
+ const isVisible = await target.isVisible();
183
+ if (isVisible) {
184
+ passes.push(`${assertion.target} is visible as expected. Test: "${dynamicTest.description}".`);
185
+ } else {
186
+ failures.push(`${assertion.failureMessage}`);
187
+ }
188
+ }
189
+ if (assertion.assertion === "notToBeVisible") {
190
+ const isVisible = await target.isVisible();
191
+ if (!isVisible) {
192
+ passes.push(`${assertion.target} is not visible as expected. Test: "${dynamicTest.description}".`);
193
+ } else {
194
+ failures.push(assertion.failureMessage + ` ${assertion.target} is still visible.`);
195
+ }
196
+ }
197
+ if (assertion.assertion === "toHaveAttribute" && assertion.attribute && assertion.expectedValue) {
198
+ const attributeValue = await target.getAttribute(assertion.attribute);
199
+ if (attributeValue === assertion.expectedValue) {
200
+ passes.push(`${assertion.target} has expected "${assertion.attribute}". Test: "${dynamicTest.description}".`);
201
+ } else {
202
+ failures.push(assertion.failureMessage + ` ${assertion.target} "${assertion.attribute}" should be "${assertion.expectedValue}", found "${attributeValue}".`);
203
+ }
204
+ }
205
+ if (assertion.assertion === "toHaveFocus") {
206
+ const hasFocus = await target.evaluate((el) => el === document.activeElement);
207
+ if (hasFocus) {
208
+ passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
209
+ } else {
210
+ failures.push(`${assertion.failureMessage}`);
211
+ }
212
+ }
213
+ if (assertion.assertion === "toHaveRole" && assertion.expectedValue) {
214
+ const roleValue = await target.getAttribute("role");
215
+ if (roleValue === assertion.expectedValue) {
216
+ passes.push(`${assertion.target} has role "${assertion.expectedValue}". Test: "${dynamicTest.description}".`);
217
+ } else {
218
+ failures.push(assertion.failureMessage + ` Expected role "${assertion.expectedValue}", found "${roleValue}".`);
219
+ }
220
+ }
221
+ }
222
+ const failuresAfterTest = failures.length;
223
+ const testPassed = failuresAfterTest === failuresBeforeTest;
224
+ const failureMessage = testPassed ? void 0 : failures[failures.length - 1];
225
+ reporter.reportTest(dynamicTest, testPassed ? "pass" : "fail", failureMessage);
226
+ }
227
+ const staticPassed = componentContract.static[0].assertions.length;
228
+ const staticFailed = 0;
229
+ reporter.reportStatic(staticPassed, staticFailed);
230
+ reporter.summary(failures);
231
+ } catch (error) {
232
+ if (error instanceof Error) {
233
+ if (error.message.includes("Executable doesn't exist")) {
234
+ console.error("\n\u274C Playwright browsers not found!\n");
235
+ console.log("\u{1F4E6} Run: npx playwright install chromium\n");
236
+ failures.push("Playwright browser not installed. Run: npx playwright install chromium");
237
+ } else if (error.message.includes("net::ERR_CONNECTION_REFUSED")) {
238
+ console.error("\n\u274C Cannot connect to dev server!\n");
239
+ console.log(` Make sure your dev server is running at ${url}
240
+ `);
241
+ failures.push(`Dev server not running at ${url}`);
242
+ } else {
243
+ console.error("\u274C Playwright test error:", error.message);
244
+ failures.push(`Test error: ${error.message}`);
245
+ }
246
+ }
247
+ } finally {
248
+ if (browser) await browser.close();
249
+ }
250
+ return { passes, failures };
251
+ }
252
+ export {
253
+ runContractTestsPlaywright
254
+ };
255
+ //# sourceMappingURL=contractTestRunnerPlaywright-FM6MK6DY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/test/contract/contractTestRunnerPlaywright.ts"],"sourcesContent":["import { chromium, Browser, Page } from \"playwright\";\nimport { readFileSync } from \"fs\";\nimport contract from \"./contract.json\";\nimport type { ComponentContract, Contract } from \"Types\";\nimport { ContractReporter } from \"./ContractReporter\";\n\nexport interface ContractTestResult {\n passes: string[];\n failures: string[];\n}\n\nexport async function runContractTestsPlaywright(componentName: string, url: string): Promise<ContractTestResult> {\n const reporter = new ContractReporter(true);\n \n const contractTyped: Contract = contract;\n const contractPath = contractTyped[componentName]?.path;\n\n if (!contractPath) {\n throw new Error(`Contract path not found for component: ${componentName}`);\n }\n\n const resolvedPath = new URL(contractPath, import.meta.url).pathname;\n const contractData = readFileSync(resolvedPath, \"utf-8\");\n const componentContract: ComponentContract = JSON.parse(contractData);\n\n const totalTests = componentContract.static[0].assertions.length + componentContract.dynamic.length;\n reporter.start(componentName, totalTests);\n\n const failures: string[] = [];\n const passes: string[] = [];\n //const skipped: string[] = [];\n let browser: Browser | null = null;\n\n try {\n browser = await chromium.launch({ headless: true });\n const context = await browser.newContext();\n const page: Page = await context.newPage();\n\n await page.goto(url, { waitUntil: \"networkidle\" });\n \n await page.waitForSelector(componentContract.selectors.trigger, { timeout: 5000 });\n\n async function resolveRelativeTarget(selector: string, relative: string) {\n const items = await page.locator(selector).all();\n \n switch (relative) {\n case \"first\":\n return items[0];\n case \"second\":\n return items[1];\n case \"last\":\n return items[items.length - 1];\n case \"next\": {\n const currentIndex = await page.evaluate(([sel]) => {\n const items = Array.from(document.querySelectorAll(sel as string));\n return items.indexOf(document.activeElement as Element);\n }, [selector]);\n const nextIndex = (currentIndex + 1) % items.length;\n return items[nextIndex];\n }\n case \"previous\": {\n const currentIndex = await page.evaluate(([sel]) => {\n const items = Array.from(document.querySelectorAll(sel as string));\n return items.indexOf(document.activeElement as Element);\n }, [selector]);\n const prevIndex = (currentIndex - 1 + items.length) % items.length;\n return items[prevIndex];\n }\n default:\n return null;\n }\n }\n\n // Run static tests\n for (const test of componentContract.static[0]?.assertions || []) {\n if (test.target === \"relative\") continue;\n\n const targetSelector = componentContract.selectors[test.target as keyof typeof componentContract.selectors];\n if (!targetSelector) {\n failures.push(`Selector for target ${test.target} not found.`);\n continue;\n }\n const target = page.locator(targetSelector).first();\n\n const exists = await target.count() > 0;\n if (!exists) {\n failures.push(`Target ${test.target} not found.`);\n continue;\n }\n\n if (!test.expectedValue) {\n const attributes = test.attribute.split(\" | \");\n let hasAny = false;\n for (const attr of attributes) {\n const value = await target.getAttribute(attr.trim());\n if (value !== null) {\n hasAny = true;\n break;\n }\n }\n if (!hasAny) {\n failures.push(test.failureMessage + ` None of the attributes \"${test.attribute}\" are present.`);\n } else {\n passes.push(`At least one of the attributes \"${test.attribute}\" exists on the element.`);\n }\n } else {\n const attributeValue = await target.getAttribute(test.attribute);\n const expectedValues = test.expectedValue.split(\" | \");\n if (!attributeValue || !expectedValues.includes(attributeValue)) {\n failures.push(test.failureMessage + ` Attribute value does not match expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`);\n } else {\n passes.push(`Attribute value matches expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`);\n }\n }\n }\n\n // Run dynamic tests\n for (const dynamicTest of componentContract.dynamic || []) {\n const { action, assertions } = dynamicTest;\n \n const failuresBeforeTest = failures.length;\n\n // Reset component state before each test for proper isolation\n const containerElement = page.locator(componentContract.selectors.container).first();\n const triggerElement = page.locator(componentContract.selectors.trigger).first();\n const isContainerVisible = await containerElement.isVisible();\n if (isContainerVisible) {\n await triggerElement.click(); // Close the component\n await page.waitForTimeout(50); // Wait for state update\n }\n\n for (const act of action) {\n if (act.type === \"click\") {\n if (act.target === \"document\") {\n await page.mouse.click(10, 10);\n } else {\n const actionSelector = componentContract.selectors[act.target as keyof typeof componentContract.selectors];\n if (!actionSelector) {\n failures.push(`Selector for action target ${act.target} not found.`);\n continue;\n }\n await page.locator(actionSelector).first().click();\n await page.waitForTimeout(200);\n }\n }\n\n if (act.type === \"keypress\" && act.key) {\n const keyMap: Record<string, string> = {\n \"Space\": \"Space\",\n \"Enter\": \"Enter\",\n \"Escape\": \"Escape\",\n \"Arrow Up\": \"ArrowUp\",\n \"Arrow Down\": \"ArrowDown\",\n \"Arrow Left\": \"ArrowLeft\",\n \"Arrow Right\": \"ArrowRight\",\n \"Home\": \"Home\",\n \"End\": \"End\",\n \"Tab\": \"Tab\"\n };\n\n let keyValue = keyMap[act.key] || act.key;\n if (keyValue === \"Space\") {\n keyValue = \" \";\n } else if (keyValue.includes(\" \")) {\n keyValue = keyValue.replace(/ /g, \"\");\n }\n\n if (act.target === \"focusable\" && [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\", \"Escape\"].includes(keyValue)) {\n await page.waitForTimeout(100);\n await page.keyboard.press(keyValue);\n await page.waitForTimeout(50);\n } else {\n const keypressSelector = componentContract.selectors[act.target as keyof typeof componentContract.selectors];\n if (!keypressSelector) {\n failures.push(`Selector for keypress target ${act.target} not found.`);\n continue;\n }\n const target = page.locator(keypressSelector).first();\n await target.press(keyValue);\n }\n }\n\n await page.waitForTimeout(100);\n }\n\n // Evaluate assertions after action chain completes\n for (const assertion of assertions) {\n let target;\n\n if (assertion.target === \"relative\") {\n const relativeSelector = componentContract.selectors.relative;\n if (!relativeSelector) {\n failures.push(\"Relative selector is not defined in the contract.\");\n continue;\n }\n if (!assertion.expectedValue) {\n failures.push(\"Expected value for relative target is not defined.\");\n continue;\n }\n target = await resolveRelativeTarget(relativeSelector, assertion.expectedValue);\n } else {\n const assertionSelector = componentContract.selectors[assertion.target as keyof typeof componentContract.selectors];\n if (!assertionSelector) {\n failures.push(`Selector for assertion target ${assertion.target} not found.`);\n continue;\n }\n target = page.locator(assertionSelector).first();\n }\n\n if (!target) {\n failures.push(`Target ${assertion.target} not found.`);\n continue;\n }\n\n // Evaluate assertion\n if (assertion.assertion === \"toBeVisible\") {\n const isVisible = await target.isVisible();\n if (isVisible) {\n passes.push(`${assertion.target} is visible as expected. Test: \"${dynamicTest.description}\".`);\n } else {\n failures.push(`${assertion.failureMessage}`);\n }\n }\n\n if (assertion.assertion === \"notToBeVisible\") {\n const isVisible = await target.isVisible();\n if (!isVisible) {\n passes.push(`${assertion.target} is not visible as expected. Test: \"${dynamicTest.description}\".`);\n } else {\n failures.push(assertion.failureMessage + ` ${assertion.target} is still visible.`);\n }\n }\n\n if (assertion.assertion === \"toHaveAttribute\" && assertion.attribute && assertion.expectedValue) {\n const attributeValue = await target.getAttribute(assertion.attribute);\n if (attributeValue === assertion.expectedValue) {\n passes.push(`${assertion.target} has expected \"${assertion.attribute}\". Test: \"${dynamicTest.description}\".`);\n } else {\n failures.push(assertion.failureMessage + ` ${assertion.target} \"${assertion.attribute}\" should be \"${assertion.expectedValue}\", found \"${attributeValue}\".`);\n }\n }\n\n if (assertion.assertion === \"toHaveFocus\") {\n const hasFocus = await target.evaluate((el) => el === document.activeElement);\n if (hasFocus) {\n passes.push(`${assertion.target} has focus as expected. Test: \"${dynamicTest.description}\".`);\n } else {\n failures.push(`${assertion.failureMessage}`);\n }\n }\n\n if (assertion.assertion === \"toHaveRole\" && assertion.expectedValue) {\n const roleValue = await target.getAttribute(\"role\");\n if (roleValue === assertion.expectedValue) {\n passes.push(`${assertion.target} has role \"${assertion.expectedValue}\". Test: \"${dynamicTest.description}\".`);\n } else {\n failures.push(assertion.failureMessage + ` Expected role \"${assertion.expectedValue}\", found \"${roleValue}\".`);\n }\n }\n }\n \n // Report test result\n const failuresAfterTest = failures.length;\n const testPassed = failuresAfterTest === failuresBeforeTest;\n const failureMessage = testPassed ? undefined : failures[failures.length - 1];\n reporter.reportTest(dynamicTest, testPassed ? 'pass' : 'fail', failureMessage);\n }\n \n // Report static test summary\n const staticPassed = componentContract.static[0].assertions.length;\n const staticFailed = 0;\n reporter.reportStatic(staticPassed, staticFailed);\n \n // Final summary\n reporter.summary(failures);\n\n } catch (error: unknown) {\n if (error instanceof Error) {\n if (error.message.includes(\"Executable doesn't exist\")) {\n console.error(\"\\n❌ Playwright browsers not found!\\n\");\n console.log(\"📦 Run: npx playwright install chromium\\n\");\n failures.push(\"Playwright browser not installed. Run: npx playwright install chromium\");\n } else if (error.message.includes(\"net::ERR_CONNECTION_REFUSED\")) {\n console.error(\"\\n❌ Cannot connect to dev server!\\n\");\n console.log(` Make sure your dev server is running at ${url}\\n`);\n failures.push(`Dev server not running at ${url}`);\n } else {\n console.error(\"❌ Playwright test error:\", error.message);\n failures.push(`Test error: ${error.message}`);\n }\n }\n } finally {\n if (browser) await browser.close();\n }\n\n return { passes, failures };\n}"],"mappings":"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","names":["items"]}