aria-ease 6.10.0 → 6.11.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 (44) hide show
  1. package/README.md +1 -1
  2. package/{bin/buildContracts-S22V7AGV.js → dist/buildContracts-FT6KWUJN.js} +3 -3
  3. package/{bin → dist}/cli.cjs +4 -4
  4. package/{bin → dist}/cli.js +1 -1
  5. package/dist/index.cjs +132 -56
  6. package/dist/index.js +132 -56
  7. package/dist/src/{Types.d-yGC2bBaB.d.ts → Types.d-DYfYR3Vc.d.cts} +1 -1
  8. package/dist/src/{Types.d-yGC2bBaB.d.cts → Types.d-DYfYR3Vc.d.ts} +1 -1
  9. package/dist/src/accordion/index.d.cts +1 -1
  10. package/dist/src/accordion/index.d.ts +1 -1
  11. package/dist/src/block/index.d.cts +1 -1
  12. package/dist/src/block/index.d.ts +1 -1
  13. package/dist/src/checkbox/index.d.cts +1 -1
  14. package/dist/src/checkbox/index.d.ts +1 -1
  15. package/dist/src/combobox/index.d.cts +1 -1
  16. package/dist/src/combobox/index.d.ts +1 -1
  17. package/dist/src/menu/index.d.cts +1 -1
  18. package/dist/src/menu/index.d.ts +1 -1
  19. package/dist/src/radio/index.d.cts +1 -1
  20. package/dist/src/radio/index.d.ts +1 -1
  21. package/dist/src/tabs/index.d.cts +1 -1
  22. package/dist/src/tabs/index.d.ts +1 -1
  23. package/dist/src/toggle/index.d.cts +1 -1
  24. package/dist/src/toggle/index.d.ts +1 -1
  25. package/dist/src/utils/test/dsl/index.cjs +132 -56
  26. package/dist/src/utils/test/dsl/index.js +132 -56
  27. package/package.json +4 -5
  28. package/bin/AccordionComponentStrategy-4ZEIQ2V6.js +0 -42
  29. package/bin/ComboboxComponentStrategy-OGRVZXAF.js +0 -64
  30. package/bin/MenuComponentStrategy-JAMTCSNF.js +0 -81
  31. package/bin/TabsComponentStrategy-3SQURPMX.js +0 -29
  32. package/bin/chunk-I2KLQ2HA.js +0 -22
  33. package/bin/chunk-PK5L2SAF.js +0 -17
  34. package/bin/chunk-XERMSYEH.js +0 -363
  35. /package/{bin → dist}/audit-RM6TCZ5C.js +0 -0
  36. /package/{bin → dist}/badgeHelper-JOWO6RQG.js +0 -0
  37. /package/{bin → dist}/chunk-JJEPLK7L.js +0 -0
  38. /package/{bin → dist}/chunk-NI3MQCAS.js +0 -0
  39. /package/{bin → dist}/cli.d.cts +0 -0
  40. /package/{bin → dist}/cli.d.ts +0 -0
  41. /package/{bin → dist}/configLoader-UJZHQBYS.js +0 -0
  42. /package/{bin → dist}/contractTestRunnerPlaywright-QDXSK3FE.js +0 -0
  43. /package/{bin → dist}/formatters-32KQIIYS.js +0 -0
  44. /package/{bin → dist}/test-O3J4ZPQR.js +0 -0
