aria-ease 6.12.2 → 7.0.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.
- package/dist/AccordionComponentStrategy-2SWMNUR6.js +1 -0
- package/dist/ComboboxComponentStrategy-YSYLR2U5.js +5 -0
- package/dist/MenuComponentStrategy-C22BZEBH.js +5 -0
- package/dist/RelativeTargetResolver-T4P25J2M.js +1 -0
- package/dist/TabsComponentStrategy-ADEEFJXM.js +1 -0
- package/dist/audit-APAPHXRO.js +9 -0
- package/dist/badgeHelper-IB5RTMAG.js +11 -0
- package/dist/badgeHelper-JSROP5ML.js +1 -0
- package/dist/buildContracts-T4XQZBDU.js +13 -0
- package/dist/chunk-52I3INNG.js +11 -0
- package/dist/chunk-APUMBDOT.js +1 -0
- package/dist/chunk-BHNO4ZI3.js +1 -0
- package/dist/chunk-CNU4N4AY.js +1 -0
- package/dist/chunk-SM6ZKEDR.js +1 -0
- package/dist/chunk-ZNQ5BXVJ.js +1 -0
- package/dist/cli.cjs +132 -3494
- package/dist/cli.js +19 -161
- package/dist/configLoader-ZEJVXLX7.js +1 -0
- package/dist/configLoader-ZXTSCIP6.js +1 -0
- package/dist/contractTestRunnerPlaywright-FOCQTM4L.js +46 -0
- package/dist/contractTestRunnerPlaywright-QPU6HZXG.js +46 -0
- package/dist/formatters-H3CPDLG5.js +87 -0
- package/dist/index.cjs +64 -4657
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +17 -2351
- package/dist/src/accordion/index.cjs +1 -183
- package/dist/src/accordion/index.js +1 -181
- package/dist/src/block/index.cjs +1 -124
- package/dist/src/block/index.js +1 -122
- package/dist/src/checkbox/index.cjs +1 -109
- package/dist/src/checkbox/index.js +1 -107
- package/dist/src/combobox/index.cjs +1 -265
- package/dist/src/combobox/index.js +1 -263
- package/dist/src/menu/index.cjs +1 -339
- package/dist/src/menu/index.js +1 -337
- package/dist/src/radio/index.cjs +1 -117
- package/dist/src/radio/index.js +1 -115
- package/dist/src/tabs/index.cjs +1 -265
- package/dist/src/tabs/index.js +1 -263
- package/dist/src/toggle/index.cjs +1 -119
- package/dist/src/toggle/index.js +1 -117
- package/dist/src/utils/test/AccordionComponentStrategy-X2GSQ5KT.js +1 -0
- package/dist/src/utils/test/ComboboxComponentStrategy-SICWLI27.js +5 -0
- package/dist/src/utils/test/MenuComponentStrategy-R4VPAHDE.js +5 -0
- package/dist/src/utils/test/RelativeTargetResolver-UQQMZHI6.js +1 -0
- package/dist/src/utils/test/TabsComponentStrategy-L2PYNEW6.js +1 -0
- package/dist/src/utils/test/badgeHelper-ER5ZOHWF.js +11 -0
- package/dist/src/utils/test/chunk-APUMBDOT.js +1 -0
- package/dist/src/utils/test/chunk-BHNO4ZI3.js +1 -0
- package/dist/src/utils/test/configLoader-NCYRL2O6.js +1 -0
- package/dist/src/utils/test/contractTestRunnerPlaywright-YZCMF64Q.js +46 -0
- package/dist/src/utils/test/dsl/index.cjs +1 -486
- package/dist/src/utils/test/dsl/index.d.cts +21 -0
- package/dist/src/utils/test/dsl/index.d.ts +21 -0
- package/dist/src/utils/test/dsl/index.js +1 -484
- package/dist/src/utils/test/index.cjs +64 -2578
- package/dist/src/utils/test/index.d.cts +2 -2
- package/dist/src/utils/test/index.d.ts +2 -2
- package/dist/src/utils/test/index.js +16 -340
- package/dist/test-VXSCSKV5.js +19 -0
- package/package.json +7 -9
- package/dist/AccordionComponentStrategy-4ZEIQ2V6.js +0 -42
- package/dist/ComboboxComponentStrategy-DU342VMB.js +0 -64
- package/dist/MenuComponentStrategy-JAMTCSNF.js +0 -81
- package/dist/RelativeTargetResolver-DJAITO6D.js +0 -7
- package/dist/TabsComponentStrategy-3SQURPMX.js +0 -29
- package/dist/audit-JYEPKLHR.js +0 -63
- package/dist/badgeHelper-JOWO6RQG.js +0 -15
- package/dist/badgeHelper-RDOMCC6E.js +0 -108
- package/dist/buildContracts-FT6KWUJN.js +0 -465
- package/dist/chunk-4DU5Z5BR.js +0 -340
- package/dist/chunk-GJGUY643.js +0 -182
- package/dist/chunk-GLT43UVH.js +0 -43
- package/dist/chunk-I2KLQ2HA.js +0 -22
- package/dist/chunk-JJEPLK7L.js +0 -107
- package/dist/chunk-PK5L2SAF.js +0 -17
- package/dist/configLoader-Q7N5XV4P.js +0 -183
- package/dist/configLoader-REHK3S3Q.js +0 -7
- package/dist/contractTestRunnerPlaywright-47DCBO4A.js +0 -1300
- package/dist/contractTestRunnerPlaywright-UJKXRXBS.js +0 -1300
- package/dist/formatters-32KQIIYS.js +0 -183
- package/dist/src/utils/test/AccordionComponentStrategy-WRHZOEN6.js +0 -38
- package/dist/src/utils/test/ComboboxComponentStrategy-XKQ72RFD.js +0 -60
- package/dist/src/utils/test/MenuComponentStrategy-VKZQYLBE.js +0 -77
- package/dist/src/utils/test/RelativeTargetResolver-G2XDN2VV.js +0 -1
- package/dist/src/utils/test/TabsComponentStrategy-BKG53SEV.js +0 -26
- package/dist/src/utils/test/badgeHelper-HZKGOPB4.js +0 -102
- package/dist/src/utils/test/chunk-4DU5Z5BR.js +0 -332
- package/dist/src/utils/test/chunk-GLT43UVH.js +0 -41
- package/dist/src/utils/test/configLoader-NA7IBCS3.js +0 -181
- package/dist/src/utils/test/contractTestRunnerPlaywright-AZ4QKLYT.js +0 -1278
- package/dist/test-6Y4CIQOM.js +0 -358
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
import { chromium } from 'playwright';
|
|
2
|
-
|
|
3
|
-
// src/utils/test/src/ContractReporter.ts
|
|
4
|
-
var ContractReporter = class {
|
|
5
|
-
startTime = 0;
|
|
6
|
-
componentName = "";
|
|
7
|
-
staticPasses = 0;
|
|
8
|
-
staticFailures = 0;
|
|
9
|
-
staticWarnings = 0;
|
|
10
|
-
dynamicResults = [];
|
|
11
|
-
totalTests = 0;
|
|
12
|
-
skipped = 0;
|
|
13
|
-
warnings = 0;
|
|
14
|
-
isPlaywright = false;
|
|
15
|
-
isCustomContract = false;
|
|
16
|
-
apgUrl = "https://www.w3.org/WAI/ARIA/apg/";
|
|
17
|
-
hasPrintedStaticSection = false;
|
|
18
|
-
hasPrintedDynamicSection = false;
|
|
19
|
-
constructor(isPlaywright = false, isCustomContract = false) {
|
|
20
|
-
this.isPlaywright = isPlaywright;
|
|
21
|
-
this.isCustomContract = isCustomContract;
|
|
22
|
-
}
|
|
23
|
-
log(message) {
|
|
24
|
-
process.stderr.write(message + "\n");
|
|
25
|
-
}
|
|
26
|
-
start(componentName, totalTests, apgUrl) {
|
|
27
|
-
this.startTime = Date.now();
|
|
28
|
-
this.componentName = componentName;
|
|
29
|
-
this.totalTests = totalTests;
|
|
30
|
-
this.hasPrintedStaticSection = false;
|
|
31
|
-
this.hasPrintedDynamicSection = false;
|
|
32
|
-
if (apgUrl) {
|
|
33
|
-
this.apgUrl = apgUrl;
|
|
34
|
-
}
|
|
35
|
-
const mode = this.isPlaywright ? "Playwright (Real Browser)" : "jsdom (Fast)";
|
|
36
|
-
this.log(`
|
|
37
|
-
${"\u2550".repeat(60)}`);
|
|
38
|
-
this.log(`\u{1F50D} Testing ${componentName.charAt(0).toUpperCase() + componentName.slice(1)} Component - ${mode}`);
|
|
39
|
-
this.log(`${"\u2550".repeat(60)}
|
|
40
|
-
`);
|
|
41
|
-
}
|
|
42
|
-
reportStatic(passes, failures, warnings = 0) {
|
|
43
|
-
this.staticPasses = passes;
|
|
44
|
-
this.staticFailures = failures;
|
|
45
|
-
this.staticWarnings = warnings;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Report individual static test pass
|
|
49
|
-
*/
|
|
50
|
-
reportStaticTest(description, status, failureMessage, level) {
|
|
51
|
-
if (!this.hasPrintedStaticSection) {
|
|
52
|
-
this.log(`${"\u2500".repeat(60)}`);
|
|
53
|
-
this.log(`\u{1F9EA} Static Assertions`);
|
|
54
|
-
this.log(`${"\u2500".repeat(60)}`);
|
|
55
|
-
this.hasPrintedStaticSection = true;
|
|
56
|
-
}
|
|
57
|
-
const icon = status === "pass" ? "\u2713" : status === "warn" ? "\u26A0" : status === "skip" ? "\u25CB" : "\u2717";
|
|
58
|
-
this.log(` ${icon} ${description}`);
|
|
59
|
-
if (level) {
|
|
60
|
-
this.log(` \u21B3 level=${level}`);
|
|
61
|
-
}
|
|
62
|
-
if ((status === "fail" || status === "warn" || status === "skip") && failureMessage) {
|
|
63
|
-
this.log(` \u21B3 ${failureMessage}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Report individual dynamic test result
|
|
68
|
-
*/
|
|
69
|
-
reportTest(test, status, failureMessage) {
|
|
70
|
-
if (!this.hasPrintedDynamicSection) {
|
|
71
|
-
this.log("");
|
|
72
|
-
this.log(`${"\u2500".repeat(60)}`);
|
|
73
|
-
this.log(`\u2328\uFE0F Dynamic Interaction Tests`);
|
|
74
|
-
this.log(`${"\u2500".repeat(60)}`);
|
|
75
|
-
this.hasPrintedDynamicSection = true;
|
|
76
|
-
}
|
|
77
|
-
const result = {
|
|
78
|
-
description: test.description,
|
|
79
|
-
status,
|
|
80
|
-
failureMessage,
|
|
81
|
-
level: test.level
|
|
82
|
-
};
|
|
83
|
-
if (status === "skip") {
|
|
84
|
-
result.skipReason = "Requires real browser (addEventListener events)";
|
|
85
|
-
}
|
|
86
|
-
this.dynamicResults.push(result);
|
|
87
|
-
const icons = { pass: "\u2713", fail: "\u2717", warn: "\u26A0", skip: "\u25CB" };
|
|
88
|
-
const levelPrefix = test.level ? `[${test.level.toUpperCase()}] ` : "";
|
|
89
|
-
this.log(` ${icons[status]} ${levelPrefix}${test.description}`);
|
|
90
|
-
if (status === "skip" && !this.isPlaywright) {
|
|
91
|
-
this.log(` \u21B3 Skipped in jsdom (runs in Playwright)`);
|
|
92
|
-
}
|
|
93
|
-
if (status === "fail" && failureMessage) {
|
|
94
|
-
this.log(` \u21B3 ${failureMessage}`);
|
|
95
|
-
}
|
|
96
|
-
if (status === "warn" && failureMessage) {
|
|
97
|
-
this.log(` \u21B3 ${failureMessage}`);
|
|
98
|
-
}
|
|
99
|
-
if (status === "skip" && failureMessage) {
|
|
100
|
-
this.log(` \u21B3 ${failureMessage}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Report all failures with actionable context
|
|
105
|
-
*/
|
|
106
|
-
reportFailures(failures) {
|
|
107
|
-
if (failures.length === 0) return;
|
|
108
|
-
this.log(`
|
|
109
|
-
${"\u2500".repeat(60)}`);
|
|
110
|
-
this.log(`\u274C Failures (${failures.length}):
|
|
111
|
-
`);
|
|
112
|
-
failures.forEach((failure, index) => {
|
|
113
|
-
this.log(`${index + 1}. ${failure}`);
|
|
114
|
-
if (failure.includes("aria-")) {
|
|
115
|
-
this.log(` \u{1F4A1} Add the missing ARIA attribute to improve screen reader support`);
|
|
116
|
-
} else if (failure.includes("focus")) {
|
|
117
|
-
this.log(` \u{1F4A1} Check keyboard event handlers and focus management`);
|
|
118
|
-
} else if (failure.includes("visible")) {
|
|
119
|
-
this.log(` \u{1F4A1} Verify display/visibility styles and state management`);
|
|
120
|
-
}
|
|
121
|
-
this.log("");
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
reportWarnings() {
|
|
125
|
-
const warnings = this.dynamicResults.filter((r) => r.status === "warn");
|
|
126
|
-
if (warnings.length === 0 && this.staticWarnings === 0) return;
|
|
127
|
-
this.log(`
|
|
128
|
-
${"\u2500".repeat(60)}`);
|
|
129
|
-
this.log(`\u26A0\uFE0F Warnings (${this.staticWarnings + warnings.length}):
|
|
130
|
-
`);
|
|
131
|
-
this.log(`These checks are failing but treated as warnings under the active strictness mode.
|
|
132
|
-
`);
|
|
133
|
-
warnings.forEach((test, index) => {
|
|
134
|
-
this.log(`${index + 1}. ${test.description}`);
|
|
135
|
-
if (test.failureMessage) {
|
|
136
|
-
this.log(` \u21B3 ${test.failureMessage}`);
|
|
137
|
-
}
|
|
138
|
-
if (test.level) {
|
|
139
|
-
this.log(` \u21B3 level=${test.level}`);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
if (this.apgUrl) {
|
|
143
|
-
this.log(`
|
|
144
|
-
Reference: ${this.apgUrl}
|
|
145
|
-
`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Report skipped tests with helpful context
|
|
150
|
-
*/
|
|
151
|
-
reportSkipped() {
|
|
152
|
-
if (this.skipped === 0 || this.isPlaywright) return;
|
|
153
|
-
const skippedTests = this.dynamicResults.filter((r) => r.status === "skip");
|
|
154
|
-
this.log(`
|
|
155
|
-
${"\u2500".repeat(60)}`);
|
|
156
|
-
this.log(`\u2139\uFE0F Skipped Tests (${this.skipped}):
|
|
157
|
-
`);
|
|
158
|
-
this.log(`These tests use native keyboard events via addEventListener,`);
|
|
159
|
-
this.log(`which jsdom cannot simulate. They run successfully in Playwright.
|
|
160
|
-
`);
|
|
161
|
-
skippedTests.forEach((test, index) => {
|
|
162
|
-
this.log(`${index + 1}. ${test.description}`);
|
|
163
|
-
});
|
|
164
|
-
this.log(`
|
|
165
|
-
\u{1F4A1} Run with Playwright for full validation:`);
|
|
166
|
-
this.log(` testUiComponent('${this.componentName}', null, 'http://localhost:5173/test-harness?component=component_name')
|
|
167
|
-
`);
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Generate final summary with statistics
|
|
171
|
-
*/
|
|
172
|
-
summary(failures) {
|
|
173
|
-
const duration = Date.now() - this.startTime;
|
|
174
|
-
const dynamicPasses = this.dynamicResults.filter((r) => r.status === "pass").length;
|
|
175
|
-
const dynamicFailures = this.dynamicResults.filter((r) => r.status === "fail").length;
|
|
176
|
-
const dynamicWarnings = this.dynamicResults.filter((r) => r.status === "warn").length;
|
|
177
|
-
this.skipped = this.dynamicResults.filter((r) => r.status === "skip").length;
|
|
178
|
-
this.warnings = this.staticWarnings + dynamicWarnings;
|
|
179
|
-
const totalPasses = this.staticPasses + dynamicPasses;
|
|
180
|
-
const totalFailures = this.staticFailures + dynamicFailures;
|
|
181
|
-
const totalRun = totalPasses + totalFailures + this.warnings;
|
|
182
|
-
const getComponentMessage = () => {
|
|
183
|
-
const componentDisplayName = `${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)}`;
|
|
184
|
-
if (this.isCustomContract) {
|
|
185
|
-
return `${componentDisplayName} component validates against your custom accessibility policy \u2713`;
|
|
186
|
-
}
|
|
187
|
-
return `${componentDisplayName} component meets Aria-Ease baseline WAI-ARIA expectations \u2713`;
|
|
188
|
-
};
|
|
189
|
-
if (failures.length > 0) {
|
|
190
|
-
this.reportFailures(failures);
|
|
191
|
-
}
|
|
192
|
-
this.reportWarnings();
|
|
193
|
-
this.reportSkipped();
|
|
194
|
-
this.log(`
|
|
195
|
-
${"\u2550".repeat(60)}`);
|
|
196
|
-
this.log(`\u{1F4CA} Summary
|
|
197
|
-
`);
|
|
198
|
-
if (totalFailures === 0 && this.skipped === 0 && this.warnings === 0) {
|
|
199
|
-
this.log(`\u2705 All ${totalRun} tests passed!`);
|
|
200
|
-
this.log(` ${getComponentMessage()}`);
|
|
201
|
-
} else if (totalFailures === 0) {
|
|
202
|
-
this.log(`\u2705 ${totalPasses}/${totalRun} tests passed`);
|
|
203
|
-
if (this.skipped > 0) {
|
|
204
|
-
this.log(`\u25CB ${this.skipped} tests skipped`);
|
|
205
|
-
}
|
|
206
|
-
if (this.warnings > 0) {
|
|
207
|
-
this.log(`\u26A0\uFE0F ${this.warnings} warning${this.warnings > 1 ? "s" : ""}`);
|
|
208
|
-
}
|
|
209
|
-
this.log(` ${getComponentMessage()}`);
|
|
210
|
-
} else {
|
|
211
|
-
this.log(`\u274C ${totalFailures} test${totalFailures > 1 ? "s" : ""} failed`);
|
|
212
|
-
this.log(`\u2705 ${totalPasses} test${totalPasses > 1 ? "s" : ""} passed`);
|
|
213
|
-
if (this.warnings > 0) {
|
|
214
|
-
this.log(`\u26A0\uFE0F ${this.warnings} warning${this.warnings > 1 ? "s" : ""}`);
|
|
215
|
-
}
|
|
216
|
-
if (this.skipped > 0) {
|
|
217
|
-
this.log(`\u25CB ${this.skipped} test${this.skipped > 1 ? "s" : ""} skipped`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
this.log(`\u23F1\uFE0F Duration: ${duration}ms`);
|
|
221
|
-
this.log(`${"\u2550".repeat(60)}
|
|
222
|
-
`);
|
|
223
|
-
if (totalFailures > 0) {
|
|
224
|
-
this.log(`\u{1F527} Next Steps:`);
|
|
225
|
-
this.log(` 1. Review the failures above`);
|
|
226
|
-
this.log(` 2. Fix ARIA attributes and keyboard handlers`);
|
|
227
|
-
this.log(` 3. Re-run tests to verify fixes
|
|
228
|
-
`);
|
|
229
|
-
} else if (!this.isPlaywright && this.skipped > 0) {
|
|
230
|
-
this.log(`\u2728 Optional: Run Playwright tests for complete validation
|
|
231
|
-
`);
|
|
232
|
-
}
|
|
233
|
-
return {
|
|
234
|
-
passes: totalPasses,
|
|
235
|
-
failures: totalFailures,
|
|
236
|
-
skipped: this.skipped,
|
|
237
|
-
duration
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Report an error during test execution
|
|
242
|
-
*/
|
|
243
|
-
error(message, context) {
|
|
244
|
-
this.log(`
|
|
245
|
-
\u274C Error: ${message}`);
|
|
246
|
-
if (context) {
|
|
247
|
-
this.log(` Context: ${context}`);
|
|
248
|
-
}
|
|
249
|
-
this.log("");
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
// src/utils/test/src/strictness.ts
|
|
254
|
-
var FALLBACK_LEVEL = "required";
|
|
255
|
-
function normalizeLevel(level) {
|
|
256
|
-
if (level === "required" || level === "recommended" || level === "optional") {
|
|
257
|
-
return level;
|
|
258
|
-
}
|
|
259
|
-
return FALLBACK_LEVEL;
|
|
260
|
-
}
|
|
261
|
-
function normalizeStrictness(strictness) {
|
|
262
|
-
if (strictness === "minimal" || strictness === "balanced" || strictness === "strict" || strictness === "paranoid") {
|
|
263
|
-
return strictness;
|
|
264
|
-
}
|
|
265
|
-
return "balanced";
|
|
266
|
-
}
|
|
267
|
-
function resolveEnforcement(level, strictness) {
|
|
268
|
-
const matrix = {
|
|
269
|
-
minimal: {
|
|
270
|
-
required: "error",
|
|
271
|
-
recommended: "ignore",
|
|
272
|
-
optional: "ignore"
|
|
273
|
-
},
|
|
274
|
-
balanced: {
|
|
275
|
-
required: "error",
|
|
276
|
-
recommended: "warning",
|
|
277
|
-
optional: "ignore"
|
|
278
|
-
},
|
|
279
|
-
strict: {
|
|
280
|
-
required: "error",
|
|
281
|
-
recommended: "error",
|
|
282
|
-
optional: "warning"
|
|
283
|
-
},
|
|
284
|
-
paranoid: {
|
|
285
|
-
required: "error",
|
|
286
|
-
recommended: "error",
|
|
287
|
-
optional: "error"
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
return matrix[strictness][level];
|
|
291
|
-
}
|
|
292
|
-
var sharedBrowser = null;
|
|
293
|
-
var sharedContext = null;
|
|
294
|
-
async function getOrCreateBrowser() {
|
|
295
|
-
if (!sharedBrowser) {
|
|
296
|
-
sharedBrowser = await chromium.launch({
|
|
297
|
-
headless: true,
|
|
298
|
-
// Launch with clean browser profile - no extensions, no user data
|
|
299
|
-
args: [
|
|
300
|
-
"--disable-extensions",
|
|
301
|
-
"--disable-blink-features=AutomationControlled"
|
|
302
|
-
]
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
return sharedBrowser;
|
|
306
|
-
}
|
|
307
|
-
async function getOrCreateContext() {
|
|
308
|
-
if (!sharedContext) {
|
|
309
|
-
const browser = await getOrCreateBrowser();
|
|
310
|
-
sharedContext = await browser.newContext({
|
|
311
|
-
permissions: [],
|
|
312
|
-
ignoreHTTPSErrors: true
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
return sharedContext;
|
|
316
|
-
}
|
|
317
|
-
async function createTestPage() {
|
|
318
|
-
const context = await getOrCreateContext();
|
|
319
|
-
return await context.newPage();
|
|
320
|
-
}
|
|
321
|
-
async function closeSharedBrowser() {
|
|
322
|
-
if (sharedContext) {
|
|
323
|
-
await sharedContext.close();
|
|
324
|
-
sharedContext = null;
|
|
325
|
-
}
|
|
326
|
-
if (sharedBrowser) {
|
|
327
|
-
await sharedBrowser.close();
|
|
328
|
-
sharedBrowser = null;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
export { ContractReporter, closeSharedBrowser, createTestPage, normalizeLevel, normalizeStrictness, resolveEnforcement };
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// src/utils/test/src/RelativeTargetResolver.ts
|
|
2
|
-
var RelativeTargetResolver = class {
|
|
3
|
-
/**
|
|
4
|
-
* Resolve a relative target like "first", "second", "last", "next", "previous"
|
|
5
|
-
* @param page Playwright page instance
|
|
6
|
-
* @param selector Base selector to find elements
|
|
7
|
-
* @param relative Relative position (first, second, last, next, previous)
|
|
8
|
-
* @returns The resolved Locator or null if not found
|
|
9
|
-
*/
|
|
10
|
-
static async resolve(page, selector, relative) {
|
|
11
|
-
const items = await page.locator(selector).all();
|
|
12
|
-
switch (relative) {
|
|
13
|
-
case "first":
|
|
14
|
-
return items[0];
|
|
15
|
-
case "second":
|
|
16
|
-
return items[1];
|
|
17
|
-
case "last":
|
|
18
|
-
return items[items.length - 1];
|
|
19
|
-
case "next": {
|
|
20
|
-
const currentIndex = await page.evaluate(([sel]) => {
|
|
21
|
-
const items2 = Array.from(document.querySelectorAll(sel));
|
|
22
|
-
return items2.indexOf(document.activeElement);
|
|
23
|
-
}, [selector]);
|
|
24
|
-
const nextIndex = (currentIndex + 1) % items.length;
|
|
25
|
-
return items[nextIndex];
|
|
26
|
-
}
|
|
27
|
-
case "previous": {
|
|
28
|
-
const currentIndex = await page.evaluate(([sel]) => {
|
|
29
|
-
const items2 = Array.from(document.querySelectorAll(sel));
|
|
30
|
-
return items2.indexOf(document.activeElement);
|
|
31
|
-
}, [selector]);
|
|
32
|
-
const prevIndex = (currentIndex - 1 + items.length) % items.length;
|
|
33
|
-
return items[prevIndex];
|
|
34
|
-
}
|
|
35
|
-
default:
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export { RelativeTargetResolver };
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
|
|
4
|
-
// src/utils/cli/configLoader.ts
|
|
5
|
-
function validateConfig(config) {
|
|
6
|
-
const errors = [];
|
|
7
|
-
if (!config || typeof config !== "object") {
|
|
8
|
-
errors.push("Config must be an object");
|
|
9
|
-
return { valid: false, errors };
|
|
10
|
-
}
|
|
11
|
-
const cfg = config;
|
|
12
|
-
if (cfg.audit !== void 0) {
|
|
13
|
-
if (typeof cfg.audit !== "object" || cfg.audit === null) {
|
|
14
|
-
errors.push("audit must be an object");
|
|
15
|
-
} else {
|
|
16
|
-
if (cfg.audit.urls !== void 0) {
|
|
17
|
-
if (!Array.isArray(cfg.audit.urls)) {
|
|
18
|
-
errors.push("audit.urls must be an array");
|
|
19
|
-
} else if (cfg.audit.urls.some((url) => typeof url !== "string")) {
|
|
20
|
-
errors.push("audit.urls must contain only strings");
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
if (cfg.audit.output !== void 0) {
|
|
24
|
-
if (typeof cfg.audit.output !== "object") {
|
|
25
|
-
errors.push("audit.output must be an object");
|
|
26
|
-
} else {
|
|
27
|
-
const output = cfg.audit.output;
|
|
28
|
-
if (output.format !== void 0) {
|
|
29
|
-
if (!["json", "csv", "html", "all"].includes(output.format)) {
|
|
30
|
-
errors.push("audit.output.format must be one of: json, csv, html, all");
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
if (output.out !== void 0 && typeof output.out !== "string") {
|
|
34
|
-
errors.push("audit.output.out must be a string");
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
if (cfg.test !== void 0) {
|
|
41
|
-
if (typeof cfg.test !== "object" || cfg.test === null) {
|
|
42
|
-
errors.push("test must be an object");
|
|
43
|
-
} else {
|
|
44
|
-
if (cfg.test.disableTimeouts !== void 0 && typeof cfg.test.disableTimeouts !== "boolean") {
|
|
45
|
-
errors.push("test.disableTimeouts must be a boolean when provided");
|
|
46
|
-
}
|
|
47
|
-
const testTimeoutFields = [
|
|
48
|
-
"actionTimeoutMs",
|
|
49
|
-
"assertionTimeoutMs",
|
|
50
|
-
"navigationTimeoutMs",
|
|
51
|
-
"componentReadyTimeoutMs"
|
|
52
|
-
];
|
|
53
|
-
for (const field of testTimeoutFields) {
|
|
54
|
-
const value = cfg.test[field];
|
|
55
|
-
if (value !== void 0) {
|
|
56
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
57
|
-
errors.push(`test.${field} must be a non-negative number when provided`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (cfg.test.components !== void 0) {
|
|
62
|
-
if (!Array.isArray(cfg.test.components)) {
|
|
63
|
-
errors.push("test.components must be an array");
|
|
64
|
-
} else {
|
|
65
|
-
cfg.test.components.forEach((comp, idx) => {
|
|
66
|
-
if (typeof comp !== "object" || comp === null) {
|
|
67
|
-
errors.push(`test.components[${idx}] must be an object`);
|
|
68
|
-
} else {
|
|
69
|
-
if (typeof comp.name !== "string") {
|
|
70
|
-
errors.push(`test.components[${idx}].name must be a string`);
|
|
71
|
-
}
|
|
72
|
-
if (comp.contractPath !== void 0 && typeof comp.contractPath !== "string") {
|
|
73
|
-
errors.push(`test.components[${idx}].contractPath must be a string when provided`);
|
|
74
|
-
}
|
|
75
|
-
if (comp.strategyPath !== void 0 && typeof comp.strategyPath !== "string") {
|
|
76
|
-
errors.push(`test.components[${idx}].strategyPath must be a string when provided`);
|
|
77
|
-
}
|
|
78
|
-
if (comp.strictness !== void 0 && !["minimal", "balanced", "strict", "paranoid"].includes(comp.strictness)) {
|
|
79
|
-
errors.push(`test.components[${idx}].strictness must be one of: minimal, balanced, strict, paranoid`);
|
|
80
|
-
}
|
|
81
|
-
if (comp.disableTimeouts !== void 0 && typeof comp.disableTimeouts !== "boolean") {
|
|
82
|
-
errors.push(`test.components[${idx}].disableTimeouts must be a boolean when provided`);
|
|
83
|
-
}
|
|
84
|
-
const componentTimeoutFields = [
|
|
85
|
-
"actionTimeoutMs",
|
|
86
|
-
"assertionTimeoutMs",
|
|
87
|
-
"navigationTimeoutMs",
|
|
88
|
-
"componentReadyTimeoutMs"
|
|
89
|
-
];
|
|
90
|
-
for (const field of componentTimeoutFields) {
|
|
91
|
-
const value = comp[field];
|
|
92
|
-
if (value !== void 0) {
|
|
93
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
94
|
-
errors.push(`test.components[${idx}].${field} must be a non-negative number when provided`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (cfg.test.strictness !== void 0) {
|
|
103
|
-
if (!["minimal", "balanced", "strict", "paranoid"].includes(cfg.test.strictness)) {
|
|
104
|
-
errors.push("test.strictness must be one of: minimal, balanced, strict, paranoid");
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (cfg.contracts !== void 0) {
|
|
110
|
-
if (!Array.isArray(cfg.contracts)) {
|
|
111
|
-
errors.push("contracts must be an array");
|
|
112
|
-
} else {
|
|
113
|
-
cfg.contracts.forEach((contract, idx) => {
|
|
114
|
-
if (typeof contract !== "object" || contract === null) {
|
|
115
|
-
errors.push(`contracts[${idx}] must be an object`);
|
|
116
|
-
} else {
|
|
117
|
-
if (typeof contract.src !== "string") {
|
|
118
|
-
errors.push(`contracts[${idx}].src is required and must be a string`);
|
|
119
|
-
}
|
|
120
|
-
if (contract.out !== void 0 && typeof contract.out !== "string") {
|
|
121
|
-
errors.push(`contracts[${idx}].out must be a string`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return { valid: errors.length === 0, errors };
|
|
128
|
-
}
|
|
129
|
-
async function loadConfigFile(filePath) {
|
|
130
|
-
try {
|
|
131
|
-
const ext = path.extname(filePath);
|
|
132
|
-
if (ext === ".json") {
|
|
133
|
-
const content = await fs.readFile(filePath, "utf-8");
|
|
134
|
-
return JSON.parse(content);
|
|
135
|
-
} else if ([".js", ".mjs", ".cjs", ".ts"].includes(ext)) {
|
|
136
|
-
const imported = await import(filePath);
|
|
137
|
-
return imported.default || imported;
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
} catch {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
async function loadConfig(cwd = process.cwd()) {
|
|
145
|
-
const configNames = [
|
|
146
|
-
"ariaease.config.js",
|
|
147
|
-
"ariaease.config.mjs",
|
|
148
|
-
"ariaease.config.cjs",
|
|
149
|
-
"ariaease.config.json",
|
|
150
|
-
"ariaease.config.ts"
|
|
151
|
-
];
|
|
152
|
-
let loadedConfig = null;
|
|
153
|
-
let foundPath = null;
|
|
154
|
-
const errors = [];
|
|
155
|
-
for (const name of configNames) {
|
|
156
|
-
const configPath = path.resolve(cwd, name);
|
|
157
|
-
if (await fs.pathExists(configPath)) {
|
|
158
|
-
foundPath = configPath;
|
|
159
|
-
loadedConfig = await loadConfigFile(configPath);
|
|
160
|
-
if (loadedConfig === null) {
|
|
161
|
-
errors.push(`Found config at ${name} but failed to load it. Check for syntax errors.`);
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
const validation = validateConfig(loadedConfig);
|
|
165
|
-
if (!validation.valid) {
|
|
166
|
-
errors.push(`Config validation failed in ${name}:`);
|
|
167
|
-
errors.push(...validation.errors.map((err) => ` - ${err}`));
|
|
168
|
-
loadedConfig = null;
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return {
|
|
175
|
-
config: loadedConfig || {},
|
|
176
|
-
configPath: loadedConfig ? foundPath : null,
|
|
177
|
-
errors
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export { loadConfig };
|