playwright-e2e-mcp 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +208 -54
  2. package/dist/http.d.ts +1 -1
  3. package/dist/http.js +1 -1
  4. package/dist/prompts.d.ts +6 -0
  5. package/dist/prompts.js +39 -0
  6. package/dist/prompts.js.map +1 -0
  7. package/dist/server.d.ts +4 -3
  8. package/dist/server.js +63 -5
  9. package/dist/server.js.map +1 -1
  10. package/dist/tools/analyze-history.d.ts +48 -0
  11. package/dist/tools/analyze-history.js +132 -0
  12. package/dist/tools/analyze-history.js.map +1 -0
  13. package/dist/tools/compare-visual-state.d.ts +89 -17
  14. package/dist/tools/compare-visual-state.js +10 -3
  15. package/dist/tools/compare-visual-state.js.map +1 -1
  16. package/dist/tools/diagnose-flaky.js +5 -2
  17. package/dist/tools/diagnose-flaky.js.map +1 -1
  18. package/dist/tools/generate-e2e-test.d.ts +11 -0
  19. package/dist/tools/generate-e2e-test.js +50 -3
  20. package/dist/tools/generate-e2e-test.js.map +1 -1
  21. package/dist/tools/get-failure.d.ts +6 -1
  22. package/dist/tools/get-failure.js +17 -11
  23. package/dist/tools/get-failure.js.map +1 -1
  24. package/dist/tools/get-run-status.d.ts +28 -0
  25. package/dist/tools/get-run-status.js +75 -0
  26. package/dist/tools/get-run-status.js.map +1 -0
  27. package/dist/tools/inspect-page.d.ts +102 -14
  28. package/dist/tools/inspect-page.js +50 -10
  29. package/dist/tools/inspect-page.js.map +1 -1
  30. package/dist/tools/probe-script.d.ts +20 -0
  31. package/dist/tools/probe-script.js +641 -0
  32. package/dist/tools/probe-script.js.map +1 -0
  33. package/dist/tools/run-test.d.ts +5 -1
  34. package/dist/tools/run-test.js +30 -3
  35. package/dist/tools/run-test.js.map +1 -1
  36. package/dist/tools/shared.d.ts +117 -3
  37. package/dist/tools/shared.js +154 -285
  38. package/dist/tools/shared.js.map +1 -1
  39. package/dist/tools/suggest-fix.d.ts +89 -0
  40. package/dist/tools/suggest-fix.js +437 -0
  41. package/dist/tools/suggest-fix.js.map +1 -0
  42. package/dist/tools/validate-selector.d.ts +83 -6
  43. package/dist/tools/validate-selector.js +71 -32
  44. package/dist/tools/validate-selector.js.map +1 -1
  45. package/dist/types/index.d.ts +40 -0
  46. package/dist/utils/locator-expr.d.ts +38 -0
  47. package/dist/utils/locator-expr.js +280 -0
  48. package/dist/utils/locator-expr.js.map +1 -0
  49. package/dist/utils/playwright-runner.d.ts +9 -1
  50. package/dist/utils/playwright-runner.js +60 -4
  51. package/dist/utils/playwright-runner.js.map +1 -1
  52. package/dist/utils/report-parser.d.ts +3 -1
  53. package/dist/utils/report-parser.js +22 -0
  54. package/dist/utils/report-parser.js.map +1 -1
  55. package/dist/utils/run-history.d.ts +103 -0
  56. package/dist/utils/run-history.js +219 -0
  57. package/dist/utils/run-history.js.map +1 -0
  58. package/dist/utils/run-registry.d.ts +34 -0
  59. package/dist/utils/run-registry.js +86 -0
  60. package/dist/utils/run-registry.js.map +1 -0
  61. package/dist/utils/trace-reader.d.ts +23 -2
  62. package/dist/utils/trace-reader.js +86 -15
  63. package/dist/utils/trace-reader.js.map +1 -1
  64. package/package.json +2 -2
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Tool 9 — suggest-fix: turn a failure from the last run into a concrete
3
+ * patch for the spec, optionally apply it, and prove it by re-running the
4
+ * test (reverting the file when the re-run still fails).
5
+ *
6
+ * Handles the two most common E2E breakages:
7
+ * - Locator drift: the element is still on the page but its test id, text
8
+ * or structure changed. The broken locator's words are matched against
9
+ * the DOM at failure (from the Playwright trace, or a live URL), and the
10
+ * best match gets a Playwright locator proven unique on that page.
11
+ * - Copy changes in text assertions (toHaveText & co): the expected string
12
+ * is replaced with what the page shows. That can hide a real regression,
13
+ * so it is applied only with allowExpectationUpdate.
14
+ *
15
+ * When no element plausibly matches, the tool says so: a missing element is
16
+ * usually an app bug, and "healing" it would hide the bug.
17
+ */
18
+ import { z } from 'zod';
19
+ import type { ElementInfo, TestFailure, ToolContext, ToolResponse } from '../types/index.js';
20
+ import type { LocatorCall } from '../utils/locator-expr.js';
21
+ declare const suggestFixInput: z.ZodObject<{
22
+ apply: z.ZodOptional<z.ZodBoolean>;
23
+ verify: z.ZodOptional<z.ZodBoolean>;
24
+ allowExpectationUpdate: z.ZodOptional<z.ZodBoolean>;
25
+ config: z.ZodOptional<z.ZodString>;
26
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
27
+ storageState: z.ZodOptional<z.ZodString>;
28
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
29
+ index: z.ZodOptional<z.ZodNumber>;
30
+ projectRoot: z.ZodOptional<z.ZodString>;
31
+ url: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strip>;
33
+ export type SuggestFixInput = z.infer<typeof suggestFixInput>;
34
+ export declare const suggestFixSchema: z.ZodObject<{
35
+ apply: z.ZodOptional<z.ZodBoolean>;
36
+ verify: z.ZodOptional<z.ZodBoolean>;
37
+ allowExpectationUpdate: z.ZodOptional<z.ZodBoolean>;
38
+ config: z.ZodOptional<z.ZodString>;
39
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
40
+ storageState: z.ZodOptional<z.ZodString>;
41
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
42
+ index: z.ZodOptional<z.ZodNumber>;
43
+ projectRoot: z.ZodOptional<z.ZodString>;
44
+ url: z.ZodOptional<z.ZodString>;
45
+ }, z.core.$strip>;
46
+ /** Pull the locator Playwright printed in the error ("Locator: …", "waiting for …"). */
47
+ export declare function brokenLocatorFromMessage(message: string): string | undefined;
48
+ export interface HealTokens {
49
+ /** All words to score elements with. */
50
+ tokens: string[];
51
+ /** The words that identify the element (what must match for a confident fix). */
52
+ distinctive: string[];
53
+ role?: string;
54
+ }
55
+ /** Split a broken locator into scoring words. */
56
+ export declare function healTokensFor(chain: LocatorCall[]): HealTokens;
57
+ export interface Confidence {
58
+ level: 'high' | 'medium' | 'none';
59
+ matched: string[];
60
+ }
61
+ /** How sure we are that `element` is what the broken locator meant. */
62
+ export declare function healConfidence(element: ElementInfo, heal: HealTokens, runnerUp?: ElementInfo): Confidence;
63
+ /** Find the source span of a locator's first call on a line, tolerant of quote style and spacing. */
64
+ export declare function findCallSpan(line: string, call: LocatorCall): {
65
+ start: number;
66
+ end: number;
67
+ } | undefined;
68
+ /** Line of the failing call inside `file`, from the stack ("…/file.spec.ts:18:47"). */
69
+ export declare function failingLine(failure: TestFailure): number | undefined;
70
+ /** Minimal unified diff for a single changed line. */
71
+ export declare function unifiedDiff(file: string, lines: string[], lineNo: number, replacement: string): string;
72
+ export declare const suggestFixTool: {
73
+ name: string;
74
+ description: string;
75
+ inputSchema: z.ZodObject<{
76
+ apply: z.ZodOptional<z.ZodBoolean>;
77
+ verify: z.ZodOptional<z.ZodBoolean>;
78
+ allowExpectationUpdate: z.ZodOptional<z.ZodBoolean>;
79
+ config: z.ZodOptional<z.ZodString>;
80
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
81
+ storageState: z.ZodOptional<z.ZodString>;
82
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
83
+ index: z.ZodOptional<z.ZodNumber>;
84
+ projectRoot: z.ZodOptional<z.ZodString>;
85
+ url: z.ZodOptional<z.ZodString>;
86
+ }, z.core.$strip>;
87
+ handler: (args: SuggestFixInput, ctx: ToolContext) => Promise<ToolResponse>;
88
+ };
89
+ export {};
@@ -0,0 +1,437 @@
1
+ /**
2
+ * Tool 9 — suggest-fix: turn a failure from the last run into a concrete
3
+ * patch for the spec, optionally apply it, and prove it by re-running the
4
+ * test (reverting the file when the re-run still fails).
5
+ *
6
+ * Handles the two most common E2E breakages:
7
+ * - Locator drift: the element is still on the page but its test id, text
8
+ * or structure changed. The broken locator's words are matched against
9
+ * the DOM at failure (from the Playwright trace, or a live URL), and the
10
+ * best match gets a Playwright locator proven unique on that page.
11
+ * - Copy changes in text assertions (toHaveText & co): the expected string
12
+ * is replaced with what the page shows. That can hide a real regression,
13
+ * so it is applied only with allowExpectationUpdate.
14
+ *
15
+ * When no element plausibly matches, the tool says so: a missing element is
16
+ * usually an app bug, and "healing" it would hide the bug.
17
+ */
18
+ import { readFile, rm, writeFile } from 'node:fs/promises';
19
+ import { z } from 'zod';
20
+ import { PlaywrightMcpError } from '../types/index.js';
21
+ import { readFailureTrace } from '../utils/trace-reader.js';
22
+ import { runTests } from '../utils/playwright-runner.js';
23
+ import { detectProject } from '../utils/project-detector.js';
24
+ import { recordRun } from '../utils/run-history.js';
25
+ import { assertRealPathInside, isTestFile, sanitizeUserPath, tempFilePath, writeFileInsideRoot, } from '../utils/path-utils.js';
26
+ import { formatLocator, parseLocator, quote } from '../utils/locator-expr.js';
27
+ import { assertUrlAllowed } from '../utils/url-policy.js';
28
+ import { assertHttpUrl, bestLocator, clipLines, codeFence, formatDuration, guard, resolveConfigSelection, resolvePageState, resolveProjectRoot, runBrowserScript, sessionShape, toolText, } from './shared.js';
29
+ import { allFailures } from './get-failure.js';
30
+ const suggestFixInput = z.object({
31
+ index: z.number().int().min(1).optional().describe('1-based failure index (default 1)'),
32
+ projectRoot: z.string().optional(),
33
+ url: z.string().optional().describe('Heal against this live page instead of the trace snapshot'),
34
+ ...sessionShape,
35
+ apply: z.boolean().optional().describe('Write the fix (default: diff only)'),
36
+ verify: z.boolean().optional().describe('Re-run after applying; revert if still failing (default true)'),
37
+ allowExpectationUpdate: z.boolean().optional().describe('Allow applying changed expected text (can hide regressions)'),
38
+ config: z.string().optional().describe('playwright.config path or 1-based index'),
39
+ timeoutMs: z.number().int().min(1_000).max(3_600_000).optional().describe('Verification run limit (default 120000)'),
40
+ });
41
+ export const suggestFixSchema = suggestFixInput;
42
+ /* ------------------------------------------------------------------ */
43
+ /* Pure helpers (unit-tested) */
44
+ /* ------------------------------------------------------------------ */
45
+ /** Pull the locator Playwright printed in the error ("Locator: …", "waiting for …"). */
46
+ export function brokenLocatorFromMessage(message) {
47
+ const lines = message.split(/\r?\n/);
48
+ for (const line of lines) {
49
+ const m = /(?:^|\s)(?:Locator:|waiting for)\s+((?:getBy\w+|locator)\(.*)$/.exec(line.trim());
50
+ if (!m)
51
+ continue;
52
+ const text = m[1].trim();
53
+ try {
54
+ parseLocator(text);
55
+ return text;
56
+ }
57
+ catch {
58
+ /* not a clean expression; keep looking */
59
+ }
60
+ }
61
+ return undefined;
62
+ }
63
+ const SYNONYMS = {
64
+ btn: ['button'],
65
+ nav: ['navigation'],
66
+ img: ['image'],
67
+ pwd: ['password'],
68
+ msg: ['message'],
69
+ qty: ['quantity'],
70
+ cta: ['call', 'action'],
71
+ submit: ['save', 'send'],
72
+ signin: ['sign', 'login'],
73
+ login: ['sign', 'signin'],
74
+ };
75
+ /** Words that say what kind of element it is, not which one. */
76
+ const GENERIC = new Set([
77
+ 'button', 'btn', 'link', 'input', 'field', 'text', 'label', 'icon', 'item', 'container', 'wrapper', 'div', 'span',
78
+ 'el', 'element', 'box', 'form', 'page', 'main', 'section', 'the', 'and', 'name', 'exact', 'true', 'false', 'id',
79
+ 'test', 'testid', 'data', 'role', 'heading', 'textbox', 'checkbox', 'option', 'locator', 'get', 'by', 'css',
80
+ ]);
81
+ /** Split a broken locator into scoring words. */
82
+ export function healTokensFor(chain) {
83
+ const words = [];
84
+ let role;
85
+ const collect = (value) => {
86
+ if (typeof value === 'string') {
87
+ words.push(...value
88
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
89
+ .toLowerCase()
90
+ .split(/[^a-z0-9]+/)
91
+ .filter((w) => w.length > 1));
92
+ }
93
+ else if (value && typeof value === 'object' && !('$regex' in value)) {
94
+ for (const inner of Object.values(value))
95
+ collect(inner);
96
+ }
97
+ else if (value && typeof value === 'object' && '$regex' in value) {
98
+ collect(value.$regex);
99
+ }
100
+ };
101
+ for (const call of chain) {
102
+ if (call.method === 'getByRole' && typeof call.args[0] === 'string') {
103
+ role = call.args[0];
104
+ for (const arg of call.args.slice(1))
105
+ collect(arg);
106
+ continue;
107
+ }
108
+ if (call.method === 'locator' && typeof call.args[0] === 'string') {
109
+ // Keep attribute values and ids/classes; drop CSS syntax and tag names.
110
+ const css = call.args[0];
111
+ const parts = [...css.matchAll(/[#.]([\w-]+)|=\s*["']?([^"'\]]+)/g)].map((m) => m[1] ?? m[2]);
112
+ collect(parts.join(' '));
113
+ continue;
114
+ }
115
+ for (const arg of call.args)
116
+ collect(arg);
117
+ }
118
+ const expanded = new Set();
119
+ for (const word of words) {
120
+ expanded.add(word);
121
+ for (const syn of SYNONYMS[word] ?? [])
122
+ expanded.add(syn);
123
+ }
124
+ const tokens = [...expanded];
125
+ const distinctive = [...new Set(words.filter((w) => !GENERIC.has(w) && !/^\d+$/.test(w)))];
126
+ return { tokens, distinctive, role };
127
+ }
128
+ /** How sure we are that `element` is what the broken locator meant. */
129
+ export function healConfidence(element, heal, runnerUp) {
130
+ const hay = [
131
+ element.id,
132
+ element.attributes['data-testid'],
133
+ element.attributes['data-test-id'],
134
+ element.attributes['data-test'],
135
+ element.attributes.name,
136
+ element.attributes['aria-label'],
137
+ element.attributes.placeholder,
138
+ element.attributes.title,
139
+ element.attributes.alt,
140
+ element.name,
141
+ element.text,
142
+ ]
143
+ .filter(Boolean)
144
+ .join(' ')
145
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
146
+ .toLowerCase();
147
+ const words = new Set(hay.split(/[^a-z0-9]+/).filter(Boolean));
148
+ const matched = heal.distinctive.filter((token) => words.has(token) || [...words].some((w) => w.length > 2 && (w.startsWith(token) || token.startsWith(w))));
149
+ if (heal.distinctive.length === 0 || matched.length === 0)
150
+ return { level: 'none', matched };
151
+ const share = matched.length / heal.distinctive.length;
152
+ const roleOk = heal.role === undefined || element.role === heal.role;
153
+ const clearWinner = runnerUp === undefined || (element.score ?? 0) > (runnerUp.score ?? 0);
154
+ if (share >= 0.5 && roleOk && clearWinner)
155
+ return { level: 'high', matched };
156
+ if (share >= 0.5 || (matched.length >= 1 && roleOk))
157
+ return { level: 'medium', matched };
158
+ return { level: 'none', matched };
159
+ }
160
+ /** Find the source span of a locator's first call on a line, tolerant of quote style and spacing. */
161
+ export function findCallSpan(line, call) {
162
+ const first = call.args[0];
163
+ if (typeof first !== 'string')
164
+ return undefined;
165
+ const escaped = first.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/'/g, "(?:'|\\\\')").replace(/"/g, '(?:"|\\\\")');
166
+ const re = new RegExp(`\\b${call.method}\\s*\\(\\s*(['"\`])${escaped}\\1`);
167
+ const m = re.exec(line);
168
+ if (!m)
169
+ return undefined;
170
+ // Walk to the matching close paren, skipping string contents.
171
+ let depth = 0;
172
+ let quoteChar = null;
173
+ for (let i = m.index + call.method.length; i < line.length; i += 1) {
174
+ const ch = line[i];
175
+ if (quoteChar) {
176
+ if (ch === '\\')
177
+ i += 1;
178
+ else if (ch === quoteChar)
179
+ quoteChar = null;
180
+ continue;
181
+ }
182
+ if (ch === "'" || ch === '"' || ch === '`')
183
+ quoteChar = ch;
184
+ else if (ch === '(')
185
+ depth += 1;
186
+ else if (ch === ')') {
187
+ depth -= 1;
188
+ if (depth === 0)
189
+ return { start: m.index, end: i + 1 };
190
+ }
191
+ }
192
+ return undefined;
193
+ }
194
+ /** Line of the failing call inside `file`, from the stack ("…/file.spec.ts:18:47"). */
195
+ export function failingLine(failure) {
196
+ const text = `${failure.stack ?? ''}\n${failure.message}`;
197
+ const base = failure.file.split('/').pop();
198
+ if (!base)
199
+ return failure.line;
200
+ const re = new RegExp(`${base.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}:(\\d+)(?::\\d+)?`, 'g');
201
+ let found;
202
+ for (const m of text.matchAll(re)) {
203
+ found = Number(m[1]);
204
+ break;
205
+ }
206
+ return found ?? failure.line;
207
+ }
208
+ /** Minimal unified diff for a single changed line. */
209
+ export function unifiedDiff(file, lines, lineNo, replacement) {
210
+ const idx = lineNo - 1;
211
+ const from = Math.max(0, idx - 2);
212
+ const to = Math.min(lines.length, idx + 3);
213
+ const out = [`--- a/${file}`, `+++ b/${file}`, `@@ -${from + 1},${to - from} +${from + 1},${to - from} @@`];
214
+ for (let i = from; i < to; i += 1) {
215
+ if (i === idx) {
216
+ out.push(`-${lines[i]}`, `+${replacement}`);
217
+ }
218
+ else {
219
+ out.push(` ${lines[i]}`);
220
+ }
221
+ }
222
+ return out.join('\n');
223
+ }
224
+ const EXPECTATION_MATCHERS = /toHaveText|toContainText|toHaveTitle|toHaveValue|toHaveAttribute|toHaveURL/;
225
+ async function proposeExpectationFix(failure, lines, lineNo) {
226
+ if (failure.expected === undefined || failure.actual === undefined)
227
+ return undefined;
228
+ if (!EXPECTATION_MATCHERS.test(failure.message))
229
+ return undefined;
230
+ const expected = failure.expected.replace(/^"|"$/g, '');
231
+ const actual = failure.actual.replace(/^"|"$/g, '');
232
+ if (expected === '' || actual === '' || actual.length > 200 || /\n/.test(actual))
233
+ return undefined;
234
+ const line = lines[lineNo - 1] ?? '';
235
+ for (const q of ["'", '"', '`']) {
236
+ const literal = `${q}${expected}${q}`;
237
+ const at = line.indexOf(literal);
238
+ if (at < 0)
239
+ continue;
240
+ const replacement = q === "'" ? quote(actual) : `${q}${actual.replace(new RegExp(q, 'g'), `\\${q}`)}${q}`;
241
+ return {
242
+ kind: 'expectation',
243
+ confidence: 'low',
244
+ lineNo,
245
+ before: line,
246
+ after: line.slice(0, at) + replacement + line.slice(at + literal.length),
247
+ why: `The page shows ${JSON.stringify(actual)} where the test expects ${JSON.stringify(expected)}. Update the expectation only if that copy change was intended; otherwise this is the bug.`,
248
+ };
249
+ }
250
+ return undefined;
251
+ }
252
+ function renderHeader(failure, index, total) {
253
+ return [
254
+ `## 🩹 Fix for failure ${index} of ${total} — ${failure.title}`,
255
+ '',
256
+ `**File:** \`${failure.file}${failure.line ? `:${failure.line}` : ''}\` | **Kind:** \`${failure.failureKind}\``,
257
+ '',
258
+ ];
259
+ }
260
+ export const suggestFixTool = {
261
+ name: 'suggest-fix',
262
+ description: "Patch a failure from the last run: a drifted locator is matched against the DOM at failure (trace, or live url) and replaced with one proven unique; changed copy gets the new expected text. Returns a diff and confidence; apply: true writes it, re-runs the test and reverts if still red. Refuses when the element is truly missing (app bug).",
263
+ inputSchema: suggestFixSchema,
264
+ handler: async (args, ctx) => guard('suggest-fix', async () => {
265
+ const record = ctx.store.lastRun;
266
+ if (!record) {
267
+ throw new PlaywrightMcpError('No test run has happened yet', 'REPORT_MISSING', {
268
+ hint: 'Call run-test first; suggest-fix works on the failures of the most recent run.',
269
+ });
270
+ }
271
+ const root = await resolveProjectRoot(args.projectRoot ?? record.projectRoot, ctx);
272
+ const failures = await allFailures(record);
273
+ if (failures.length === 0)
274
+ return toolText('## ✅ Nothing to fix\n\nThe last run had no failures.');
275
+ const index = Math.min(args.index ?? 1, failures.length);
276
+ const failure = failures[index - 1];
277
+ const out = renderHeader(failure, index, failures.length);
278
+ if (!failure.file || !isTestFile(failure.file)) {
279
+ out.push('No spec file is attached to this failure (it is a configuration or global error), so there is nothing to patch. Use **get-failure** for the details.');
280
+ return toolText(out.join('\n'));
281
+ }
282
+ const specPath = sanitizeUserPath(failure.file, root);
283
+ await assertRealPathInside(specPath, root);
284
+ const source = await readFile(specPath, 'utf8');
285
+ const eol = source.includes('\r\n') ? '\r\n' : '\n';
286
+ const lines = source.split(/\r?\n/);
287
+ const lineNo = failingLine(failure) ?? failure.line ?? 1;
288
+ let proposal;
289
+ const notes = [];
290
+ // 1. Locator drift.
291
+ const brokenText = brokenLocatorFromMessage(failure.message);
292
+ if (brokenText) {
293
+ const chain = parseLocator(brokenText);
294
+ const heal = healTokensFor(chain);
295
+ let elements = [];
296
+ let domSource;
297
+ const state = args.url ? await resolvePageState(args, root, assertHttpUrl(args.url), ctx) : {};
298
+ let snapshotFile;
299
+ try {
300
+ if (args.url) {
301
+ const url = assertHttpUrl(args.url);
302
+ await assertUrlAllowed(url);
303
+ domSource = `the live page ${url}`;
304
+ }
305
+ else {
306
+ const trace = failure.tracePath ? await readFailureTrace(failure.tracePath, { maxHtmlChars: 2_000_000 }).catch(() => null) : null;
307
+ if (!trace?.snapshotHtml) {
308
+ throw new PlaywrightMcpError('The failure has no DOM snapshot to heal against', 'REPORT_MISSING', {
309
+ hint: 'Pass `url` (plus storageState/actions if needed) so the fix is computed against the live page, or re-run the test so a trace is captured.',
310
+ });
311
+ }
312
+ snapshotFile = tempFilePath('pw-mcp-snapshot', '.html');
313
+ await writeFile(snapshotFile, trace.snapshotHtml, 'utf8');
314
+ domSource = 'the DOM snapshot at failure (Playwright trace)';
315
+ }
316
+ const outcome = await runBrowserScript({
317
+ ...state,
318
+ mode: 'heal',
319
+ projectRoot: root,
320
+ url: args.url ? assertHttpUrl(args.url) : undefined,
321
+ snapshotHtmlPath: snapshotFile,
322
+ healTokens: heal.tokens,
323
+ healRole: heal.role,
324
+ gotoTimeout: 30_000,
325
+ startedAt: Date.now(),
326
+ }, { timeoutMs: 60_000, signal: ctx.signal });
327
+ if (!outcome.ok) {
328
+ throw new PlaywrightMcpError(`Could not open ${domSource}: ${outcome.error ?? 'unknown error'}`, outcome.kind ?? 'UNKNOWN', {
329
+ hint: outcome.hint,
330
+ });
331
+ }
332
+ elements = outcome.data?.elements ?? [];
333
+ }
334
+ finally {
335
+ if (snapshotFile)
336
+ await rm(snapshotFile, { force: true }).catch(() => undefined);
337
+ }
338
+ const usable = elements.filter((element) => (element.locators?.length ?? 0) > 0);
339
+ const best = usable[0];
340
+ const confidence = best ? healConfidence(best, heal, usable[1]) : { level: 'none', matched: [] };
341
+ const line = lines[lineNo - 1] ?? '';
342
+ const span = findCallSpan(line, chain[0]);
343
+ if (!best || confidence.level === 'none') {
344
+ notes.push(`**No confident replacement for \`${brokenText}\`** in ${domSource}. Nothing on the page matches ${heal.distinctive.length > 0 ? heal.distinctive.map((w) => `"${w}"`).join(', ') : 'its words'}${best ? ` (closest: \`${bestLocator(best)}\`, which shares only generic words)` : ''}.`, '', 'The element is most likely **missing**, not renamed: the app did not render it (a real bug, a failed request, or a missing step before this line). Fixing the test would hide that. Check **get-failure** for failed requests and console errors first.');
345
+ }
346
+ else if (!span) {
347
+ notes.push(`Found the likely target: \`${bestLocator(best)}\`, but could not locate \`${formatLocator(chain.slice(0, 1))}\` on line ${lineNo} of \`${failure.file}\` to patch it automatically. Replace it by hand.`);
348
+ }
349
+ else {
350
+ const replacement = `${line.slice(0, span.start)}${bestLocator(best)}${line.slice(span.end)}`;
351
+ proposal = {
352
+ kind: 'locator',
353
+ confidence: confidence.level,
354
+ lineNo,
355
+ before: line,
356
+ after: replacement,
357
+ why: `\`${brokenText}\` no longer matches anything. In ${domSource}, ${best.role ? `the ${best.role}${best.name ? ` "${clipLines(best.name, 1, 60)}"` : ''}` : `the <${best.tag}> element`} matches ${confidence.matched.map((w) => `"${w}"`).join(', ')}, and \`${bestLocator(best)}\` is proven to resolve to exactly that element.`,
358
+ alternatives: usable
359
+ .slice(1)
360
+ .filter((element) => healConfidence(element, heal).level !== 'none')
361
+ .slice(0, 2)
362
+ .map((element) => bestLocator(element))
363
+ .filter((value) => value !== undefined),
364
+ };
365
+ }
366
+ }
367
+ // 2. Changed copy in a text/value assertion.
368
+ if (!proposal) {
369
+ const expectation = await proposeExpectationFix(failure, lines, lineNo);
370
+ if (expectation)
371
+ proposal = expectation;
372
+ }
373
+ if (!proposal) {
374
+ if (notes.length === 0) {
375
+ notes.push(`No automatic fix applies to this \`${failure.failureKind}\` failure: suggest-fix patches broken locators and changed expected text. Use **get-failure** for the trace, then edit by hand.`);
376
+ }
377
+ out.push(...notes);
378
+ return toolText(out.join('\n'));
379
+ }
380
+ const diff = unifiedDiff(failure.file, lines, proposal.lineNo, proposal.after);
381
+ out.push(`### Proposed ${proposal.kind === 'locator' ? 'locator fix' : 'expectation update'} — confidence **${proposal.confidence}**`, '', proposal.why, '', codeFence(diff, 'diff'), '');
382
+ if (proposal.alternatives && proposal.alternatives.length > 0) {
383
+ out.push(`Other candidates: ${proposal.alternatives.map((a) => `\`${a}\``).join(', ')}`, '');
384
+ }
385
+ const mayApply = proposal.kind === 'locator' || args.allowExpectationUpdate === true;
386
+ if (!args.apply) {
387
+ out.push(mayApply
388
+ ? '> Next: call **suggest-fix** again with `apply: true` to write this change and re-run the test to verify it.'
389
+ : '> This changes what the test asserts. Apply it by hand, or pass `apply: true, allowExpectationUpdate: true` if the new text is intended.');
390
+ return toolText(out.join('\n'));
391
+ }
392
+ if (!mayApply) {
393
+ out.push('> ⛔ Not applied: expectation updates need `allowExpectationUpdate: true`, because they can hide a real regression.');
394
+ return toolText(out.join('\n'));
395
+ }
396
+ // Apply: refuse if the file changed since we read it.
397
+ const current = await readFile(specPath, 'utf8');
398
+ if (current !== source) {
399
+ throw new PlaywrightMcpError(`${failure.file} changed while the fix was being computed`, 'INVALID_PATH', {
400
+ hint: 'Call suggest-fix again to compute the fix against the current file.',
401
+ });
402
+ }
403
+ const patched = [...lines];
404
+ patched[proposal.lineNo - 1] = proposal.after;
405
+ await writeFileInsideRoot(specPath, patched.join(eol), root);
406
+ out.push(`**Applied** to \`${failure.file}:${proposal.lineNo}\`.`, '');
407
+ if (args.verify === false) {
408
+ out.push('> Not verified (verify: false). Re-run with **run-test** to check it.');
409
+ return toolText(out.join('\n'));
410
+ }
411
+ const detection = await detectProject(root);
412
+ const configPath = resolveConfigSelection(detection, args.config);
413
+ const target = `${specPath}${failure.line ? `:${failure.line}` : ''}`;
414
+ const result = await runTests({
415
+ projectRoot: root,
416
+ configPath,
417
+ testFiles: [target],
418
+ project: failure.project,
419
+ retries: 0,
420
+ retryOnFailure: false,
421
+ timeoutMs: args.timeoutMs,
422
+ signal: ctx.signal,
423
+ });
424
+ ctx.store.setLastRun({ projectRoot: root, result, at: Date.now() });
425
+ await recordRun(root, result, 'suggest-fix').catch(() => undefined);
426
+ if (result.ok) {
427
+ out.push(`### ✅ Verified — the test passes with the fix (${formatDuration(result.durationMs)}).`);
428
+ }
429
+ else {
430
+ await writeFileInsideRoot(specPath, source, root);
431
+ const first = result.failures[0];
432
+ out.push(`### ❌ Still failing — the change was reverted`, '', first ? codeFence(clipLines(first.message, 8, 1_200), 'text') : (result.errorMessage ?? 'The run failed without a test failure.'), '', '> The original file is restored. Call **get-failure** for the new failure, or try another candidate by hand.');
433
+ }
434
+ return toolText(out.join('\n'));
435
+ }),
436
+ };
437
+ //# sourceMappingURL=suggest-fix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggest-fix.js","sourceRoot":"","sources":["../../src/tools/suggest-fix.ts"],"names":[],"mappings":"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"}