@@ -1,64 +0,0 @@
1
- import {
2
- test_exports
3
- } from "./chunk-PK5L2SAF.js";
4
- import "./chunk-I2KLQ2HA.js";
5
-
6
- // src/utils/test/src/component-strategies/ComboboxComponentStrategy.ts
7
- var ComboboxComponentStrategy = class {
8
- constructor(mainSelector, selectors, actionTimeoutMs = 400, assertionTimeoutMs = 400) {
9
- this.mainSelector = mainSelector;
10
- this.selectors = selectors;
11
- this.actionTimeoutMs = actionTimeoutMs;
12
- this.assertionTimeoutMs = assertionTimeoutMs;
13
- }
14
- async resetState(page) {
15
- if (!this.selectors.popup) return;
16
- const popupSelector = this.selectors.popup;
17
- const popupElement = page.locator(popupSelector).first();
18
- const isPopupVisible = await popupElement.isVisible().catch(() => false);
19
- if (!isPopupVisible) return;
20
- let listBoxClosed = false;
21
- let closeSelector = this.selectors.input;
22
- if (!closeSelector && this.selectors.focusable) {
23
- closeSelector = this.selectors.focusable;
24
- } else if (!closeSelector) {
25
- closeSelector = this.selectors.button;
26
- }
27
- if (closeSelector) {
28
- const closeElement = page.locator(closeSelector).first();
29
- await closeElement.focus();
30
- await page.keyboard.press("Escape");
31
- listBoxClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
32
- }
33
- if (!listBoxClosed && this.selectors.button) {
34
- const buttonElement = page.locator(this.selectors.button).first();
35
- await buttonElement.click({ timeout: this.actionTimeoutMs });
36
- listBoxClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
37
- }
38
- if (!listBoxClosed) {
39
- await page.mouse.click(10, 10);
40
- listBoxClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
41
- }
42
- if (!listBoxClosed) {
43
- throw new Error(
44
- `\u274C FATAL: Cannot close combobox popup between tests. Popup remains visible after trying:
45
- 1. Escape key
46
- 2. Clicking button
47
- 3. Clicking outside
48
- This indicates a problem with the combobox component's close functionality.`
49
- );
50
- }
51
- if (this.selectors.input) {
52
- await page.locator(this.selectors.input).first().clear();
53
- }
54
- }
55
- async shouldSkipTest() {
56
- return false;
57
- }
58
- getMainSelector() {
59
- return this.mainSelector;
60
- }
61
- };
62
- export {
63
- ComboboxComponentStrategy
64
- };
@@ -1,81 +0,0 @@
1
- import {
2
- test_exports
3
- } from "./chunk-PK5L2SAF.js";
4
- import "./chunk-I2KLQ2HA.js";
5
-
6
- // src/utils/test/src/component-strategies/MenuComponentStrategy.ts
7
- var MenuComponentStrategy = class {
8
- constructor(mainSelector, selectors, actionTimeoutMs = 400, assertionTimeoutMs = 400) {
9
- this.mainSelector = mainSelector;
10
- this.selectors = selectors;
11
- this.actionTimeoutMs = actionTimeoutMs;
12
- this.assertionTimeoutMs = assertionTimeoutMs;
13
- }
14
- async resetState(page) {
15
- if (!this.selectors.popup) return;
16
- const popupSelector = this.selectors.popup;
17
- const popupElement = page.locator(popupSelector).first();
18
- const isPopupVisible = await popupElement.isVisible().catch(() => false);
19
- if (!isPopupVisible) return;
20
- let menuClosed = false;
21
- let closeSelector = this.selectors.input;
22
- if (!closeSelector && this.selectors.focusable) {
23
- closeSelector = this.selectors.focusable;
24
- } else if (!closeSelector) {
25
- closeSelector = this.selectors.trigger;
26
- }
27
- if (closeSelector) {
28
- const closeElement = page.locator(closeSelector).first();
29
- await closeElement.focus();
30
- await page.keyboard.press("Escape");
31
- menuClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
32
- }
33
- if (!menuClosed && this.selectors.trigger) {
34
- const triggerElement = page.locator(this.selectors.trigger).first();
35
- await triggerElement.click({ timeout: this.actionTimeoutMs });
36
- menuClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
37
- }
38
- if (!menuClosed) {
39
- await page.mouse.click(10, 10);
40
- menuClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
41
- }
42
- if (!menuClosed) {
43
- throw new Error(
44
- `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
45
- 1. Escape key
46
- 2. Clicking trigger
47
- 3. Clicking outside
48
- This indicates a problem with the menu component's close functionality.`
49
- );
50
- }
51
- if (this.selectors.input) {
52
- await page.locator(this.selectors.input).first().clear();
53
- }
54
- if (this.selectors.trigger) {
55
- const triggerElement = page.locator(this.selectors.trigger).first();
56
- await triggerElement.focus();
57
- }
58
- }
59
- async shouldSkipTest(test, page) {
60
- const requiresSubmenu = test.action.some(
61
- (act) => act.target === "submenu" || act.target === "submenuTrigger" || act.target === "submenuItems"
62
- ) || test.assertions.some(
63
- (assertion) => assertion.target === "submenu" || assertion.target === "submenuTrigger" || assertion.target === "submenuItems"
64
- );
65
- if (!requiresSubmenu) {
66
- return false;
67
- }
68
- const submenuTriggerSelector = this.selectors.submenuTrigger;
69
- if (!submenuTriggerSelector) {
70
- return true;
71
- }
72
- const submenuTriggerCount = await page.locator(submenuTriggerSelector).count();
73
- return submenuTriggerCount === 0;
74
- }
75
- getMainSelector() {
76
- return this.mainSelector;
77
- }
78
- };
79
- export {
80
- MenuComponentStrategy
81
- };
@@ -1,29 +0,0 @@
1
- import "./chunk-I2KLQ2HA.js";
2
-
3
- // src/utils/test/src/component-strategies/TabsComponentStrategy.ts
4
- var TabsComponentStrategy = class {
5
- constructor(mainSelector, selectors) {
6
- this.mainSelector = mainSelector;
7
- this.selectors = selectors;
8
- }
9
- async resetState() {
10
- }
11
- async shouldSkipTest(test, page) {
12
- if (test.isVertical !== void 0 && this.selectors.tablist) {
13
- const tablistSelector = this.selectors.tablist;
14
- const tablist = page.locator(tablistSelector).first();
15
- const orientation = await tablist.getAttribute("aria-orientation");
16
- const isVertical = orientation === "vertical";
17
- if (test.isVertical !== isVertical) {
18
- return true;
19
- }
20
- }
21
- return false;
22
- }
23
- getMainSelector() {
24
- return this.mainSelector;
25
- }
26
- };
27
- export {
28
- TabsComponentStrategy
29
- };
@@ -1,22 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
18
-
19
- export {
20
- __export,
21
- __reExport
22
- };
@@ -1,17 +0,0 @@
1
- import {
2
- __export,
3
- __reExport
4
- } from "./chunk-I2KLQ2HA.js";
5
-
6
- // node_modules/@playwright/test/index.mjs
7
- var test_exports = {};
8
- __export(test_exports, {
9
- default: () => default2
10
- });
11
- __reExport(test_exports, test_star);
12
- import * as test_star from "playwright/test";
13
- import { default as default2 } from "playwright/test";
14
-
15
- export {
16
- test_exports
17
- };
@@ -1,363 +0,0 @@
1
- // src/utils/test/contract/contract.json
2
- var contract_default = {
3
- menu: {
4
- path: "./aria-contracts/menu/menu.contract.json",
5
- component: "menu"
6
- },
7
- "combobox.listbox": {
8
- path: "./aria-contracts/combobox/combobox.listbox.contract.json",
9
- component: "combobox.listbox"
10
- },
11
- accordion: {
12
- path: "./aria-contracts/accordion/accordion.contract.json",
13
- component: "accordion"
14
- },
15
- tabs: {
16
- path: "./aria-contracts/tabs/tabs.contract.json",
17
- component: "tabs"
18
- }
19
- };
20
-
21
- // src/utils/test/src/ContractReporter.ts
22
- var ContractReporter = class {
23
- startTime = 0;
24
- componentName = "";
25
- staticPasses = 0;
26
- staticFailures = 0;
27
- staticWarnings = 0;
28
- dynamicResults = [];
29
- totalTests = 0;
30
- skipped = 0;
31
- warnings = 0;
32
- isPlaywright = false;
33
- isCustomContract = false;
34
- apgUrl = "https://www.w3.org/WAI/ARIA/apg/";
35
- hasPrintedStaticSection = false;
36
- hasPrintedDynamicSection = false;
37
- constructor(isPlaywright = false, isCustomContract = false) {
38
- this.isPlaywright = isPlaywright;
39
- this.isCustomContract = isCustomContract;
40
- }
41
- log(message) {
42
- process.stderr.write(message + "\n");
43
- }
44
- start(componentName, totalTests, apgUrl) {
45
- this.startTime = Date.now();
46
- this.componentName = componentName;
47
- this.totalTests = totalTests;
48
- this.hasPrintedStaticSection = false;
49
- this.hasPrintedDynamicSection = false;
50
- if (apgUrl) {
51
- this.apgUrl = apgUrl;
52
- }
53
- const mode = this.isPlaywright ? "Playwright (Real Browser)" : "jsdom (Fast)";
54
- this.log(`
55
- ${"\u2550".repeat(60)}`);
56
- this.log(`\u{1F50D} Testing ${componentName.charAt(0).toUpperCase() + componentName.slice(1)} Component - ${mode}`);
57
- this.log(`${"\u2550".repeat(60)}
58
- `);
59
- }
60
- reportStatic(passes, failures, warnings = 0) {
61
- this.staticPasses = passes;
62
- this.staticFailures = failures;
63
- this.staticWarnings = warnings;
64
- }
65
- /**
66
- * Report individual static test pass
67
- */
68
- reportStaticTest(description, status, failureMessage, level) {
69
- if (!this.hasPrintedStaticSection) {
70
- this.log(`${"\u2500".repeat(60)}`);
71
- this.log(`\u{1F9EA} Static Assertions`);
72
- this.log(`${"\u2500".repeat(60)}`);
73
- this.hasPrintedStaticSection = true;
74
- }
75
- const icon = status === "pass" ? "\u2713" : status === "warn" ? "\u26A0" : status === "skip" ? "\u25CB" : "\u2717";
76
- this.log(` ${icon} ${description}`);
77
- if (level) {
78
- this.log(` \u21B3 level=${level}`);
79
- }
80
- if ((status === "fail" || status === "warn" || status === "skip") && failureMessage) {
81
- this.log(` \u21B3 ${failureMessage}`);
82
- }
83
- }
84
- /**
85
- * Report individual dynamic test result
86
- */
87
- reportTest(test, status, failureMessage) {
88
- if (!this.hasPrintedDynamicSection) {
89
- this.log("");
90
- this.log(`${"\u2500".repeat(60)}`);
91
- this.log(`\u2328\uFE0F Dynamic Interaction Tests`);
92
- this.log(`${"\u2500".repeat(60)}`);
93
- this.hasPrintedDynamicSection = true;
94
- }
95
- const result = {
96
- description: test.description,
97
- status,
98
- failureMessage,
99
- level: test.level
100
- };
101
- if (status === "skip") {
102
- result.skipReason = "Requires real browser (addEventListener events)";
103
- }
104
- this.dynamicResults.push(result);
105
- const icons = { pass: "\u2713", fail: "\u2717", warn: "\u26A0", skip: "\u25CB" };
106
- const levelPrefix = test.level ? `[${test.level.toUpperCase()}] ` : "";
107
- this.log(` ${icons[status]} ${levelPrefix}${test.description}`);
108
- if (status === "skip" && !this.isPlaywright) {
109
- this.log(` \u21B3 Skipped in jsdom (runs in Playwright)`);
110
- }
111
- if (status === "fail" && failureMessage) {
112
- this.log(` \u21B3 ${failureMessage}`);
113
- }
114
- if (status === "warn" && failureMessage) {
115
- this.log(` \u21B3 ${failureMessage}`);
116
- }
117
- if (status === "skip" && failureMessage) {
118
- this.log(` \u21B3 ${failureMessage}`);
119
- }
120
- }
121
- /**
122
- * Report all failures with actionable context
123
- */
124
- reportFailures(failures) {
125
- if (failures.length === 0) return;
126
- this.log(`
127
- ${"\u2500".repeat(60)}`);
128
- this.log(`\u274C Failures (${failures.length}):
129
- `);
130
- failures.forEach((failure, index) => {
131
- this.log(`${index + 1}. ${failure}`);
132
- if (failure.includes("aria-")) {
133
- this.log(` \u{1F4A1} Add the missing ARIA attribute to improve screen reader support`);
134
- } else if (failure.includes("focus")) {
135
- this.log(` \u{1F4A1} Check keyboard event handlers and focus management`);
136
- } else if (failure.includes("visible")) {
137
- this.log(` \u{1F4A1} Verify display/visibility styles and state management`);
138
- }
139
- this.log("");
140
- });
141
- }
142
- reportWarnings() {
143
- const warnings = this.dynamicResults.filter((r) => r.status === "warn");
144
- if (warnings.length === 0 && this.staticWarnings === 0) return;
145
- this.log(`
146
- ${"\u2500".repeat(60)}`);
147
- this.log(`\u26A0\uFE0F Warnings (${this.staticWarnings + warnings.length}):
148
- `);
149
- this.log(`These checks are failing but treated as warnings under the active strictness mode.
150
- `);
151
- warnings.forEach((test, index) => {
152
- this.log(`${index + 1}. ${test.description}`);
153
- if (test.failureMessage) {
154
- this.log(` \u21B3 ${test.failureMessage}`);
155
- }
156
- if (test.level) {
157
- this.log(` \u21B3 level=${test.level}`);
158
- }
159
- });
160
- if (this.apgUrl) {
161
- this.log(`
162
- Reference: ${this.apgUrl}
163
- `);
164
- }
165
- }
166
- /**
167
- * Report skipped tests with helpful context
168
- */
169
- reportSkipped() {
170
- if (this.skipped === 0 || this.isPlaywright) return;
171
- const skippedTests = this.dynamicResults.filter((r) => r.status === "skip");
172
- this.log(`
173
- ${"\u2500".repeat(60)}`);
174
- this.log(`\u2139\uFE0F Skipped Tests (${this.skipped}):
175
- `);
176
- this.log(`These tests use native keyboard events via addEventListener,`);
177
- this.log(`which jsdom cannot simulate. They run successfully in Playwright.
178
- `);
179
- skippedTests.forEach((test, index) => {
180
- this.log(`${index + 1}. ${test.description}`);
181
- });
182
- this.log(`
183
- \u{1F4A1} Run with Playwright for full validation:`);
184
- this.log(` testUiComponent('${this.componentName}', null, 'http://localhost:5173/test-harness?component=component_name')
185
- `);
186
- }
187
- /**
188
- * Generate final summary with statistics
189
- */
190
- summary(failures) {
191
- const duration = Date.now() - this.startTime;
192
- const dynamicPasses = this.dynamicResults.filter((r) => r.status === "pass").length;
193
- const dynamicFailures = this.dynamicResults.filter((r) => r.status === "fail").length;
194
- const dynamicWarnings = this.dynamicResults.filter((r) => r.status === "warn").length;
195
- this.skipped = this.dynamicResults.filter((r) => r.status === "skip").length;
196
- this.warnings = this.staticWarnings + dynamicWarnings;
197
- const totalPasses = this.staticPasses + dynamicPasses;
198
- const totalFailures = this.staticFailures + dynamicFailures;
199
- const totalRun = totalPasses + totalFailures + this.warnings;
200
- const getComponentMessage = () => {
201
- const componentDisplayName = `${this.componentName.charAt(0).toUpperCase()}${this.componentName.slice(1)}`;
202
- if (this.isCustomContract) {
203
- return `${componentDisplayName} component validates against your custom accessibility policy \u2713`;
204
- }
205
- return `${componentDisplayName} component meets Aria-Ease baseline WAI-ARIA expectations \u2713`;
206
- };
207
- if (failures.length > 0) {
208
- this.reportFailures(failures);
209
- }
210
- this.reportWarnings();
211
- this.reportSkipped();
212
- this.log(`
213
- ${"\u2550".repeat(60)}`);
214
- this.log(`\u{1F4CA} Summary
215
- `);
216
- if (totalFailures === 0 && this.skipped === 0 && this.warnings === 0) {
217
- this.log(`\u2705 All ${totalRun} tests passed!`);
218
- this.log(` ${getComponentMessage()}`);
219
- } else if (totalFailures === 0) {
220
- this.log(`\u2705 ${totalPasses}/${totalRun} tests passed`);
221
- if (this.skipped > 0) {
222
- this.log(`\u25CB ${this.skipped} tests skipped`);
223
- }
224
- if (this.warnings > 0) {
225
- this.log(`\u26A0\uFE0F ${this.warnings} warning${this.warnings > 1 ? "s" : ""}`);
226
- }
227
- this.log(` ${getComponentMessage()}`);
228
- } else {
229
- this.log(`\u274C ${totalFailures} test${totalFailures > 1 ? "s" : ""} failed`);
230
- this.log(`\u2705 ${totalPasses} test${totalPasses > 1 ? "s" : ""} passed`);
231
- if (this.warnings > 0) {
232
- this.log(`\u26A0\uFE0F ${this.warnings} warning${this.warnings > 1 ? "s" : ""}`);
233
- }
234
- if (this.skipped > 0) {
235
- this.log(`\u25CB ${this.skipped} test${this.skipped > 1 ? "s" : ""} skipped`);
236
- }
237
- }
238
- this.log(`\u23F1\uFE0F Duration: ${duration}ms`);
239
- this.log(`${"\u2550".repeat(60)}
240
- `);
241
- if (totalFailures > 0) {
242
- this.log(`\u{1F527} Next Steps:`);
243
- this.log(` 1. Review the failures above`);
244
- this.log(` 2. Fix ARIA attributes and keyboard handlers`);
245
- this.log(` 3. Re-run tests to verify fixes
246
- `);
247
- } else if (!this.isPlaywright && this.skipped > 0) {
248
- this.log(`\u2728 Optional: Run Playwright tests for complete validation
249
- `);
250
- }
251
- return {
252
- passes: totalPasses,
253
- failures: totalFailures,
254
- skipped: this.skipped,
255
- duration
256
- };
257
- }
258
- /**
259
- * Report an error during test execution
260
- */
261
- error(message, context) {
262
- this.log(`
263
- \u274C Error: ${message}`);
264
- if (context) {
265
- this.log(` Context: ${context}`);
266
- }
267
- this.log("");
268
- }
269
- };
270
-
271
- // src/utils/test/src/strictness.ts
272
- var FALLBACK_LEVEL = "required";
273
- function normalizeLevel(level) {
274
- if (level === "required" || level === "recommended" || level === "optional") {
275
- return level;
276
- }
277
- return FALLBACK_LEVEL;
278
- }
279
- function normalizeStrictness(strictness) {
280
- if (strictness === "minimal" || strictness === "balanced" || strictness === "strict" || strictness === "paranoid") {
281
- return strictness;
282
- }
283
- return "balanced";
284
- }
285
- function resolveEnforcement(level, strictness) {
286
- const matrix = {
287
- minimal: {
288
- required: "error",
289
- recommended: "ignore",
290
- optional: "ignore"
291
- },
292
- balanced: {
293
- required: "error",
294
- recommended: "warning",
295
- optional: "ignore"
296
- },
297
- strict: {
298
- required: "error",
299
- recommended: "error",
300
- optional: "warning"
301
- },
302
- paranoid: {
303
- required: "error",
304
- recommended: "error",
305
- optional: "error"
306
- }
307
- };
308
- return matrix[strictness][level];
309
- }
310
-
311
- // src/utils/test/src/playwrightTestHarness.ts
312
- import { chromium } from "playwright";
313
- var sharedBrowser = null;
314
- var sharedContext = null;
315
- async function getOrCreateBrowser() {
316
- if (!sharedBrowser) {
317
- sharedBrowser = await chromium.launch({
318
- headless: true,
319
- // Launch with clean browser profile - no extensions, no user data
320
- args: [
321
- "--disable-extensions",
322
- "--disable-blink-features=AutomationControlled"
323
- ]
324
- });
325
- }
326
- return sharedBrowser;
327
- }
328
- async function getOrCreateContext() {
329
- if (!sharedContext) {
330
- const browser = await getOrCreateBrowser();
331
- sharedContext = await browser.newContext({
332
- // Isolated context - no permissions, no geolocation, etc.
333
- permissions: [],
334
- // Ignore HTTPS errors for local dev servers
335
- ignoreHTTPSErrors: true
336
- });
337
- }
338
- return sharedContext;
339
- }
340
- async function createTestPage() {
341
- const context = await getOrCreateContext();
342
- return await context.newPage();
343
- }
344
- async function closeSharedBrowser() {
345
- if (sharedContext) {
346
- await sharedContext.close();
347
- sharedContext = null;
348
- }
349
- if (sharedBrowser) {
350
- await sharedBrowser.close();
351
- sharedBrowser = null;
352
- }
353
- }
354
-
355
- export {
356
- contract_default,
357
- ContractReporter,
358
- normalizeLevel,
359
- normalizeStrictness,
360
- resolveEnforcement,
361
- createTestPage,
362
- closeSharedBrowser
363
- };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes