playwright-e2e-mcp 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -19
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/http.js +1 -1
- package/dist/http.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +16 -3
- package/dist/server.js.map +1 -1
- package/dist/tools/analyze-history.d.ts +3 -3
- package/dist/tools/audit-accessibility.d.ts +184 -0
- package/dist/tools/audit-accessibility.js +162 -0
- package/dist/tools/audit-accessibility.js.map +1 -0
- package/dist/tools/compare-visual-state.d.ts +39 -39
- package/dist/tools/diagnose-flaky.d.ts +38 -0
- package/dist/tools/diagnose-flaky.js +196 -1
- package/dist/tools/diagnose-flaky.js.map +1 -1
- package/dist/tools/inspect-page.d.ts +38 -38
- package/dist/tools/probe-script.d.ts +2 -0
- package/dist/tools/probe-script.js +50 -0
- package/dist/tools/probe-script.js.map +1 -1
- package/dist/tools/run-test.d.ts +14 -1
- package/dist/tools/run-test.js +51 -4
- package/dist/tools/run-test.js.map +1 -1
- package/dist/tools/shared.d.ts +38 -11
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/suggest-fix.d.ts +13 -13
- package/dist/tools/validate-selector.d.ts +21 -21
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/change-analyzer.js.map +1 -1
- package/dist/utils/image-diff.js.map +1 -1
- package/dist/utils/locator-expr.d.ts +1 -1
- package/dist/utils/locator-expr.js.map +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/playwright-runner.js +6 -0
- package/dist/utils/playwright-runner.js.map +1 -1
- package/dist/utils/project-detector.js.map +1 -1
- package/dist/utils/trace-reader.js +6 -1
- package/dist/utils/trace-reader.js.map +1 -1
- package/package.json +13 -6
- package/skill/playwright-e2e-mcp/SKILL.md +41 -7
- package/skill/playwright-e2e-mcp/references/setup.md +5 -3
- package/skill/playwright-e2e-mcp/references/tools.md +26 -1
- package/skill/playwright-e2e-mcp/references/writing-tests.md +170 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 12 — audit-accessibility: run axe-core (the engine behind Lighthouse
|
|
3
|
+
* and @axe-core/playwright) on a live page and return the WCAG violations,
|
|
4
|
+
* worst first, each with the offending elements as verified Playwright
|
|
5
|
+
* locators and a ready-made regression test.
|
|
6
|
+
*
|
|
7
|
+
* It takes the same page state as inspect-page (storageState, headers,
|
|
8
|
+
* actions), so pages behind a login, open modals and later steps of a flow
|
|
9
|
+
* can be audited, which is where most real accessibility bugs sit.
|
|
10
|
+
*/
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import type { ToolContext, ToolResponse } from '../types/index.js';
|
|
13
|
+
import { type BrowserScriptData } from './shared.js';
|
|
14
|
+
/** WCAG 2.2 level A and AA, the usual legal and contractual bar. */
|
|
15
|
+
export declare const DEFAULT_AXE_TAGS: readonly ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'];
|
|
16
|
+
declare const IMPACT_ORDER: readonly ['critical', 'serious', 'moderate', 'minor'];
|
|
17
|
+
declare const auditAccessibilityInput: z.ZodObject<{
|
|
18
|
+
storageState: z.ZodOptional<z.ZodString>;
|
|
19
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
20
|
+
actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
21
|
+
type: z.ZodEnum<{
|
|
22
|
+
check: "check";
|
|
23
|
+
click: "click";
|
|
24
|
+
dblclick: "dblclick";
|
|
25
|
+
fill: "fill";
|
|
26
|
+
goto: "goto";
|
|
27
|
+
hover: "hover";
|
|
28
|
+
press: "press";
|
|
29
|
+
select: "select";
|
|
30
|
+
uncheck: "uncheck";
|
|
31
|
+
wait: "wait";
|
|
32
|
+
}>;
|
|
33
|
+
locator: z.ZodOptional<z.ZodString>;
|
|
34
|
+
value: z.ZodOptional<z.ZodString>;
|
|
35
|
+
url: z.ZodOptional<z.ZodString>;
|
|
36
|
+
ms: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
}, z.core.$strip>>>;
|
|
38
|
+
viewport: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
width: z.ZodNumber;
|
|
40
|
+
height: z.ZodNumber;
|
|
41
|
+
}, z.core.$strip>>;
|
|
42
|
+
url: z.ZodString;
|
|
43
|
+
projectRoot: z.ZodOptional<z.ZodString>;
|
|
44
|
+
selector: z.ZodOptional<z.ZodString>;
|
|
45
|
+
standard: z.ZodOptional<z.ZodEnum<{
|
|
46
|
+
all: "all";
|
|
47
|
+
"best-practice": "best-practice";
|
|
48
|
+
wcag21aa: "wcag21aa";
|
|
49
|
+
wcag22aa: "wcag22aa";
|
|
50
|
+
wcag2a: "wcag2a";
|
|
51
|
+
wcag2aa: "wcag2aa";
|
|
52
|
+
}>>;
|
|
53
|
+
minImpact: z.ZodOptional<z.ZodEnum<{
|
|
54
|
+
critical: "critical";
|
|
55
|
+
minor: "minor";
|
|
56
|
+
moderate: "moderate";
|
|
57
|
+
serious: "serious";
|
|
58
|
+
}>>;
|
|
59
|
+
waitFor: z.ZodOptional<z.ZodString>;
|
|
60
|
+
waitUntil: z.ZodOptional<z.ZodEnum<{
|
|
61
|
+
domcontentloaded: "domcontentloaded";
|
|
62
|
+
load: "load";
|
|
63
|
+
networkidle: "networkidle";
|
|
64
|
+
}>>;
|
|
65
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
export type AuditAccessibilityInput = z.infer<typeof auditAccessibilityInput>;
|
|
68
|
+
export declare const auditAccessibilitySchema: z.ZodObject<{
|
|
69
|
+
storageState: z.ZodOptional<z.ZodString>;
|
|
70
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
71
|
+
actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
72
|
+
type: z.ZodEnum<{
|
|
73
|
+
check: "check";
|
|
74
|
+
click: "click";
|
|
75
|
+
dblclick: "dblclick";
|
|
76
|
+
fill: "fill";
|
|
77
|
+
goto: "goto";
|
|
78
|
+
hover: "hover";
|
|
79
|
+
press: "press";
|
|
80
|
+
select: "select";
|
|
81
|
+
uncheck: "uncheck";
|
|
82
|
+
wait: "wait";
|
|
83
|
+
}>;
|
|
84
|
+
locator: z.ZodOptional<z.ZodString>;
|
|
85
|
+
value: z.ZodOptional<z.ZodString>;
|
|
86
|
+
url: z.ZodOptional<z.ZodString>;
|
|
87
|
+
ms: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
}, z.core.$strip>>>;
|
|
89
|
+
viewport: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
width: z.ZodNumber;
|
|
91
|
+
height: z.ZodNumber;
|
|
92
|
+
}, z.core.$strip>>;
|
|
93
|
+
url: z.ZodString;
|
|
94
|
+
projectRoot: z.ZodOptional<z.ZodString>;
|
|
95
|
+
selector: z.ZodOptional<z.ZodString>;
|
|
96
|
+
standard: z.ZodOptional<z.ZodEnum<{
|
|
97
|
+
all: "all";
|
|
98
|
+
"best-practice": "best-practice";
|
|
99
|
+
wcag21aa: "wcag21aa";
|
|
100
|
+
wcag22aa: "wcag22aa";
|
|
101
|
+
wcag2a: "wcag2a";
|
|
102
|
+
wcag2aa: "wcag2aa";
|
|
103
|
+
}>>;
|
|
104
|
+
minImpact: z.ZodOptional<z.ZodEnum<{
|
|
105
|
+
critical: "critical";
|
|
106
|
+
minor: "minor";
|
|
107
|
+
moderate: "moderate";
|
|
108
|
+
serious: "serious";
|
|
109
|
+
}>>;
|
|
110
|
+
waitFor: z.ZodOptional<z.ZodString>;
|
|
111
|
+
waitUntil: z.ZodOptional<z.ZodEnum<{
|
|
112
|
+
domcontentloaded: "domcontentloaded";
|
|
113
|
+
load: "load";
|
|
114
|
+
networkidle: "networkidle";
|
|
115
|
+
}>>;
|
|
116
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
117
|
+
}, z.core.$strip>;
|
|
118
|
+
/** axe tags for a standard; undefined runs every rule. */
|
|
119
|
+
export declare function axeTagsFor(standard: AuditAccessibilityInput['standard']): string[] | undefined;
|
|
120
|
+
/** axe tags like `wcag143` → "WCAG 1.4.3". */
|
|
121
|
+
export declare function wcagCriteria(tags: readonly string[]): string[];
|
|
122
|
+
export declare function axeSourcePath(): string;
|
|
123
|
+
export declare function renderAudit(url: string, data: BrowserScriptData, options: {
|
|
124
|
+
minImpact?: (typeof IMPACT_ORDER)[number];
|
|
125
|
+
tags?: string[];
|
|
126
|
+
stateLine?: string;
|
|
127
|
+
selector?: string;
|
|
128
|
+
}): string;
|
|
129
|
+
export declare const auditAccessibilityTool: {
|
|
130
|
+
name: string;
|
|
131
|
+
description: string;
|
|
132
|
+
inputSchema: z.ZodObject<{
|
|
133
|
+
storageState: z.ZodOptional<z.ZodString>;
|
|
134
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
135
|
+
actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
136
|
+
type: z.ZodEnum<{
|
|
137
|
+
check: "check";
|
|
138
|
+
click: "click";
|
|
139
|
+
dblclick: "dblclick";
|
|
140
|
+
fill: "fill";
|
|
141
|
+
goto: "goto";
|
|
142
|
+
hover: "hover";
|
|
143
|
+
press: "press";
|
|
144
|
+
select: "select";
|
|
145
|
+
uncheck: "uncheck";
|
|
146
|
+
wait: "wait";
|
|
147
|
+
}>;
|
|
148
|
+
locator: z.ZodOptional<z.ZodString>;
|
|
149
|
+
value: z.ZodOptional<z.ZodString>;
|
|
150
|
+
url: z.ZodOptional<z.ZodString>;
|
|
151
|
+
ms: z.ZodOptional<z.ZodNumber>;
|
|
152
|
+
}, z.core.$strip>>>;
|
|
153
|
+
viewport: z.ZodOptional<z.ZodObject<{
|
|
154
|
+
width: z.ZodNumber;
|
|
155
|
+
height: z.ZodNumber;
|
|
156
|
+
}, z.core.$strip>>;
|
|
157
|
+
url: z.ZodString;
|
|
158
|
+
projectRoot: z.ZodOptional<z.ZodString>;
|
|
159
|
+
selector: z.ZodOptional<z.ZodString>;
|
|
160
|
+
standard: z.ZodOptional<z.ZodEnum<{
|
|
161
|
+
all: "all";
|
|
162
|
+
"best-practice": "best-practice";
|
|
163
|
+
wcag21aa: "wcag21aa";
|
|
164
|
+
wcag22aa: "wcag22aa";
|
|
165
|
+
wcag2a: "wcag2a";
|
|
166
|
+
wcag2aa: "wcag2aa";
|
|
167
|
+
}>>;
|
|
168
|
+
minImpact: z.ZodOptional<z.ZodEnum<{
|
|
169
|
+
critical: "critical";
|
|
170
|
+
minor: "minor";
|
|
171
|
+
moderate: "moderate";
|
|
172
|
+
serious: "serious";
|
|
173
|
+
}>>;
|
|
174
|
+
waitFor: z.ZodOptional<z.ZodString>;
|
|
175
|
+
waitUntil: z.ZodOptional<z.ZodEnum<{
|
|
176
|
+
domcontentloaded: "domcontentloaded";
|
|
177
|
+
load: "load";
|
|
178
|
+
networkidle: "networkidle";
|
|
179
|
+
}>>;
|
|
180
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
181
|
+
}, z.core.$strip>;
|
|
182
|
+
handler: (args: AuditAccessibilityInput, ctx: ToolContext) => Promise<ToolResponse>;
|
|
183
|
+
};
|
|
184
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 12 — audit-accessibility: run axe-core (the engine behind Lighthouse
|
|
3
|
+
* and @axe-core/playwright) on a live page and return the WCAG violations,
|
|
4
|
+
* worst first, each with the offending elements as verified Playwright
|
|
5
|
+
* locators and a ready-made regression test.
|
|
6
|
+
*
|
|
7
|
+
* It takes the same page state as inspect-page (storageState, headers,
|
|
8
|
+
* actions), so pages behind a login, open modals and later steps of a flow
|
|
9
|
+
* can be audited, which is where most real accessibility bugs sit.
|
|
10
|
+
*/
|
|
11
|
+
import { createRequire } from 'node:module';
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { assertHttpUrl, bestLocator, clipLines, describePageState, guard, loginHint, pageStateShape, resolvePageState, resolveProjectRoot, runBrowserScript, toolError, toolText, } from './shared.js';
|
|
14
|
+
import { assertUrlAllowed } from '../utils/url-policy.js';
|
|
15
|
+
/** WCAG 2.2 level A and AA, the usual legal and contractual bar. */
|
|
16
|
+
export const DEFAULT_AXE_TAGS = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'];
|
|
17
|
+
const IMPACT_ORDER = ['critical', 'serious', 'moderate', 'minor'];
|
|
18
|
+
const auditAccessibilityInput = z.object({
|
|
19
|
+
url: z.string().describe('Full URL of the page to audit (http/https)'),
|
|
20
|
+
projectRoot: z.string().optional().describe('Project whose Playwright launches the browser (default: server root)'),
|
|
21
|
+
selector: z.string().optional().describe('CSS selector: audit only this part of the page'),
|
|
22
|
+
standard: z
|
|
23
|
+
.enum(['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa', 'best-practice', 'all'])
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Rule set: WCAG level (default wcag22aa, i.e. 2.0–2.2 A+AA), 'best-practice' adds axe's extra rules, 'all' runs everything"),
|
|
26
|
+
minImpact: z
|
|
27
|
+
.enum(IMPACT_ORDER)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe('Hide violations below this impact (default: minor, show all)'),
|
|
30
|
+
waitFor: z.string().optional().describe('Wait for this selector first'),
|
|
31
|
+
...pageStateShape,
|
|
32
|
+
waitUntil: z
|
|
33
|
+
.enum(['load', 'domcontentloaded', 'networkidle'])
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('Navigation wait condition (default load)'),
|
|
36
|
+
timeoutMs: z.number().int().min(1_000).max(300_000).optional().describe('Overall audit limit in ms (default 60000)'),
|
|
37
|
+
});
|
|
38
|
+
export const auditAccessibilitySchema = auditAccessibilityInput;
|
|
39
|
+
/** axe tags for a standard; undefined runs every rule. */
|
|
40
|
+
export function axeTagsFor(standard) {
|
|
41
|
+
switch (standard ?? 'wcag22aa') {
|
|
42
|
+
case 'wcag2a':
|
|
43
|
+
return ['wcag2a'];
|
|
44
|
+
case 'wcag2aa':
|
|
45
|
+
return ['wcag2a', 'wcag2aa'];
|
|
46
|
+
case 'wcag21aa':
|
|
47
|
+
return ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'];
|
|
48
|
+
case 'wcag22aa':
|
|
49
|
+
return [...DEFAULT_AXE_TAGS];
|
|
50
|
+
case 'best-practice':
|
|
51
|
+
return [...DEFAULT_AXE_TAGS, 'best-practice'];
|
|
52
|
+
default:
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** axe tags like `wcag143` → "WCAG 1.4.3". */
|
|
57
|
+
export function wcagCriteria(tags) {
|
|
58
|
+
const out = [];
|
|
59
|
+
for (const tag of tags) {
|
|
60
|
+
const m = /^wcag(\d)(\d)(\d{1,2})$/.exec(tag);
|
|
61
|
+
if (m)
|
|
62
|
+
out.push(`${m[1]}.${m[2]}.${m[3]}`);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
export function axeSourcePath() {
|
|
67
|
+
return createRequire(import.meta.url).resolve('axe-core/axe.min.js');
|
|
68
|
+
}
|
|
69
|
+
function impactRank(impact) {
|
|
70
|
+
const i = IMPACT_ORDER.indexOf(impact);
|
|
71
|
+
return i === -1 ? IMPACT_ORDER.length : i;
|
|
72
|
+
}
|
|
73
|
+
/** First line of axe's failure summary that says what to change. */
|
|
74
|
+
function fixLine(summary) {
|
|
75
|
+
const lines = summary.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
76
|
+
const body = lines.filter((l) => !/^Fix (any|all) of the following:?$/i.test(l));
|
|
77
|
+
return clipLines(body[0] ?? lines[0] ?? '', 1, 200);
|
|
78
|
+
}
|
|
79
|
+
export function renderAudit(url, data, options) {
|
|
80
|
+
const scan = data.a11y;
|
|
81
|
+
const floor = impactRank(options.minImpact ?? 'minor');
|
|
82
|
+
const all = [...scan.violations].sort((a, b) => impactRank(a.impact) - impactRank(b.impact) || b.nodeCount - a.nodeCount);
|
|
83
|
+
const shown = all.filter((v) => impactRank(v.impact) <= floor);
|
|
84
|
+
const hidden = all.length - shown.length;
|
|
85
|
+
const standard = options.tags ? options.tags.join(', ') : 'all axe rules';
|
|
86
|
+
const lines = [];
|
|
87
|
+
if (scan.scopeMissing) {
|
|
88
|
+
return [`## ❓ Nothing to audit`, '', `\`${options.selector}\` matched no element on ${url}. Run **inspect-page** to find the right container.`].join('\n');
|
|
89
|
+
}
|
|
90
|
+
const counts = IMPACT_ORDER.map((impact) => [impact, shown.filter((v) => v.impact === impact).length]).filter(([, n]) => n > 0);
|
|
91
|
+
if (shown.length === 0) {
|
|
92
|
+
lines.push(`## ✅ No accessibility violations`, '');
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
lines.push(`## ♿ ${shown.length} accessibility violation${shown.length === 1 ? '' : 's'} (${counts.map(([i, n]) => `${n} ${i}`).join(', ')})`, '');
|
|
96
|
+
}
|
|
97
|
+
lines.push(`**URL:** ${url}${options.selector ? ` | **Scope:** \`${options.selector}\`` : ''} | **Rules:** ${standard}`);
|
|
98
|
+
if (options.stateLine)
|
|
99
|
+
lines.push(`**Page state:** ${options.stateLine}`);
|
|
100
|
+
lines.push(`**Checked:** ${scan.passes} rules passed · ${scan.incomplete} need manual review${hidden ? ` · ${hidden} below ${options.minImpact} hidden` : ''}`, '');
|
|
101
|
+
shown.forEach((v, i) => {
|
|
102
|
+
const criteria = wcagCriteria(v.tags);
|
|
103
|
+
lines.push(`### ${i + 1}. ${v.impact} · \`${v.id}\`: ${v.help}${criteria.length ? ` (WCAG ${criteria.join(', ')})` : ''}`);
|
|
104
|
+
lines.push(`${v.nodeCount} element${v.nodeCount === 1 ? '' : 's'} · ${v.helpUrl}`);
|
|
105
|
+
for (const node of v.nodes) {
|
|
106
|
+
const element = node.element >= 0 ? data.elements[node.element] : undefined;
|
|
107
|
+
const locator = element ? bestLocator(element) : undefined;
|
|
108
|
+
lines.push(`- \`${locator ?? node.target}\`${locator ? '' : ' (CSS)'}: ${fixLine(node.summary)}`);
|
|
109
|
+
}
|
|
110
|
+
if (v.nodeCount > v.nodes.length)
|
|
111
|
+
lines.push(`- …and ${v.nodeCount - v.nodes.length} more`);
|
|
112
|
+
lines.push('');
|
|
113
|
+
});
|
|
114
|
+
if (shown.length > 0) {
|
|
115
|
+
const tagList = (options.tags ?? [...DEFAULT_AXE_TAGS]).map((t) => `'${t}'`).join(', ');
|
|
116
|
+
lines.push('**Keep it fixed:** add this check to the spec that reaches this page (`npm i -D @axe-core/playwright`):', '', '```ts', "import AxeBuilder from '@axe-core/playwright';", '', `const { violations } = await new AxeBuilder({ page })${options.selector ? `.include(${JSON.stringify(options.selector)})` : ''}.withTags([${tagList}]).analyze();`, 'expect(violations.map((v) => v.id)).toEqual([]);', '```');
|
|
117
|
+
}
|
|
118
|
+
return lines.join('\n').trimEnd();
|
|
119
|
+
}
|
|
120
|
+
export const auditAccessibilityTool = {
|
|
121
|
+
name: 'audit-accessibility',
|
|
122
|
+
description: "Run axe-core on a live page (WCAG 2.2 AA by default) and return violations worst first, each with the offending elements as verified Playwright locators, the fix, and a regression check to paste into a spec. Accepts storageState/headers/actions to audit pages behind a login or after a step.",
|
|
123
|
+
inputSchema: auditAccessibilitySchema,
|
|
124
|
+
handler: async (args, ctx) => guard('audit-accessibility', async () => {
|
|
125
|
+
const url = assertHttpUrl(args.url);
|
|
126
|
+
await assertUrlAllowed(url);
|
|
127
|
+
const root = await resolveProjectRoot(args.projectRoot, ctx);
|
|
128
|
+
const state = await resolvePageState(args, root, url, ctx);
|
|
129
|
+
const timeoutMs = args.timeoutMs ?? 60_000;
|
|
130
|
+
const tags = axeTagsFor(args.standard);
|
|
131
|
+
const outcome = await runBrowserScript({
|
|
132
|
+
...state,
|
|
133
|
+
mode: 'a11y',
|
|
134
|
+
projectRoot: root,
|
|
135
|
+
url,
|
|
136
|
+
selector: args.selector,
|
|
137
|
+
waitFor: args.waitFor,
|
|
138
|
+
waitUntil: args.waitUntil ?? 'load',
|
|
139
|
+
axeSourcePath: axeSourcePath(),
|
|
140
|
+
axeTags: tags,
|
|
141
|
+
maxNodes: 3,
|
|
142
|
+
gotoTimeout: Math.max(5_000, timeoutMs - 10_000),
|
|
143
|
+
waitTimeout: Math.min(10_000, Math.max(3_000, timeoutMs - 10_000)),
|
|
144
|
+
startedAt: Date.now(),
|
|
145
|
+
}, { timeoutMs, signal: ctx.signal });
|
|
146
|
+
if (!outcome.ok || !outcome.data?.a11y) {
|
|
147
|
+
const done = outcome.actionsDone?.length ? `\n\nSteps completed before the failure: ${outcome.actionsDone.join('; ')}` : '';
|
|
148
|
+
return toolError(outcome.kind ?? 'UNKNOWN', `Could not audit ${url}: ${outcome.error ?? 'no result from axe-core'}${done}`, outcome.hint, outcome.stderrTail);
|
|
149
|
+
}
|
|
150
|
+
let text = renderAudit(url, outcome.data, {
|
|
151
|
+
minImpact: args.minImpact,
|
|
152
|
+
tags,
|
|
153
|
+
stateLine: describePageState(state, root),
|
|
154
|
+
selector: args.selector,
|
|
155
|
+
});
|
|
156
|
+
const login = loginHint(outcome.data.finalUrl, state);
|
|
157
|
+
if (login)
|
|
158
|
+
text += `\n\n> 🔒 ${login}`;
|
|
159
|
+
return toolText(text);
|
|
160
|
+
}),
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=audit-accessibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-accessibility.js","sourceRoot":"","sources":["../../src/tools/audit-accessibility.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,24 +9,19 @@
|
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
import type { ToolContext, ToolResponse } from '../types/index.js';
|
|
11
11
|
declare const compareInput: z.ZodObject<{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
compare: "compare";
|
|
15
|
-
baseline: "baseline";
|
|
16
|
-
}>>;
|
|
17
|
-
tolerance: z.ZodOptional<z.ZodNumber>;
|
|
18
|
-
pixelThreshold: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
storageState: z.ZodOptional<z.ZodString>;
|
|
13
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
19
14
|
actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
20
15
|
type: z.ZodEnum<{
|
|
21
|
-
|
|
22
|
-
goto: "goto";
|
|
16
|
+
check: "check";
|
|
23
17
|
click: "click";
|
|
24
18
|
dblclick: "dblclick";
|
|
19
|
+
fill: "fill";
|
|
20
|
+
goto: "goto";
|
|
25
21
|
hover: "hover";
|
|
26
22
|
press: "press";
|
|
27
|
-
check: "check";
|
|
28
|
-
uncheck: "uncheck";
|
|
29
23
|
select: "select";
|
|
24
|
+
uncheck: "uncheck";
|
|
30
25
|
wait: "wait";
|
|
31
26
|
}>;
|
|
32
27
|
locator: z.ZodOptional<z.ZodString>;
|
|
@@ -38,40 +33,40 @@ declare const compareInput: z.ZodObject<{
|
|
|
38
33
|
width: z.ZodNumber;
|
|
39
34
|
height: z.ZodNumber;
|
|
40
35
|
}, z.core.$strip>>;
|
|
41
|
-
storageState: z.ZodOptional<z.ZodString>;
|
|
42
|
-
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
43
36
|
url: z.ZodString;
|
|
44
37
|
name: z.ZodString;
|
|
45
38
|
projectRoot: z.ZodOptional<z.ZodString>;
|
|
46
39
|
selector: z.ZodOptional<z.ZodString>;
|
|
47
40
|
fullPage: z.ZodOptional<z.ZodBoolean>;
|
|
48
41
|
waitUntil: z.ZodOptional<z.ZodEnum<{
|
|
49
|
-
load: "load";
|
|
50
42
|
domcontentloaded: "domcontentloaded";
|
|
43
|
+
load: "load";
|
|
51
44
|
networkidle: "networkidle";
|
|
52
45
|
}>>;
|
|
53
46
|
waitFor: z.ZodOptional<z.ZodString>;
|
|
54
|
-
}, z.core.$strip>;
|
|
55
|
-
export type CompareVisualStateInput = z.infer<typeof compareInput>;
|
|
56
|
-
export declare const compareVisualStateSchema: z.ZodObject<{
|
|
57
47
|
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
58
48
|
action: z.ZodOptional<z.ZodEnum<{
|
|
59
|
-
compare: "compare";
|
|
60
49
|
baseline: "baseline";
|
|
50
|
+
compare: "compare";
|
|
61
51
|
}>>;
|
|
62
52
|
tolerance: z.ZodOptional<z.ZodNumber>;
|
|
63
53
|
pixelThreshold: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
}, z.core.$strip>;
|
|
55
|
+
export type CompareVisualStateInput = z.infer<typeof compareInput>;
|
|
56
|
+
export declare const compareVisualStateSchema: z.ZodObject<{
|
|
57
|
+
storageState: z.ZodOptional<z.ZodString>;
|
|
58
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
64
59
|
actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
65
60
|
type: z.ZodEnum<{
|
|
66
|
-
|
|
67
|
-
goto: "goto";
|
|
61
|
+
check: "check";
|
|
68
62
|
click: "click";
|
|
69
63
|
dblclick: "dblclick";
|
|
64
|
+
fill: "fill";
|
|
65
|
+
goto: "goto";
|
|
70
66
|
hover: "hover";
|
|
71
67
|
press: "press";
|
|
72
|
-
check: "check";
|
|
73
|
-
uncheck: "uncheck";
|
|
74
68
|
select: "select";
|
|
69
|
+
uncheck: "uncheck";
|
|
75
70
|
wait: "wait";
|
|
76
71
|
}>;
|
|
77
72
|
locator: z.ZodOptional<z.ZodString>;
|
|
@@ -83,42 +78,42 @@ export declare const compareVisualStateSchema: z.ZodObject<{
|
|
|
83
78
|
width: z.ZodNumber;
|
|
84
79
|
height: z.ZodNumber;
|
|
85
80
|
}, z.core.$strip>>;
|
|
86
|
-
storageState: z.ZodOptional<z.ZodString>;
|
|
87
|
-
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
88
81
|
url: z.ZodString;
|
|
89
82
|
name: z.ZodString;
|
|
90
83
|
projectRoot: z.ZodOptional<z.ZodString>;
|
|
91
84
|
selector: z.ZodOptional<z.ZodString>;
|
|
92
85
|
fullPage: z.ZodOptional<z.ZodBoolean>;
|
|
93
86
|
waitUntil: z.ZodOptional<z.ZodEnum<{
|
|
94
|
-
load: "load";
|
|
95
87
|
domcontentloaded: "domcontentloaded";
|
|
88
|
+
load: "load";
|
|
96
89
|
networkidle: "networkidle";
|
|
97
90
|
}>>;
|
|
98
91
|
waitFor: z.ZodOptional<z.ZodString>;
|
|
92
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
93
|
+
action: z.ZodOptional<z.ZodEnum<{
|
|
94
|
+
baseline: "baseline";
|
|
95
|
+
compare: "compare";
|
|
96
|
+
}>>;
|
|
97
|
+
tolerance: z.ZodOptional<z.ZodNumber>;
|
|
98
|
+
pixelThreshold: z.ZodOptional<z.ZodNumber>;
|
|
99
99
|
}, z.core.$strip>;
|
|
100
100
|
export declare const compareVisualStateTool: {
|
|
101
101
|
name: string;
|
|
102
102
|
description: string;
|
|
103
103
|
inputSchema: z.ZodObject<{
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
compare: "compare";
|
|
107
|
-
baseline: "baseline";
|
|
108
|
-
}>>;
|
|
109
|
-
tolerance: z.ZodOptional<z.ZodNumber>;
|
|
110
|
-
pixelThreshold: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
storageState: z.ZodOptional<z.ZodString>;
|
|
105
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
111
106
|
actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
112
107
|
type: z.ZodEnum<{
|
|
113
|
-
|
|
114
|
-
goto: "goto";
|
|
108
|
+
check: "check";
|
|
115
109
|
click: "click";
|
|
116
110
|
dblclick: "dblclick";
|
|
111
|
+
fill: "fill";
|
|
112
|
+
goto: "goto";
|
|
117
113
|
hover: "hover";
|
|
118
114
|
press: "press";
|
|
119
|
-
check: "check";
|
|
120
|
-
uncheck: "uncheck";
|
|
121
115
|
select: "select";
|
|
116
|
+
uncheck: "uncheck";
|
|
122
117
|
wait: "wait";
|
|
123
118
|
}>;
|
|
124
119
|
locator: z.ZodOptional<z.ZodString>;
|
|
@@ -130,19 +125,24 @@ export declare const compareVisualStateTool: {
|
|
|
130
125
|
width: z.ZodNumber;
|
|
131
126
|
height: z.ZodNumber;
|
|
132
127
|
}, z.core.$strip>>;
|
|
133
|
-
storageState: z.ZodOptional<z.ZodString>;
|
|
134
|
-
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
135
128
|
url: z.ZodString;
|
|
136
129
|
name: z.ZodString;
|
|
137
130
|
projectRoot: z.ZodOptional<z.ZodString>;
|
|
138
131
|
selector: z.ZodOptional<z.ZodString>;
|
|
139
132
|
fullPage: z.ZodOptional<z.ZodBoolean>;
|
|
140
133
|
waitUntil: z.ZodOptional<z.ZodEnum<{
|
|
141
|
-
load: "load";
|
|
142
134
|
domcontentloaded: "domcontentloaded";
|
|
135
|
+
load: "load";
|
|
143
136
|
networkidle: "networkidle";
|
|
144
137
|
}>>;
|
|
145
138
|
waitFor: z.ZodOptional<z.ZodString>;
|
|
139
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
140
|
+
action: z.ZodOptional<z.ZodEnum<{
|
|
141
|
+
baseline: "baseline";
|
|
142
|
+
compare: "compare";
|
|
143
|
+
}>>;
|
|
144
|
+
tolerance: z.ZodOptional<z.ZodNumber>;
|
|
145
|
+
pixelThreshold: z.ZodOptional<z.ZodNumber>;
|
|
146
146
|
}, z.core.$strip>;
|
|
147
147
|
handler: (args: CompareVisualStateInput, ctx: ToolContext) => Promise<ToolResponse>;
|
|
148
148
|
};
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
* keeps only one result per test. `isolate` adds a second pass with one
|
|
10
10
|
* worker so failures caused by parallelism (shared state, test-order
|
|
11
11
|
* coupling, contention) are told apart from flakiness inside the test.
|
|
12
|
+
* `order` (Playwright 1.64+) runs the target files in several random orders
|
|
13
|
+
* with one worker and replays a failing order, which finds tests that pass
|
|
14
|
+
* or fail depending on what ran before them, and names the likely culprit.
|
|
12
15
|
*
|
|
13
16
|
* The verdict logic is pure functions (exported for unit tests).
|
|
14
17
|
*/
|
|
@@ -26,6 +29,7 @@ declare const diagnoseFlakyInput: z.ZodObject<{
|
|
|
26
29
|
headed: z.ZodOptional<z.ZodBoolean>;
|
|
27
30
|
workers: z.ZodOptional<z.ZodNumber>;
|
|
28
31
|
isolate: z.ZodOptional<z.ZodBoolean>;
|
|
32
|
+
order: z.ZodOptional<z.ZodBoolean>;
|
|
29
33
|
separateProcesses: z.ZodOptional<z.ZodBoolean>;
|
|
30
34
|
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
31
35
|
config: z.ZodOptional<z.ZodString>;
|
|
@@ -43,6 +47,7 @@ export declare const diagnoseFlakySchema: z.ZodObject<{
|
|
|
43
47
|
headed: z.ZodOptional<z.ZodBoolean>;
|
|
44
48
|
workers: z.ZodOptional<z.ZodNumber>;
|
|
45
49
|
isolate: z.ZodOptional<z.ZodBoolean>;
|
|
50
|
+
order: z.ZodOptional<z.ZodBoolean>;
|
|
46
51
|
separateProcesses: z.ZodOptional<z.ZodBoolean>;
|
|
47
52
|
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
48
53
|
config: z.ZodOptional<z.ZodString>;
|
|
@@ -95,6 +100,38 @@ export type IsolationReading = 'PARALLEL ONLY' | 'FLAKY ALONE TOO' | 'FAILS EITH
|
|
|
95
100
|
* was therefore not re-run.
|
|
96
101
|
*/
|
|
97
102
|
export declare function isolationReading(parallel: FlakySummary, isolated: FlakySummary | undefined): IsolationReading;
|
|
103
|
+
/** True when this Playwright version has `--shuffle` (1.64+). */
|
|
104
|
+
export declare function supportsShuffle(version: string | null | undefined): boolean;
|
|
105
|
+
/** One shuffled run: its seed and the attempts in execution order (one worker). */
|
|
106
|
+
export interface OrderRun {
|
|
107
|
+
seed: string;
|
|
108
|
+
attempts: TestAttempt[];
|
|
109
|
+
}
|
|
110
|
+
export type OrderReading = 'ORDER DEPENDENT' | 'FLAKY IN ANY ORDER' | 'FAILS IN EVERY ORDER' | 'PASSES IN EVERY ORDER';
|
|
111
|
+
export interface OrderFinding {
|
|
112
|
+
file: string;
|
|
113
|
+
line?: number;
|
|
114
|
+
title: string;
|
|
115
|
+
project?: string;
|
|
116
|
+
passedSeeds: string[];
|
|
117
|
+
failedSeeds: string[];
|
|
118
|
+
/** The failing seed replayed to confirm, and whether it failed again. */
|
|
119
|
+
replay?: {
|
|
120
|
+
seed: string;
|
|
121
|
+
failedAgain: boolean;
|
|
122
|
+
};
|
|
123
|
+
reading: OrderReading;
|
|
124
|
+
/** Tests that ran before this one in every failing order but after it in a passing one (they break it). */
|
|
125
|
+
suspects: string[];
|
|
126
|
+
/** Tests that ran before it in every passing order but after it in a failing one (it relies on them). */
|
|
127
|
+
reliesOn: string[];
|
|
128
|
+
headline?: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Read shuffled runs (plus replays of failing seeds) per test. Pure, so the
|
|
132
|
+
* verdicts are unit-tested without Playwright.
|
|
133
|
+
*/
|
|
134
|
+
export declare function analyzeOrder(runs: OrderRun[], replays?: OrderRun[]): OrderFinding[];
|
|
98
135
|
/**
|
|
99
136
|
* Split one --repeat-each run into one run per repetition, so run history
|
|
100
137
|
* (analyze-history) counts every repetition as its own run, exactly as it
|
|
@@ -116,6 +153,7 @@ export declare const diagnoseFlakyTool: {
|
|
|
116
153
|
headed: z.ZodOptional<z.ZodBoolean>;
|
|
117
154
|
workers: z.ZodOptional<z.ZodNumber>;
|
|
118
155
|
isolate: z.ZodOptional<z.ZodBoolean>;
|
|
156
|
+
order: z.ZodOptional<z.ZodBoolean>;
|
|
119
157
|
separateProcesses: z.ZodOptional<z.ZodBoolean>;
|
|
120
158
|
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
121
159
|
config: z.ZodOptional<z.ZodString>;
|