aria-ease 3.0.1 → 3.0.3
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/README.md +6 -6
- package/bin/{audit-XZJXMUPL.js → audit-6A7OW5NJ.js} +1 -1
- package/bin/{chunk-JSBRDJBE.js → chunk-2P3A4VVY.js} +7 -0
- package/bin/cli.cjs +128 -48
- package/bin/cli.js +4 -4
- package/bin/{contractTestRunnerPlaywright-62LXHK7K.js → contractTestRunnerPlaywright-3VJUZSYK.js} +74 -31
- package/bin/{formatters-U4E5EVPL.js → formatters-FCDHFTPI.js} +1 -1
- package/bin/{test-PK5MBHIN.js → test-D374H2ZS.js} +48 -13
- package/dist/{chunk-57O4KFP4.js → chunk-IPJYOFRK.js} +7 -0
- package/dist/{contractTestRunnerPlaywright-LGXSV2ZS.js → contractTestRunnerPlaywright-4UOHWGWD.js} +73 -31
- package/dist/index.cjs +125 -43
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +51 -14
- package/dist/src/combobox/index.cjs +3 -1
- package/dist/src/combobox/index.js +3 -1
- package/dist/src/utils/test/{chunk-57O4KFP4.js → chunk-IPJYOFRK.js} +6 -1
- package/dist/src/utils/test/{contractTestRunnerPlaywright-LGXSV2ZS.js → contractTestRunnerPlaywright-4UOHWGWD.js} +68 -31
- package/dist/src/utils/test/contracts/MenuContract.json +1 -0
- package/dist/src/utils/test/index.cjs +139 -42
- package/dist/src/utils/test/index.d.cts +5 -4
- package/dist/src/utils/test/index.d.ts +5 -4
- package/dist/src/utils/test/index.js +48 -13
- package/package.json +10 -7
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { ContractReporter, contract_default } from './chunk-
|
|
1
|
+
import { __export, __reExport, ContractReporter, contract_default } from './chunk-IPJYOFRK.js';
|
|
2
2
|
import { chromium } from 'playwright';
|
|
3
|
+
import * as default2 from 'playwright/test';
|
|
4
|
+
import default2__default from 'playwright/test';
|
|
3
5
|
import { readFileSync } from 'fs';
|
|
4
6
|
|
|
7
|
+
// node_modules/@playwright/test/index.mjs
|
|
8
|
+
var test_exports = {};
|
|
9
|
+
__export(test_exports, {
|
|
10
|
+
default: () => default2__default
|
|
11
|
+
});
|
|
12
|
+
__reExport(test_exports, default2);
|
|
5
13
|
async function runContractTestsPlaywright(componentName, url) {
|
|
6
14
|
const reporter = new ContractReporter(true);
|
|
7
15
|
const contractTyped = contract_default;
|
|
@@ -16,6 +24,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
16
24
|
reporter.start(componentName, totalTests);
|
|
17
25
|
const failures = [];
|
|
18
26
|
const passes = [];
|
|
27
|
+
const skipped = [];
|
|
19
28
|
let browser = null;
|
|
20
29
|
try {
|
|
21
30
|
browser = await chromium.launch({ headless: true });
|
|
@@ -23,13 +32,25 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
23
32
|
const page = await context.newPage();
|
|
24
33
|
await page.goto(url, {
|
|
25
34
|
waitUntil: "domcontentloaded",
|
|
26
|
-
timeout:
|
|
35
|
+
timeout: 9e4
|
|
27
36
|
});
|
|
28
37
|
const mainSelector = componentContract.selectors.trigger || componentContract.selectors.input || componentContract.selectors.container;
|
|
29
38
|
if (!mainSelector) {
|
|
30
39
|
throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
|
|
31
40
|
}
|
|
32
|
-
await page.waitForSelector(mainSelector, { timeout:
|
|
41
|
+
await page.waitForSelector(mainSelector, { timeout: 9e4 });
|
|
42
|
+
if (componentName === "menu" && componentContract.selectors.trigger) {
|
|
43
|
+
await page.waitForFunction(
|
|
44
|
+
(selector) => {
|
|
45
|
+
const trigger = document.querySelector(selector);
|
|
46
|
+
return trigger && trigger.getAttribute("data-menu-initialized") === "true";
|
|
47
|
+
},
|
|
48
|
+
componentContract.selectors.trigger,
|
|
49
|
+
{ timeout: 6e3 }
|
|
50
|
+
).catch(() => {
|
|
51
|
+
console.warn("Menu initialization signal not detected, continuing with tests...");
|
|
52
|
+
});
|
|
53
|
+
}
|
|
33
54
|
async function resolveRelativeTarget(selector, relative) {
|
|
34
55
|
const items = await page.locator(selector).all();
|
|
35
56
|
switch (relative) {
|
|
@@ -115,7 +136,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
115
136
|
if (componentContract.selectors.input) {
|
|
116
137
|
const inputElement = page.locator(componentContract.selectors.input).first();
|
|
117
138
|
await inputElement.clear();
|
|
118
|
-
await page.waitForTimeout(
|
|
139
|
+
await page.waitForTimeout(100);
|
|
119
140
|
}
|
|
120
141
|
}
|
|
121
142
|
}
|
|
@@ -128,7 +149,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
128
149
|
continue;
|
|
129
150
|
}
|
|
130
151
|
await page.locator(focusSelector).first().focus();
|
|
131
|
-
await page.waitForTimeout(
|
|
152
|
+
await page.waitForTimeout(100);
|
|
132
153
|
}
|
|
133
154
|
if (act.type === "type" && act.value) {
|
|
134
155
|
const typeSelector = componentContract.selectors[act.target];
|
|
@@ -137,7 +158,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
137
158
|
continue;
|
|
138
159
|
}
|
|
139
160
|
await page.locator(typeSelector).first().fill(act.value);
|
|
140
|
-
await page.waitForTimeout(
|
|
161
|
+
await page.waitForTimeout(100);
|
|
141
162
|
}
|
|
142
163
|
if (act.type === "click") {
|
|
143
164
|
if (act.target === "document") {
|
|
@@ -154,7 +175,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
154
175
|
continue;
|
|
155
176
|
}
|
|
156
177
|
await relativeElement.click();
|
|
157
|
-
await page.waitForTimeout(200);
|
|
178
|
+
await page.waitForTimeout(componentName === "menu" ? 500 : 200);
|
|
158
179
|
} else {
|
|
159
180
|
const actionSelector = componentContract.selectors[act.target];
|
|
160
181
|
if (!actionSelector) {
|
|
@@ -162,7 +183,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
162
183
|
continue;
|
|
163
184
|
}
|
|
164
185
|
await page.locator(actionSelector).first().click();
|
|
165
|
-
await page.waitForTimeout(200);
|
|
186
|
+
await page.waitForTimeout(componentName === "menu" ? 500 : 200);
|
|
166
187
|
}
|
|
167
188
|
}
|
|
168
189
|
if (act.type === "keypress" && act.key) {
|
|
@@ -187,7 +208,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
187
208
|
if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
|
|
188
209
|
await page.waitForTimeout(100);
|
|
189
210
|
await page.keyboard.press(keyValue);
|
|
190
|
-
await page.waitForTimeout(
|
|
211
|
+
await page.waitForTimeout(100);
|
|
191
212
|
} else {
|
|
192
213
|
const keypressSelector = componentContract.selectors[act.target];
|
|
193
214
|
if (!keypressSelector) {
|
|
@@ -216,7 +237,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
216
237
|
continue;
|
|
217
238
|
}
|
|
218
239
|
await relativeElement.hover();
|
|
219
|
-
await page.waitForTimeout(
|
|
240
|
+
await page.waitForTimeout(100);
|
|
220
241
|
} else {
|
|
221
242
|
const hoverSelector = componentContract.selectors[act.target];
|
|
222
243
|
if (!hoverSelector) {
|
|
@@ -224,7 +245,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
224
245
|
continue;
|
|
225
246
|
}
|
|
226
247
|
await page.locator(hoverSelector).first().hover();
|
|
227
|
-
await page.waitForTimeout(
|
|
248
|
+
await page.waitForTimeout(100);
|
|
228
249
|
}
|
|
229
250
|
}
|
|
230
251
|
await page.waitForTimeout(100);
|
|
@@ -256,32 +277,48 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
256
277
|
continue;
|
|
257
278
|
}
|
|
258
279
|
if (assertion.assertion === "toBeVisible") {
|
|
259
|
-
|
|
260
|
-
|
|
280
|
+
try {
|
|
281
|
+
await (0, test_exports.expect)(target).toBeVisible({ timeout: 3e3 });
|
|
261
282
|
passes.push(`${assertion.target} is visible as expected. Test: "${dynamicTest.description}".`);
|
|
262
|
-
}
|
|
263
|
-
|
|
283
|
+
} catch {
|
|
284
|
+
const debugState = await page.evaluate((sel) => {
|
|
285
|
+
const el = sel ? document.querySelector(sel) : null;
|
|
286
|
+
if (!el) return "element not found";
|
|
287
|
+
const styles = window.getComputedStyle(el);
|
|
288
|
+
return `display:${styles.display}, visibility:${styles.visibility}, opacity:${styles.opacity}`;
|
|
289
|
+
}, componentContract.selectors[assertion.target] || "");
|
|
290
|
+
failures.push(`${assertion.failureMessage} (actual: ${debugState})`);
|
|
264
291
|
}
|
|
265
292
|
}
|
|
266
293
|
if (assertion.assertion === "notToBeVisible") {
|
|
267
|
-
|
|
268
|
-
|
|
294
|
+
try {
|
|
295
|
+
await (0, test_exports.expect)(target).toBeHidden({ timeout: 5e3 });
|
|
269
296
|
passes.push(`${assertion.target} is not visible as expected. Test: "${dynamicTest.description}".`);
|
|
270
|
-
}
|
|
271
|
-
|
|
297
|
+
} catch {
|
|
298
|
+
const debugState = await page.evaluate((sel) => {
|
|
299
|
+
const el = sel ? document.querySelector(sel) : null;
|
|
300
|
+
if (!el) return "element not found";
|
|
301
|
+
const styles = window.getComputedStyle(el);
|
|
302
|
+
return `display:${styles.display}, visibility:${styles.visibility}, opacity:${styles.opacity}`;
|
|
303
|
+
}, componentContract.selectors[assertion.target] || "");
|
|
304
|
+
failures.push(assertion.failureMessage + ` ${assertion.target} is still visible (actual: ${debugState}).`);
|
|
272
305
|
}
|
|
273
306
|
}
|
|
274
307
|
if (assertion.assertion === "toHaveAttribute" && assertion.attribute && assertion.expectedValue) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
308
|
+
try {
|
|
309
|
+
if (assertion.expectedValue === "!empty") {
|
|
310
|
+
const attributeValue = await target.getAttribute(assertion.attribute);
|
|
311
|
+
if (attributeValue && attributeValue.trim() !== "") {
|
|
312
|
+
passes.push(`${assertion.target} has non-empty "${assertion.attribute}". Test: "${dynamicTest.description}".`);
|
|
313
|
+
} else {
|
|
314
|
+
failures.push(assertion.failureMessage + ` ${assertion.target} "${assertion.attribute}" should not be empty, found "${attributeValue}".`);
|
|
315
|
+
}
|
|
279
316
|
} else {
|
|
280
|
-
|
|
317
|
+
await (0, test_exports.expect)(target).toHaveAttribute(assertion.attribute, assertion.expectedValue, { timeout: 3e3 });
|
|
318
|
+
passes.push(`${assertion.target} has expected "${assertion.attribute}". Test: "${dynamicTest.description}".`);
|
|
281
319
|
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
} else {
|
|
320
|
+
} catch {
|
|
321
|
+
const attributeValue = await target.getAttribute(assertion.attribute);
|
|
285
322
|
failures.push(assertion.failureMessage + ` ${assertion.target} "${assertion.attribute}" should be "${assertion.expectedValue}", found "${attributeValue}".`);
|
|
286
323
|
}
|
|
287
324
|
}
|
|
@@ -306,10 +343,10 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
306
343
|
}
|
|
307
344
|
}
|
|
308
345
|
if (assertion.assertion === "toHaveFocus") {
|
|
309
|
-
|
|
310
|
-
|
|
346
|
+
try {
|
|
347
|
+
await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
|
|
311
348
|
passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
|
|
312
|
-
}
|
|
349
|
+
} catch {
|
|
313
350
|
failures.push(`${assertion.failureMessage}`);
|
|
314
351
|
}
|
|
315
352
|
}
|
|
@@ -350,7 +387,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
350
387
|
} finally {
|
|
351
388
|
if (browser) await browser.close();
|
|
352
389
|
}
|
|
353
|
-
return { passes, failures };
|
|
390
|
+
return { passes, failures, skipped };
|
|
354
391
|
}
|
|
355
392
|
|
|
356
393
|
export { runContractTestsPlaywright };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var default2 = require('playwright/test');
|
|
3
4
|
var playwright = require('playwright');
|
|
4
5
|
var fs = require('fs');
|
|
5
6
|
var jestAxe = require('jest-axe');
|
|
@@ -8,6 +9,25 @@ var fs$1 = require('fs/promises');
|
|
|
8
9
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
11
|
|
|
12
|
+
function _interopNamespace(e) {
|
|
13
|
+
if (e && e.__esModule) return e;
|
|
14
|
+
var n = Object.create(null);
|
|
15
|
+
if (e) {
|
|
16
|
+
Object.keys(e).forEach(function (k) {
|
|
17
|
+
if (k !== 'default') {
|
|
18
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
19
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return e[k]; }
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
n.default = e;
|
|
27
|
+
return Object.freeze(n);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var default2__namespace = /*#__PURE__*/_interopNamespace(default2);
|
|
11
31
|
var fs__default = /*#__PURE__*/_interopDefault(fs$1);
|
|
12
32
|
|
|
13
33
|
var __create = Object.create;
|
|
@@ -34,6 +54,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
34
54
|
}
|
|
35
55
|
return to;
|
|
36
56
|
};
|
|
57
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget);
|
|
37
58
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
38
59
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
39
60
|
// file that has been converted to a CommonJS file using a Babel-
|
|
@@ -9237,6 +9258,17 @@ ${"\u2550".repeat(60)}`);
|
|
|
9237
9258
|
}
|
|
9238
9259
|
});
|
|
9239
9260
|
|
|
9261
|
+
// node_modules/@playwright/test/index.mjs
|
|
9262
|
+
var test_exports = {};
|
|
9263
|
+
__export(test_exports, {
|
|
9264
|
+
default: () => default2__namespace.default
|
|
9265
|
+
});
|
|
9266
|
+
var init_test = __esm({
|
|
9267
|
+
"node_modules/@playwright/test/index.mjs"() {
|
|
9268
|
+
__reExport(test_exports, default2__namespace);
|
|
9269
|
+
}
|
|
9270
|
+
});
|
|
9271
|
+
|
|
9240
9272
|
// src/utils/test/contract/contractTestRunnerPlaywright.ts
|
|
9241
9273
|
var contractTestRunnerPlaywright_exports = {};
|
|
9242
9274
|
__export(contractTestRunnerPlaywright_exports, {
|
|
@@ -9256,6 +9288,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9256
9288
|
reporter.start(componentName, totalTests);
|
|
9257
9289
|
const failures = [];
|
|
9258
9290
|
const passes = [];
|
|
9291
|
+
const skipped = [];
|
|
9259
9292
|
let browser = null;
|
|
9260
9293
|
try {
|
|
9261
9294
|
browser = await playwright.chromium.launch({ headless: true });
|
|
@@ -9263,13 +9296,25 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9263
9296
|
const page = await context.newPage();
|
|
9264
9297
|
await page.goto(url, {
|
|
9265
9298
|
waitUntil: "domcontentloaded",
|
|
9266
|
-
timeout:
|
|
9299
|
+
timeout: 9e4
|
|
9267
9300
|
});
|
|
9268
9301
|
const mainSelector = componentContract.selectors.trigger || componentContract.selectors.input || componentContract.selectors.container;
|
|
9269
9302
|
if (!mainSelector) {
|
|
9270
9303
|
throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
|
|
9271
9304
|
}
|
|
9272
|
-
await page.waitForSelector(mainSelector, { timeout:
|
|
9305
|
+
await page.waitForSelector(mainSelector, { timeout: 9e4 });
|
|
9306
|
+
if (componentName === "menu" && componentContract.selectors.trigger) {
|
|
9307
|
+
await page.waitForFunction(
|
|
9308
|
+
(selector) => {
|
|
9309
|
+
const trigger = document.querySelector(selector);
|
|
9310
|
+
return trigger && trigger.getAttribute("data-menu-initialized") === "true";
|
|
9311
|
+
},
|
|
9312
|
+
componentContract.selectors.trigger,
|
|
9313
|
+
{ timeout: 6e3 }
|
|
9314
|
+
).catch(() => {
|
|
9315
|
+
console.warn("Menu initialization signal not detected, continuing with tests...");
|
|
9316
|
+
});
|
|
9317
|
+
}
|
|
9273
9318
|
async function resolveRelativeTarget(selector, relative) {
|
|
9274
9319
|
const items = await page.locator(selector).all();
|
|
9275
9320
|
switch (relative) {
|
|
@@ -9355,7 +9400,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9355
9400
|
if (componentContract.selectors.input) {
|
|
9356
9401
|
const inputElement = page.locator(componentContract.selectors.input).first();
|
|
9357
9402
|
await inputElement.clear();
|
|
9358
|
-
await page.waitForTimeout(
|
|
9403
|
+
await page.waitForTimeout(100);
|
|
9359
9404
|
}
|
|
9360
9405
|
}
|
|
9361
9406
|
}
|
|
@@ -9368,7 +9413,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9368
9413
|
continue;
|
|
9369
9414
|
}
|
|
9370
9415
|
await page.locator(focusSelector).first().focus();
|
|
9371
|
-
await page.waitForTimeout(
|
|
9416
|
+
await page.waitForTimeout(100);
|
|
9372
9417
|
}
|
|
9373
9418
|
if (act.type === "type" && act.value) {
|
|
9374
9419
|
const typeSelector = componentContract.selectors[act.target];
|
|
@@ -9377,7 +9422,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9377
9422
|
continue;
|
|
9378
9423
|
}
|
|
9379
9424
|
await page.locator(typeSelector).first().fill(act.value);
|
|
9380
|
-
await page.waitForTimeout(
|
|
9425
|
+
await page.waitForTimeout(100);
|
|
9381
9426
|
}
|
|
9382
9427
|
if (act.type === "click") {
|
|
9383
9428
|
if (act.target === "document") {
|
|
@@ -9394,7 +9439,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9394
9439
|
continue;
|
|
9395
9440
|
}
|
|
9396
9441
|
await relativeElement.click();
|
|
9397
|
-
await page.waitForTimeout(200);
|
|
9442
|
+
await page.waitForTimeout(componentName === "menu" ? 500 : 200);
|
|
9398
9443
|
} else {
|
|
9399
9444
|
const actionSelector = componentContract.selectors[act.target];
|
|
9400
9445
|
if (!actionSelector) {
|
|
@@ -9402,7 +9447,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9402
9447
|
continue;
|
|
9403
9448
|
}
|
|
9404
9449
|
await page.locator(actionSelector).first().click();
|
|
9405
|
-
await page.waitForTimeout(200);
|
|
9450
|
+
await page.waitForTimeout(componentName === "menu" ? 500 : 200);
|
|
9406
9451
|
}
|
|
9407
9452
|
}
|
|
9408
9453
|
if (act.type === "keypress" && act.key) {
|
|
@@ -9427,7 +9472,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9427
9472
|
if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
|
|
9428
9473
|
await page.waitForTimeout(100);
|
|
9429
9474
|
await page.keyboard.press(keyValue);
|
|
9430
|
-
await page.waitForTimeout(
|
|
9475
|
+
await page.waitForTimeout(100);
|
|
9431
9476
|
} else {
|
|
9432
9477
|
const keypressSelector = componentContract.selectors[act.target];
|
|
9433
9478
|
if (!keypressSelector) {
|
|
@@ -9456,7 +9501,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9456
9501
|
continue;
|
|
9457
9502
|
}
|
|
9458
9503
|
await relativeElement.hover();
|
|
9459
|
-
await page.waitForTimeout(
|
|
9504
|
+
await page.waitForTimeout(100);
|
|
9460
9505
|
} else {
|
|
9461
9506
|
const hoverSelector = componentContract.selectors[act.target];
|
|
9462
9507
|
if (!hoverSelector) {
|
|
@@ -9464,7 +9509,7 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9464
9509
|
continue;
|
|
9465
9510
|
}
|
|
9466
9511
|
await page.locator(hoverSelector).first().hover();
|
|
9467
|
-
await page.waitForTimeout(
|
|
9512
|
+
await page.waitForTimeout(100);
|
|
9468
9513
|
}
|
|
9469
9514
|
}
|
|
9470
9515
|
await page.waitForTimeout(100);
|
|
@@ -9496,32 +9541,48 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9496
9541
|
continue;
|
|
9497
9542
|
}
|
|
9498
9543
|
if (assertion.assertion === "toBeVisible") {
|
|
9499
|
-
|
|
9500
|
-
|
|
9544
|
+
try {
|
|
9545
|
+
await (0, test_exports.expect)(target).toBeVisible({ timeout: 3e3 });
|
|
9501
9546
|
passes.push(`${assertion.target} is visible as expected. Test: "${dynamicTest.description}".`);
|
|
9502
|
-
}
|
|
9503
|
-
|
|
9547
|
+
} catch {
|
|
9548
|
+
const debugState = await page.evaluate((sel) => {
|
|
9549
|
+
const el = sel ? document.querySelector(sel) : null;
|
|
9550
|
+
if (!el) return "element not found";
|
|
9551
|
+
const styles = window.getComputedStyle(el);
|
|
9552
|
+
return `display:${styles.display}, visibility:${styles.visibility}, opacity:${styles.opacity}`;
|
|
9553
|
+
}, componentContract.selectors[assertion.target] || "");
|
|
9554
|
+
failures.push(`${assertion.failureMessage} (actual: ${debugState})`);
|
|
9504
9555
|
}
|
|
9505
9556
|
}
|
|
9506
9557
|
if (assertion.assertion === "notToBeVisible") {
|
|
9507
|
-
|
|
9508
|
-
|
|
9558
|
+
try {
|
|
9559
|
+
await (0, test_exports.expect)(target).toBeHidden({ timeout: 5e3 });
|
|
9509
9560
|
passes.push(`${assertion.target} is not visible as expected. Test: "${dynamicTest.description}".`);
|
|
9510
|
-
}
|
|
9511
|
-
|
|
9561
|
+
} catch {
|
|
9562
|
+
const debugState = await page.evaluate((sel) => {
|
|
9563
|
+
const el = sel ? document.querySelector(sel) : null;
|
|
9564
|
+
if (!el) return "element not found";
|
|
9565
|
+
const styles = window.getComputedStyle(el);
|
|
9566
|
+
return `display:${styles.display}, visibility:${styles.visibility}, opacity:${styles.opacity}`;
|
|
9567
|
+
}, componentContract.selectors[assertion.target] || "");
|
|
9568
|
+
failures.push(assertion.failureMessage + ` ${assertion.target} is still visible (actual: ${debugState}).`);
|
|
9512
9569
|
}
|
|
9513
9570
|
}
|
|
9514
9571
|
if (assertion.assertion === "toHaveAttribute" && assertion.attribute && assertion.expectedValue) {
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9572
|
+
try {
|
|
9573
|
+
if (assertion.expectedValue === "!empty") {
|
|
9574
|
+
const attributeValue = await target.getAttribute(assertion.attribute);
|
|
9575
|
+
if (attributeValue && attributeValue.trim() !== "") {
|
|
9576
|
+
passes.push(`${assertion.target} has non-empty "${assertion.attribute}". Test: "${dynamicTest.description}".`);
|
|
9577
|
+
} else {
|
|
9578
|
+
failures.push(assertion.failureMessage + ` ${assertion.target} "${assertion.attribute}" should not be empty, found "${attributeValue}".`);
|
|
9579
|
+
}
|
|
9519
9580
|
} else {
|
|
9520
|
-
|
|
9581
|
+
await (0, test_exports.expect)(target).toHaveAttribute(assertion.attribute, assertion.expectedValue, { timeout: 3e3 });
|
|
9582
|
+
passes.push(`${assertion.target} has expected "${assertion.attribute}". Test: "${dynamicTest.description}".`);
|
|
9521
9583
|
}
|
|
9522
|
-
}
|
|
9523
|
-
|
|
9524
|
-
} else {
|
|
9584
|
+
} catch {
|
|
9585
|
+
const attributeValue = await target.getAttribute(assertion.attribute);
|
|
9525
9586
|
failures.push(assertion.failureMessage + ` ${assertion.target} "${assertion.attribute}" should be "${assertion.expectedValue}", found "${attributeValue}".`);
|
|
9526
9587
|
}
|
|
9527
9588
|
}
|
|
@@ -9546,10 +9607,10 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9546
9607
|
}
|
|
9547
9608
|
}
|
|
9548
9609
|
if (assertion.assertion === "toHaveFocus") {
|
|
9549
|
-
|
|
9550
|
-
|
|
9610
|
+
try {
|
|
9611
|
+
await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
|
|
9551
9612
|
passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
|
|
9552
|
-
}
|
|
9613
|
+
} catch {
|
|
9553
9614
|
failures.push(`${assertion.failureMessage}`);
|
|
9554
9615
|
}
|
|
9555
9616
|
}
|
|
@@ -9590,10 +9651,11 @@ async function runContractTestsPlaywright(componentName, url) {
|
|
|
9590
9651
|
} finally {
|
|
9591
9652
|
if (browser) await browser.close();
|
|
9592
9653
|
}
|
|
9593
|
-
return { passes, failures };
|
|
9654
|
+
return { passes, failures, skipped };
|
|
9594
9655
|
}
|
|
9595
9656
|
var init_contractTestRunnerPlaywright = __esm({
|
|
9596
9657
|
"src/utils/test/contract/contractTestRunnerPlaywright.ts"() {
|
|
9658
|
+
init_test();
|
|
9597
9659
|
init_contract();
|
|
9598
9660
|
init_ContractReporter();
|
|
9599
9661
|
}
|
|
@@ -13140,20 +13202,54 @@ async function runContractTests(componentName, component) {
|
|
|
13140
13202
|
const staticFailed = 0;
|
|
13141
13203
|
reporter.reportStatic(staticPassed, staticFailed);
|
|
13142
13204
|
reporter.summary(failures);
|
|
13143
|
-
return { passes, failures };
|
|
13205
|
+
return { passes, failures, skipped };
|
|
13144
13206
|
}
|
|
13145
13207
|
|
|
13146
13208
|
// src/utils/test/src/test.ts
|
|
13147
13209
|
async function testUiComponent(componentName, component, url) {
|
|
13148
|
-
|
|
13210
|
+
if (!componentName || typeof componentName !== "string") {
|
|
13211
|
+
throw new Error("\u274C testUiComponent requires a valid componentName (string)");
|
|
13212
|
+
}
|
|
13213
|
+
if (!component || !(component instanceof HTMLElement)) {
|
|
13214
|
+
throw new Error("\u274C testUiComponent requires a valid component (HTMLElement)");
|
|
13215
|
+
}
|
|
13216
|
+
if (url && typeof url !== "string") {
|
|
13217
|
+
throw new Error("\u274C testUiComponent url parameter must be a string");
|
|
13218
|
+
}
|
|
13219
|
+
let results;
|
|
13220
|
+
try {
|
|
13221
|
+
results = await jestAxe.axe(component);
|
|
13222
|
+
} catch (error) {
|
|
13223
|
+
throw new Error(
|
|
13224
|
+
`\u274C Axe accessibility scan failed
|
|
13225
|
+
Error: ${error instanceof Error ? error.message : String(error)}`
|
|
13226
|
+
);
|
|
13227
|
+
}
|
|
13149
13228
|
let contract;
|
|
13150
|
-
|
|
13151
|
-
|
|
13152
|
-
|
|
13153
|
-
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13229
|
+
try {
|
|
13230
|
+
if (url) {
|
|
13231
|
+
console.log(`\u{1F3AD} Running Playwright E2E tests on ${url}`);
|
|
13232
|
+
try {
|
|
13233
|
+
new URL(url);
|
|
13234
|
+
} catch {
|
|
13235
|
+
throw new Error(
|
|
13236
|
+
`\u274C Invalid URL format: "${url}"
|
|
13237
|
+
URL must include protocol (e.g., "http://localhost:5173/test")`
|
|
13238
|
+
);
|
|
13239
|
+
}
|
|
13240
|
+
const { runContractTestsPlaywright: runContractTestsPlaywright2 } = await Promise.resolve().then(() => (init_contractTestRunnerPlaywright(), contractTestRunnerPlaywright_exports));
|
|
13241
|
+
contract = await runContractTestsPlaywright2(componentName, url);
|
|
13242
|
+
} else {
|
|
13243
|
+
console.log(`\u{1F9EA} Running jsdom tests (limited event handling)`);
|
|
13244
|
+
console.log(`Some tests may be skipped or yield false positives/negatives.
|
|
13245
|
+
For full coverage, run with a URL to enable Playwright E2E tests.`);
|
|
13246
|
+
contract = await runContractTests(componentName, component);
|
|
13247
|
+
}
|
|
13248
|
+
} catch (error) {
|
|
13249
|
+
if (error instanceof Error) {
|
|
13250
|
+
throw error;
|
|
13251
|
+
}
|
|
13252
|
+
throw new Error(`\u274C Contract test execution failed: ${String(error)}`);
|
|
13157
13253
|
}
|
|
13158
13254
|
const result = {
|
|
13159
13255
|
violations: results.violations,
|
|
@@ -13164,10 +13260,11 @@ async function testUiComponent(componentName, component, url) {
|
|
|
13164
13260
|
const mode = url ? "Playwright" : "jsdom";
|
|
13165
13261
|
throw new Error(
|
|
13166
13262
|
`
|
|
13167
|
-
\u274C ${contract.failures.length}
|
|
13168
|
-
\u2705 ${contract.passes.length}
|
|
13263
|
+
\u274C ${contract.failures.length} accessibility contract test${contract.failures.length > 1 ? "s" : ""} failed (${mode} mode)
|
|
13264
|
+
\u2705 ${contract.passes.length} test${contract.passes.length > 1 ? "s" : ""} passed
|
|
13169
13265
|
|
|
13170
|
-
\u{1F4CB} Review the detailed test report above for specific failures
|
|
13266
|
+
\u{1F4CB} Review the detailed test report above for specific failures.
|
|
13267
|
+
\u{1F4A1} Contract tests validate ARIA attributes and keyboard interactions per W3C APG guidelines.`
|
|
13171
13268
|
);
|
|
13172
13269
|
}
|
|
13173
13270
|
if (results.violations.length > 0) {
|
|
@@ -5,10 +5,11 @@ interface JestAxeResult {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
* Runs static and interactions accessibility test on UI components.
|
|
9
|
+
* @param {string} componentName The name of the component contract to test against
|
|
10
|
+
* @param {HTMLElement} component The UI component to be tested
|
|
11
|
+
* @param {string} url Optional URL to run full Playwright E2E tests (requires dev server running)
|
|
12
|
+
*/
|
|
12
13
|
|
|
13
14
|
declare function testUiComponent(componentName: string, component: HTMLElement, url?: string): Promise<JestAxeResult>;
|
|
14
15
|
declare let runTest: () => Promise<void>;
|
|
@@ -5,10 +5,11 @@ interface JestAxeResult {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
* Runs static and interactions accessibility test on UI components.
|
|
9
|
+
* @param {string} componentName The name of the component contract to test against
|
|
10
|
+
* @param {HTMLElement} component The UI component to be tested
|
|
11
|
+
* @param {string} url Optional URL to run full Playwright E2E tests (requires dev server running)
|
|
12
|
+
*/
|
|
12
13
|
|
|
13
14
|
declare function testUiComponent(componentName: string, component: HTMLElement, url?: string): Promise<JestAxeResult>;
|
|
14
15
|
declare let runTest: () => Promise<void>;
|