@supernal/interface 1.0.9 → 1.0.11
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/cjs/src/browser.js +42 -1
- package/dist/cjs/src/browser.js.map +1 -1
- package/dist/cjs/src/decorators/ContainerHelpers.js +16 -1
- package/dist/cjs/src/decorators/ContainerHelpers.js.map +1 -1
- package/dist/cjs/src/decorators/Tool.js +2 -3
- package/dist/cjs/src/decorators/Tool.js.map +1 -1
- package/dist/cjs/src/testing/graph-tester/core/GraphTester.js +339 -0
- package/dist/cjs/src/testing/graph-tester/core/GraphTester.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/core/TestFunction.js +189 -0
- package/dist/cjs/src/testing/graph-tester/core/TestFunction.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/core/types.js +24 -0
- package/dist/cjs/src/testing/graph-tester/core/types.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/fixtures/index.js +13 -0
- package/dist/cjs/src/testing/graph-tester/fixtures/index.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/fixtures/portPool.js +184 -0
- package/dist/cjs/src/testing/graph-tester/fixtures/portPool.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/index.js +98 -0
- package/dist/cjs/src/testing/graph-tester/index.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/modes/AccessibilityMode.js +230 -0
- package/dist/cjs/src/testing/graph-tester/modes/AccessibilityMode.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/modes/PerformanceMode.js +168 -0
- package/dist/cjs/src/testing/graph-tester/modes/PerformanceMode.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/modes/SEOMode.js +264 -0
- package/dist/cjs/src/testing/graph-tester/modes/SEOMode.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/modes/VisualRegressionMode.js +199 -0
- package/dist/cjs/src/testing/graph-tester/modes/VisualRegressionMode.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/modes/index.js +17 -0
- package/dist/cjs/src/testing/graph-tester/modes/index.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/reporters/HTMLReporter.js +411 -0
- package/dist/cjs/src/testing/graph-tester/reporters/HTMLReporter.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/reporters/JSONReporter.js +127 -0
- package/dist/cjs/src/testing/graph-tester/reporters/JSONReporter.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/reporters/MarkdownReporter.js +169 -0
- package/dist/cjs/src/testing/graph-tester/reporters/MarkdownReporter.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/reporters/UnifiedReporter.js +118 -0
- package/dist/cjs/src/testing/graph-tester/reporters/UnifiedReporter.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/reporters/index.js +17 -0
- package/dist/cjs/src/testing/graph-tester/reporters/index.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js +47 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js +584 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js +376 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/index.js +15 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/index.js.map +1 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/types.js +11 -0
- package/dist/cjs/src/testing/graph-tester/screenshot/types.js.map +1 -0
- package/dist/cjs/src/testing/selectors.js +1 -1
- package/dist/esm/src/browser.d.ts +9 -0
- package/dist/esm/src/browser.d.ts.map +1 -1
- package/dist/esm/src/browser.js +14 -0
- package/dist/esm/src/browser.js.map +1 -1
- package/dist/esm/src/decorators/ContainerHelpers.d.ts +2 -1
- package/dist/esm/src/decorators/ContainerHelpers.d.ts.map +1 -1
- package/dist/esm/src/decorators/ContainerHelpers.js +16 -1
- package/dist/esm/src/decorators/ContainerHelpers.js.map +1 -1
- package/dist/esm/src/decorators/Tool.d.ts.map +1 -1
- package/dist/esm/src/decorators/Tool.js +2 -3
- package/dist/esm/src/decorators/Tool.js.map +1 -1
- package/dist/esm/src/testing/graph-tester/core/GraphTester.d.ts +110 -0
- package/dist/esm/src/testing/graph-tester/core/GraphTester.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/core/GraphTester.js +335 -0
- package/dist/esm/src/testing/graph-tester/core/GraphTester.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/core/TestFunction.d.ts +120 -0
- package/dist/esm/src/testing/graph-tester/core/TestFunction.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/core/TestFunction.js +184 -0
- package/dist/esm/src/testing/graph-tester/core/TestFunction.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/core/types.d.ts +331 -0
- package/dist/esm/src/testing/graph-tester/core/types.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/core/types.js +21 -0
- package/dist/esm/src/testing/graph-tester/core/types.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/fixtures/index.d.ts +8 -0
- package/dist/esm/src/testing/graph-tester/fixtures/index.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/fixtures/index.js +7 -0
- package/dist/esm/src/testing/graph-tester/fixtures/index.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/fixtures/portPool.d.ts +40 -0
- package/dist/esm/src/testing/graph-tester/fixtures/portPool.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/fixtures/portPool.js +147 -0
- package/dist/esm/src/testing/graph-tester/fixtures/portPool.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/index.d.ts +84 -0
- package/dist/esm/src/testing/graph-tester/index.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/index.js +77 -0
- package/dist/esm/src/testing/graph-tester/index.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.d.ts +40 -0
- package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.js +193 -0
- package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.d.ts +42 -0
- package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.js +131 -0
- package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/SEOMode.d.ts +39 -0
- package/dist/esm/src/testing/graph-tester/modes/SEOMode.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/SEOMode.js +227 -0
- package/dist/esm/src/testing/graph-tester/modes/SEOMode.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.d.ts +83 -0
- package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.js +162 -0
- package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/index.d.ts +14 -0
- package/dist/esm/src/testing/graph-tester/modes/index.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/modes/index.js +10 -0
- package/dist/esm/src/testing/graph-tester/modes/index.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.d.ts +38 -0
- package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.js +374 -0
- package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.d.ts +50 -0
- package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.js +90 -0
- package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.d.ts +33 -0
- package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.js +132 -0
- package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.d.ts +30 -0
- package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.js +81 -0
- package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/index.d.ts +14 -0
- package/dist/esm/src/testing/graph-tester/reporters/index.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/reporters/index.js +10 -0
- package/dist/esm/src/testing/graph-tester/reporters/index.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.d.ts +33 -0
- package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js +43 -0
- package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.d.ts +70 -0
- package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js +547 -0
- package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.d.ts +83 -0
- package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js +339 -0
- package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/index.d.ts +11 -0
- package/dist/esm/src/testing/graph-tester/screenshot/index.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/index.js +9 -0
- package/dist/esm/src/testing/graph-tester/screenshot/index.js.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/types.d.ts +331 -0
- package/dist/esm/src/testing/graph-tester/screenshot/types.d.ts.map +1 -0
- package/dist/esm/src/testing/graph-tester/screenshot/types.js +10 -0
- package/dist/esm/src/testing/graph-tester/screenshot/types.js.map +1 -0
- package/dist/esm/src/testing/selectors.d.ts +1 -1
- package/dist/esm/src/testing/selectors.js +1 -1
- package/package.json +19 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/fixtures/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/fixtures/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port pool fixture for parallel testing.
|
|
3
|
+
*
|
|
4
|
+
* Automatically assigns unique ports to each test worker to avoid conflicts.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Port pool fixture interface.
|
|
10
|
+
*/
|
|
11
|
+
export interface PortPoolFixture {
|
|
12
|
+
/** Assigned port for this test */
|
|
13
|
+
port: number;
|
|
14
|
+
/** Base URL with assigned port */
|
|
15
|
+
baseURL: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Playwright test fixture with automatic port assignment.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { test, expect } from '@supernal/interface/testing/graph-tester/fixtures';
|
|
23
|
+
*
|
|
24
|
+
* test('visual regression', async ({ page, port, baseURL }) => {
|
|
25
|
+
* console.log(`Test running on port ${port}`);
|
|
26
|
+
* await page.goto(baseURL);
|
|
27
|
+
* // Test automatically gets unique port!
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & PortPoolFixture, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
|
|
32
|
+
/**
|
|
33
|
+
* Re-export expect from Playwright.
|
|
34
|
+
*/
|
|
35
|
+
export declare const expect: import("@playwright/test").Expect<{}>;
|
|
36
|
+
/**
|
|
37
|
+
* Cleanup port pool (call at end of test suite).
|
|
38
|
+
*/
|
|
39
|
+
export declare function cleanupPortPool(): Promise<void>;
|
|
40
|
+
//# sourceMappingURL=portPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portPool.d.ts","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/fixtures/portPool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IAEb,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AA2GD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,IAAI,+PAUf,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,MAAM,uCAAa,CAAC;AAEjC;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port pool fixture for parallel testing.
|
|
3
|
+
*
|
|
4
|
+
* Automatically assigns unique ports to each test worker to avoid conflicts.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import { test as base, expect as baseExpect } from '@playwright/test';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import * as os from 'os';
|
|
12
|
+
/**
|
|
13
|
+
* Port pool manager (singleton across workers).
|
|
14
|
+
*/
|
|
15
|
+
class PortPoolManager {
|
|
16
|
+
constructor(startPort = 3020, poolSize = 10) {
|
|
17
|
+
this.availablePorts = [];
|
|
18
|
+
this.usedPorts = new Set();
|
|
19
|
+
this.lockFile = path.join(os.tmpdir(), 'supernal-port-pool.lock');
|
|
20
|
+
this.lockFd = null;
|
|
21
|
+
// Initialize pool: 3020-3029 by default
|
|
22
|
+
for (let i = 0; i < poolSize; i++) {
|
|
23
|
+
this.availablePorts.push(startPort + i);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Acquire a port from the pool (with cross-worker coordination).
|
|
28
|
+
*/
|
|
29
|
+
async acquirePort() {
|
|
30
|
+
await this.acquireLock();
|
|
31
|
+
try {
|
|
32
|
+
if (this.availablePorts.length === 0) {
|
|
33
|
+
throw new Error('No available ports in pool. Increase pool size or reduce parallel workers.');
|
|
34
|
+
}
|
|
35
|
+
const port = this.availablePorts.shift();
|
|
36
|
+
this.usedPorts.add(port);
|
|
37
|
+
return port;
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await this.releaseLock();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Release a port back to the pool.
|
|
45
|
+
*/
|
|
46
|
+
async releasePort(port) {
|
|
47
|
+
await this.acquireLock();
|
|
48
|
+
try {
|
|
49
|
+
if (this.usedPorts.has(port)) {
|
|
50
|
+
this.usedPorts.delete(port);
|
|
51
|
+
this.availablePorts.push(port);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
await this.releaseLock();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Acquire file-based lock for cross-worker coordination.
|
|
60
|
+
*/
|
|
61
|
+
async acquireLock() {
|
|
62
|
+
const maxRetries = 100;
|
|
63
|
+
const retryDelay = 50; // ms
|
|
64
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
65
|
+
try {
|
|
66
|
+
// Try to create lock file with exclusive flag
|
|
67
|
+
this.lockFd = fs.openSync(this.lockFile, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_RDWR);
|
|
68
|
+
return; // Lock acquired
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error.code === 'EEXIST') {
|
|
72
|
+
// Lock file exists, wait and retry
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
throw new Error('Failed to acquire port pool lock after retries');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Release file-based lock.
|
|
84
|
+
*/
|
|
85
|
+
async releaseLock() {
|
|
86
|
+
if (this.lockFd !== null) {
|
|
87
|
+
try {
|
|
88
|
+
fs.closeSync(this.lockFd);
|
|
89
|
+
fs.unlinkSync(this.lockFile);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
// Ignore errors (file might already be deleted)
|
|
93
|
+
}
|
|
94
|
+
this.lockFd = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Cleanup all resources.
|
|
99
|
+
*/
|
|
100
|
+
async cleanup() {
|
|
101
|
+
try {
|
|
102
|
+
if (fs.existsSync(this.lockFile)) {
|
|
103
|
+
fs.unlinkSync(this.lockFile);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Ignore
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Global port pool instance
|
|
112
|
+
const portPool = new PortPoolManager();
|
|
113
|
+
/**
|
|
114
|
+
* Playwright test fixture with automatic port assignment.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* import { test, expect } from '@supernal/interface/testing/graph-tester/fixtures';
|
|
119
|
+
*
|
|
120
|
+
* test('visual regression', async ({ page, port, baseURL }) => {
|
|
121
|
+
* console.log(`Test running on port ${port}`);
|
|
122
|
+
* await page.goto(baseURL);
|
|
123
|
+
* // Test automatically gets unique port!
|
|
124
|
+
* });
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export const test = base.extend({
|
|
128
|
+
port: async ({}, use) => {
|
|
129
|
+
const port = await portPool.acquirePort();
|
|
130
|
+
await use(port);
|
|
131
|
+
await portPool.releasePort(port);
|
|
132
|
+
},
|
|
133
|
+
baseURL: async ({ port }, use) => {
|
|
134
|
+
await use(`http://localhost:${port}`);
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
/**
|
|
138
|
+
* Re-export expect from Playwright.
|
|
139
|
+
*/
|
|
140
|
+
export const expect = baseExpect;
|
|
141
|
+
/**
|
|
142
|
+
* Cleanup port pool (call at end of test suite).
|
|
143
|
+
*/
|
|
144
|
+
export async function cleanupPortPool() {
|
|
145
|
+
await portPool.cleanup();
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=portPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portPool.js","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/fixtures/portPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph-Based Testing Framework
|
|
3
|
+
*
|
|
4
|
+
* A comprehensive testing framework that systematically applies different testing functions
|
|
5
|
+
* (visual regression, performance, accessibility, SEO) to all routes in your application.
|
|
6
|
+
*
|
|
7
|
+
* ## Features
|
|
8
|
+
*
|
|
9
|
+
* - **Screenshot Annotation**: Capture screenshots with element bounding boxes, testids, and interaction capabilities
|
|
10
|
+
* - **Multiple Test Modes**: Visual regression, performance, accessibility, SEO
|
|
11
|
+
* - **AI-Ready Output**: JSON + PNG format optimized for multimodal AI analysis
|
|
12
|
+
* - **Multi-Format Reporting**: HTML (interactive), JSON (CI/CD), Markdown (docs)
|
|
13
|
+
* - **Parallel Testing**: Port pool fixture for running tests in parallel
|
|
14
|
+
* - **Pluggable Architecture**: Create custom test modes by extending TestFunction
|
|
15
|
+
*
|
|
16
|
+
* ## Usage
|
|
17
|
+
*
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { GraphTester, VisualRegressionMode, JSONReporter } from '@supernal/interface/testing/graph-tester';
|
|
20
|
+
*
|
|
21
|
+
* const tester = new GraphTester({
|
|
22
|
+
* baseUrl: 'http://localhost:3000',
|
|
23
|
+
* routes: [
|
|
24
|
+
* { route: '/', metadata: { name: 'Home' } },
|
|
25
|
+
* { route: '/dashboard', metadata: { name: 'Dashboard' } }
|
|
26
|
+
* ],
|
|
27
|
+
* modes: ['visual'],
|
|
28
|
+
* output: {
|
|
29
|
+
* dir: './test-results',
|
|
30
|
+
* formats: ['json', 'html']
|
|
31
|
+
* }
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Register test modes
|
|
35
|
+
* tester.registerTestFunction(new VisualRegressionMode({
|
|
36
|
+
* outputDir: './screenshots',
|
|
37
|
+
* annotate: true,
|
|
38
|
+
* generateHTML: true
|
|
39
|
+
* }));
|
|
40
|
+
*
|
|
41
|
+
* // Run tests
|
|
42
|
+
* const results = await tester.runTests();
|
|
43
|
+
* console.log(`Pass rate: ${results.passRate}%`);
|
|
44
|
+
*
|
|
45
|
+
* // Generate reports
|
|
46
|
+
* const reporter = new JSONReporter({ outputDir: './test-results' });
|
|
47
|
+
* await reporter.generate(results);
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* ## Enterprise Features
|
|
51
|
+
*
|
|
52
|
+
* For automatic route discovery via NavigationGraph, CLI commands, and AI analysis,
|
|
53
|
+
* see `@supernalintelligence/interface-enterprise/testing/graph-tester`.
|
|
54
|
+
*
|
|
55
|
+
* @packageDocumentation
|
|
56
|
+
*/
|
|
57
|
+
export { TestFunction, isTestFunction } from './core/TestFunction';
|
|
58
|
+
export { GraphTester } from './core/GraphTester';
|
|
59
|
+
export type * from './core/types';
|
|
60
|
+
export { ViewportPresets } from './core/types';
|
|
61
|
+
export { ScreenshotAnnotator } from './screenshot/ScreenshotAnnotator';
|
|
62
|
+
export type { ScreenshotAnnotatorConfig } from './screenshot/ScreenshotAnnotator';
|
|
63
|
+
export { HTMLAnnotationRenderer } from './screenshot/HTMLAnnotationRenderer';
|
|
64
|
+
export { CanvasAnnotationRenderer } from './screenshot/CanvasAnnotationRenderer';
|
|
65
|
+
export type * from './screenshot/types';
|
|
66
|
+
export { VisualRegressionMode } from './modes/VisualRegressionMode';
|
|
67
|
+
export type { VisualRegressionConfig } from './modes/VisualRegressionMode';
|
|
68
|
+
export { PerformanceMode } from './modes/PerformanceMode';
|
|
69
|
+
export type { PerformanceConfig } from './modes/PerformanceMode';
|
|
70
|
+
export { AccessibilityMode } from './modes/AccessibilityMode';
|
|
71
|
+
export type { AccessibilityConfig } from './modes/AccessibilityMode';
|
|
72
|
+
export { SEOMode } from './modes/SEOMode';
|
|
73
|
+
export type { SEOConfig } from './modes/SEOMode';
|
|
74
|
+
export { UnifiedReporter } from './reporters/UnifiedReporter';
|
|
75
|
+
export type { UnifiedReporterConfig } from './reporters/UnifiedReporter';
|
|
76
|
+
export { JSONReporter } from './reporters/JSONReporter';
|
|
77
|
+
export type { JSONReporterConfig } from './reporters/JSONReporter';
|
|
78
|
+
export { HTMLReporter } from './reporters/HTMLReporter';
|
|
79
|
+
export type { HTMLReporterConfig } from './reporters/HTMLReporter';
|
|
80
|
+
export { MarkdownReporter } from './reporters/MarkdownReporter';
|
|
81
|
+
export type { MarkdownReporterConfig } from './reporters/MarkdownReporter';
|
|
82
|
+
export { test as testWithPortPool, expect, cleanupPortPool } from './fixtures/portPool';
|
|
83
|
+
export type { PortPoolFixture } from './fixtures/portPool';
|
|
84
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/testing/graph-tester/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAIH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,mBAAmB,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAI/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAElF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAEjF,mBAAmB,oBAAoB,CAAC;AAIxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,YAAY,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,YAAY,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAI3E,OAAO,EAAE,IAAI,IAAI,gBAAgB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACxF,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph-Based Testing Framework
|
|
3
|
+
*
|
|
4
|
+
* A comprehensive testing framework that systematically applies different testing functions
|
|
5
|
+
* (visual regression, performance, accessibility, SEO) to all routes in your application.
|
|
6
|
+
*
|
|
7
|
+
* ## Features
|
|
8
|
+
*
|
|
9
|
+
* - **Screenshot Annotation**: Capture screenshots with element bounding boxes, testids, and interaction capabilities
|
|
10
|
+
* - **Multiple Test Modes**: Visual regression, performance, accessibility, SEO
|
|
11
|
+
* - **AI-Ready Output**: JSON + PNG format optimized for multimodal AI analysis
|
|
12
|
+
* - **Multi-Format Reporting**: HTML (interactive), JSON (CI/CD), Markdown (docs)
|
|
13
|
+
* - **Parallel Testing**: Port pool fixture for running tests in parallel
|
|
14
|
+
* - **Pluggable Architecture**: Create custom test modes by extending TestFunction
|
|
15
|
+
*
|
|
16
|
+
* ## Usage
|
|
17
|
+
*
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { GraphTester, VisualRegressionMode, JSONReporter } from '@supernal/interface/testing/graph-tester';
|
|
20
|
+
*
|
|
21
|
+
* const tester = new GraphTester({
|
|
22
|
+
* baseUrl: 'http://localhost:3000',
|
|
23
|
+
* routes: [
|
|
24
|
+
* { route: '/', metadata: { name: 'Home' } },
|
|
25
|
+
* { route: '/dashboard', metadata: { name: 'Dashboard' } }
|
|
26
|
+
* ],
|
|
27
|
+
* modes: ['visual'],
|
|
28
|
+
* output: {
|
|
29
|
+
* dir: './test-results',
|
|
30
|
+
* formats: ['json', 'html']
|
|
31
|
+
* }
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Register test modes
|
|
35
|
+
* tester.registerTestFunction(new VisualRegressionMode({
|
|
36
|
+
* outputDir: './screenshots',
|
|
37
|
+
* annotate: true,
|
|
38
|
+
* generateHTML: true
|
|
39
|
+
* }));
|
|
40
|
+
*
|
|
41
|
+
* // Run tests
|
|
42
|
+
* const results = await tester.runTests();
|
|
43
|
+
* console.log(`Pass rate: ${results.passRate}%`);
|
|
44
|
+
*
|
|
45
|
+
* // Generate reports
|
|
46
|
+
* const reporter = new JSONReporter({ outputDir: './test-results' });
|
|
47
|
+
* await reporter.generate(results);
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* ## Enterprise Features
|
|
51
|
+
*
|
|
52
|
+
* For automatic route discovery via NavigationGraph, CLI commands, and AI analysis,
|
|
53
|
+
* see `@supernalintelligence/interface-enterprise/testing/graph-tester`.
|
|
54
|
+
*
|
|
55
|
+
* @packageDocumentation
|
|
56
|
+
*/
|
|
57
|
+
// ==================== Core ====================
|
|
58
|
+
export { TestFunction, isTestFunction } from './core/TestFunction.js';
|
|
59
|
+
export { GraphTester } from './core/GraphTester.js';
|
|
60
|
+
export { ViewportPresets } from './core/types.js';
|
|
61
|
+
// ==================== Screenshot Annotation ====================
|
|
62
|
+
export { ScreenshotAnnotator } from './screenshot/ScreenshotAnnotator.js';
|
|
63
|
+
export { HTMLAnnotationRenderer } from './screenshot/HTMLAnnotationRenderer.js';
|
|
64
|
+
export { CanvasAnnotationRenderer } from './screenshot/CanvasAnnotationRenderer.js';
|
|
65
|
+
// ==================== Test Modes ====================
|
|
66
|
+
export { VisualRegressionMode } from './modes/VisualRegressionMode.js';
|
|
67
|
+
export { PerformanceMode } from './modes/PerformanceMode.js';
|
|
68
|
+
export { AccessibilityMode } from './modes/AccessibilityMode.js';
|
|
69
|
+
export { SEOMode } from './modes/SEOMode.js';
|
|
70
|
+
// ==================== Reporters ====================
|
|
71
|
+
export { UnifiedReporter } from './reporters/UnifiedReporter.js';
|
|
72
|
+
export { JSONReporter } from './reporters/JSONReporter.js';
|
|
73
|
+
export { HTMLReporter } from './reporters/HTMLReporter.js';
|
|
74
|
+
export { MarkdownReporter } from './reporters/MarkdownReporter.js';
|
|
75
|
+
// ==================== Fixtures ====================
|
|
76
|
+
export { test as testWithPortPool, expect, cleanupPortPool } from './fixtures/portPool.js';
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/testing/graph-tester/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,iDAAiD;AAEjD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,kEAAkE;AAElE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAIjF,uDAAuD;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG1C,sDAAsD;AAEtD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhE,qDAAqD;AAErD,OAAO,EAAE,IAAI,IAAI,gBAAgB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accessibility testing mode (stub - to be implemented in Phase 2).
|
|
3
|
+
*
|
|
4
|
+
* Will integrate axe-core for WCAG compliance testing.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import type { Page } from '@playwright/test';
|
|
9
|
+
import { TestFunction } from '../core/TestFunction';
|
|
10
|
+
import type { TestContext, TestResult } from '../core/types';
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for accessibility mode.
|
|
13
|
+
*/
|
|
14
|
+
export interface AccessibilityConfig {
|
|
15
|
+
/** Output directory */
|
|
16
|
+
outputDir: string;
|
|
17
|
+
/** WCAG version (default: '2.1') */
|
|
18
|
+
wcagVersion?: '2.0' | '2.1' | '2.2';
|
|
19
|
+
/** WCAG level (default: 'AA') */
|
|
20
|
+
wcagLevel?: 'A' | 'AA' | 'AAA';
|
|
21
|
+
/** Whether to fail on warnings (default: false) */
|
|
22
|
+
strict?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Accessibility testing mode (stub).
|
|
26
|
+
*/
|
|
27
|
+
export declare class AccessibilityMode extends TestFunction {
|
|
28
|
+
readonly mode = "accessibility";
|
|
29
|
+
readonly name = "Accessibility";
|
|
30
|
+
readonly description = "Tests WCAG compliance using axe-core";
|
|
31
|
+
private config;
|
|
32
|
+
constructor(config: AccessibilityConfig);
|
|
33
|
+
execute(page: Page, context: TestContext): Promise<TestResult>;
|
|
34
|
+
private injectAxe;
|
|
35
|
+
private getWCAGTags;
|
|
36
|
+
private sanitizeRoute;
|
|
37
|
+
private ensureDirectory;
|
|
38
|
+
private writeFile;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=AccessibilityMode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessibilityMode.d.ts","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/modes/AccessibilityMode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAElB,oCAAoC;IACpC,WAAW,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAEpC,iCAAiC;IACjC,SAAS,CAAC,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC;IAE/B,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,WAAW,0CAA0C;IAE9D,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAKjC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;YA8ItD,SAAS;IAWvB,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,aAAa;YAIP,eAAe;YAKf,SAAS;CAIxB"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accessibility testing mode (stub - to be implemented in Phase 2).
|
|
3
|
+
*
|
|
4
|
+
* Will integrate axe-core for WCAG compliance testing.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import { TestFunction } from '../core/TestFunction.js';
|
|
9
|
+
/**
|
|
10
|
+
* Accessibility testing mode (stub).
|
|
11
|
+
*/
|
|
12
|
+
export class AccessibilityMode extends TestFunction {
|
|
13
|
+
constructor(config) {
|
|
14
|
+
super();
|
|
15
|
+
this.mode = 'accessibility';
|
|
16
|
+
this.name = 'Accessibility';
|
|
17
|
+
this.description = 'Tests WCAG compliance using axe-core';
|
|
18
|
+
this.config = config;
|
|
19
|
+
}
|
|
20
|
+
async execute(page, context) {
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
const errors = [];
|
|
23
|
+
try {
|
|
24
|
+
// Inject axe-core
|
|
25
|
+
await this.injectAxe(page);
|
|
26
|
+
// Run axe analysis with WCAG tags
|
|
27
|
+
const wcagTags = this.getWCAGTags();
|
|
28
|
+
const results = await page.evaluate((tags) => {
|
|
29
|
+
return new Promise((resolve) => {
|
|
30
|
+
// @ts-ignore - axe is injected globally
|
|
31
|
+
if (typeof window.axe === 'undefined') {
|
|
32
|
+
resolve({ violations: [], passes: [], incomplete: [], inapplicable: [] });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
window.axe
|
|
37
|
+
.run({
|
|
38
|
+
runOnly: {
|
|
39
|
+
type: 'tag',
|
|
40
|
+
values: tags,
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
.then((results) => {
|
|
44
|
+
resolve(results);
|
|
45
|
+
})
|
|
46
|
+
.catch((error) => {
|
|
47
|
+
resolve({ violations: [], passes: [], incomplete: [], inapplicable: [], error: error.message });
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}, wcagTags);
|
|
51
|
+
// Process violations
|
|
52
|
+
const violations = results.violations || [];
|
|
53
|
+
const warnings = results.incomplete || [];
|
|
54
|
+
// Build detailed violation reports
|
|
55
|
+
const violationReports = violations.map((v) => ({
|
|
56
|
+
id: v.id,
|
|
57
|
+
impact: v.impact,
|
|
58
|
+
description: v.description,
|
|
59
|
+
help: v.help,
|
|
60
|
+
helpUrl: v.helpUrl,
|
|
61
|
+
nodes: v.nodes.map((node) => ({
|
|
62
|
+
html: node.html,
|
|
63
|
+
target: node.target,
|
|
64
|
+
failureSummary: node.failureSummary,
|
|
65
|
+
})),
|
|
66
|
+
}));
|
|
67
|
+
const warningReports = warnings.map((w) => ({
|
|
68
|
+
id: w.id,
|
|
69
|
+
impact: w.impact,
|
|
70
|
+
description: w.description,
|
|
71
|
+
help: w.help,
|
|
72
|
+
helpUrl: w.helpUrl,
|
|
73
|
+
nodes: w.nodes.length,
|
|
74
|
+
}));
|
|
75
|
+
// Determine if test passed
|
|
76
|
+
const hasViolations = violations.length > 0;
|
|
77
|
+
const hasWarnings = warnings.length > 0;
|
|
78
|
+
const passed = this.config.strict ? !hasViolations && !hasWarnings : !hasViolations;
|
|
79
|
+
// Collect error messages
|
|
80
|
+
if (hasViolations) {
|
|
81
|
+
violations.forEach((v) => {
|
|
82
|
+
errors.push({
|
|
83
|
+
severity: v.impact === 'critical' ? 'critical' : 'warning',
|
|
84
|
+
message: `[${v.impact}] ${v.help} (${v.nodes.length} instances)`,
|
|
85
|
+
location: v.helpUrl,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (this.config.strict && hasWarnings) {
|
|
90
|
+
warnings.forEach((w) => {
|
|
91
|
+
errors.push({
|
|
92
|
+
severity: 'info',
|
|
93
|
+
message: `[warning] ${w.help} (${w.nodes.length} instances)`,
|
|
94
|
+
location: w.helpUrl,
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// Save results
|
|
99
|
+
const outputPath = `${this.config.outputDir}/${this.sanitizeRoute(context.route)}-accessibility.json`;
|
|
100
|
+
await this.ensureDirectory(this.config.outputDir);
|
|
101
|
+
await this.writeFile(outputPath, JSON.stringify({
|
|
102
|
+
route: context.route,
|
|
103
|
+
wcagVersion: this.config.wcagVersion || '2.1',
|
|
104
|
+
wcagLevel: this.config.wcagLevel || 'AA',
|
|
105
|
+
summary: {
|
|
106
|
+
violations: violations.length,
|
|
107
|
+
warnings: warnings.length,
|
|
108
|
+
passes: results.passes?.length || 0,
|
|
109
|
+
incomplete: results.incomplete?.length || 0,
|
|
110
|
+
},
|
|
111
|
+
violations: violationReports,
|
|
112
|
+
warnings: warningReports,
|
|
113
|
+
}, null, 2));
|
|
114
|
+
const duration = Date.now() - startTime;
|
|
115
|
+
return {
|
|
116
|
+
passed,
|
|
117
|
+
duration,
|
|
118
|
+
errors,
|
|
119
|
+
metadata: {
|
|
120
|
+
accessibility: {
|
|
121
|
+
violationCount: violations.length,
|
|
122
|
+
warningCount: warnings.length,
|
|
123
|
+
passCount: results.passes?.length || 0,
|
|
124
|
+
},
|
|
125
|
+
outputPath,
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
errors.push({
|
|
131
|
+
severity: 'critical',
|
|
132
|
+
message: `Accessibility testing failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
133
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
passed: false,
|
|
137
|
+
duration: Date.now() - startTime,
|
|
138
|
+
errors,
|
|
139
|
+
metadata: {},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async injectAxe(page) {
|
|
144
|
+
try {
|
|
145
|
+
// Try to load axe-core from CDN
|
|
146
|
+
await page.addScriptTag({
|
|
147
|
+
url: 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.3/axe.min.js',
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
throw new Error('Failed to inject axe-core from CDN. Please check your network connection or use a local axe-core installation.');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
getWCAGTags() {
|
|
155
|
+
const version = this.config.wcagVersion || '2.1';
|
|
156
|
+
const level = this.config.wcagLevel || 'AA';
|
|
157
|
+
const tags = ['wcag2a'];
|
|
158
|
+
if (level === 'AA' || level === 'AAA') {
|
|
159
|
+
tags.push('wcag2aa');
|
|
160
|
+
}
|
|
161
|
+
if (level === 'AAA') {
|
|
162
|
+
tags.push('wcag2aaa');
|
|
163
|
+
}
|
|
164
|
+
// Add version-specific tags
|
|
165
|
+
if (version === '2.1') {
|
|
166
|
+
tags.push('wcag21a');
|
|
167
|
+
if (level === 'AA' || level === 'AAA')
|
|
168
|
+
tags.push('wcag21aa');
|
|
169
|
+
if (level === 'AAA')
|
|
170
|
+
tags.push('wcag21aaa');
|
|
171
|
+
}
|
|
172
|
+
if (version === '2.2') {
|
|
173
|
+
tags.push('wcag21a', 'wcag22a');
|
|
174
|
+
if (level === 'AA' || level === 'AAA')
|
|
175
|
+
tags.push('wcag21aa', 'wcag22aa');
|
|
176
|
+
if (level === 'AAA')
|
|
177
|
+
tags.push('wcag21aaa', 'wcag22aaa');
|
|
178
|
+
}
|
|
179
|
+
return tags;
|
|
180
|
+
}
|
|
181
|
+
sanitizeRoute(route) {
|
|
182
|
+
return route.replace(/^\//, '').replace(/\//g, '-') || 'home';
|
|
183
|
+
}
|
|
184
|
+
async ensureDirectory(dir) {
|
|
185
|
+
const fs = await import('fs/promises');
|
|
186
|
+
await fs.mkdir(dir, { recursive: true });
|
|
187
|
+
}
|
|
188
|
+
async writeFile(path, content) {
|
|
189
|
+
const fs = await import('fs/promises');
|
|
190
|
+
await fs.writeFile(path, content, 'utf-8');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=AccessibilityMode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessibilityMode.js","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/modes/AccessibilityMode.ts"],"names":[],"mappings":"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"}
|