playwright-e2e-mcp 0.1.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/LICENSE +21 -0
- package/README.md +497 -0
- package/dist/http.d.ts +27 -0
- package/dist/http.js +156 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.js +225 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/compare-visual-state.d.ts +77 -0
- package/dist/tools/compare-visual-state.js +223 -0
- package/dist/tools/compare-visual-state.js.map +1 -0
- package/dist/tools/diagnose-flaky.d.ts +87 -0
- package/dist/tools/diagnose-flaky.js +258 -0
- package/dist/tools/diagnose-flaky.js.map +1 -0
- package/dist/tools/generate-e2e-test.d.ts +51 -0
- package/dist/tools/generate-e2e-test.js +274 -0
- package/dist/tools/generate-e2e-test.js.map +1 -0
- package/dist/tools/get-failure.d.ts +26 -0
- package/dist/tools/get-failure.js +220 -0
- package/dist/tools/get-failure.js.map +1 -0
- package/dist/tools/inspect-page.d.ts +57 -0
- package/dist/tools/inspect-page.js +124 -0
- package/dist/tools/inspect-page.js.map +1 -0
- package/dist/tools/list-tests.d.ts +35 -0
- package/dist/tools/list-tests.js +88 -0
- package/dist/tools/list-tests.js.map +1 -0
- package/dist/tools/run-test.d.ts +70 -0
- package/dist/tools/run-test.js +169 -0
- package/dist/tools/run-test.js.map +1 -0
- package/dist/tools/shared.d.ts +86 -0
- package/dist/tools/shared.js +490 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/validate-selector.d.ts +32 -0
- package/dist/tools/validate-selector.js +93 -0
- package/dist/tools/validate-selector.js.map +1 -0
- package/dist/types/index.d.ts +344 -0
- package/dist/types/index.js +51 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/change-analyzer.d.ts +46 -0
- package/dist/utils/change-analyzer.js +290 -0
- package/dist/utils/change-analyzer.js.map +1 -0
- package/dist/utils/image-diff.d.ts +61 -0
- package/dist/utils/image-diff.js +373 -0
- package/dist/utils/image-diff.js.map +1 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.js +132 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/path-utils.d.ts +55 -0
- package/dist/utils/path-utils.js +211 -0
- package/dist/utils/path-utils.js.map +1 -0
- package/dist/utils/playwright-runner.d.ts +63 -0
- package/dist/utils/playwright-runner.js +594 -0
- package/dist/utils/playwright-runner.js.map +1 -0
- package/dist/utils/project-detector.d.ts +43 -0
- package/dist/utils/project-detector.js +255 -0
- package/dist/utils/project-detector.js.map +1 -0
- package/dist/utils/report-parser.d.ts +60 -0
- package/dist/utils/report-parser.js +501 -0
- package/dist/utils/report-parser.js.map +1 -0
- package/dist/utils/trace-reader.d.ts +109 -0
- package/dist/utils/trace-reader.js +608 -0
- package/dist/utils/trace-reader.js.map +1 -0
- package/examples/sample-test.spec.ts +49 -0
- package/package.json +66 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parsing of Playwright's JSON reporter output plus text diagnostics.
|
|
3
|
+
*
|
|
4
|
+
* The JSON report is the source of truth for pass/fail stats and
|
|
5
|
+
* failures; when the run dies before a report exists (timeout, crash,
|
|
6
|
+
* syntax error, full disk…) `diagnoseOutput` turns raw stdout/stderr
|
|
7
|
+
* into an ErrorKind + actionable hint.
|
|
8
|
+
*/
|
|
9
|
+
import { isAbsolutePath, isPathInside, normalizePath, relativeToRoot, resolvePath } from './path-utils.js';
|
|
10
|
+
/** Cap so one pathological run cannot produce a megabyte tool payload. */
|
|
11
|
+
const MAX_FAILURES = 25;
|
|
12
|
+
const ANSI_RE = /[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g;
|
|
13
|
+
/** Remove ANSI color/control sequences from captured output. */
|
|
14
|
+
export function stripAnsi(text) {
|
|
15
|
+
return text.replace(ANSI_RE, '');
|
|
16
|
+
}
|
|
17
|
+
export function emptyStats() {
|
|
18
|
+
return { expected: 0, unexpected: 0, flaky: 0, skipped: 0, duration: 0 };
|
|
19
|
+
}
|
|
20
|
+
function stringifyMaybe(value) {
|
|
21
|
+
if (value === undefined || value === null)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (typeof value === 'string')
|
|
24
|
+
return value;
|
|
25
|
+
try {
|
|
26
|
+
const json = JSON.stringify(value);
|
|
27
|
+
return json === undefined ? String(value) : json;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return String(value);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** JSON-report stdout entries are strings (or {text} chunks). */
|
|
34
|
+
function flattenOutput(entries) {
|
|
35
|
+
if (!entries || entries.length === 0)
|
|
36
|
+
return undefined;
|
|
37
|
+
const parts = [];
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
if (typeof entry === 'string')
|
|
40
|
+
parts.push(entry);
|
|
41
|
+
else if (entry && typeof entry === 'object' && 'text' in entry) {
|
|
42
|
+
const text = entry.text;
|
|
43
|
+
if (typeof text === 'string')
|
|
44
|
+
parts.push(text);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const joined = parts.join('\n').trim();
|
|
48
|
+
return joined === '' ? undefined : joined;
|
|
49
|
+
}
|
|
50
|
+
/** Locate the trace.zip attachment for a failed attempt, if any. */
|
|
51
|
+
function resolveTracePath(attachments, ctx) {
|
|
52
|
+
for (const attachment of attachments ?? []) {
|
|
53
|
+
const name = attachment.name ?? '';
|
|
54
|
+
const contentType = attachment.contentType ?? '';
|
|
55
|
+
const isTrace = name === 'trace' || name.endsWith('.zip') || contentType.includes('zip') || contentType.includes('trace');
|
|
56
|
+
if (!isTrace || !attachment.path)
|
|
57
|
+
continue;
|
|
58
|
+
const p = normalizePath(attachment.path);
|
|
59
|
+
if (isAbsolutePath(p))
|
|
60
|
+
return p;
|
|
61
|
+
const bases = [ctx.rootDir, ctx.root].filter((b) => Boolean(b));
|
|
62
|
+
for (const base of bases)
|
|
63
|
+
return resolvePath(base, p);
|
|
64
|
+
return p;
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
function mapStatus(status) {
|
|
69
|
+
switch (status) {
|
|
70
|
+
case 'passed':
|
|
71
|
+
return 'passed';
|
|
72
|
+
case 'failed':
|
|
73
|
+
return 'failed';
|
|
74
|
+
case 'timedOut':
|
|
75
|
+
return 'timedOut';
|
|
76
|
+
case 'skipped':
|
|
77
|
+
return 'skipped';
|
|
78
|
+
case 'interrupted':
|
|
79
|
+
return 'failed';
|
|
80
|
+
default:
|
|
81
|
+
return 'unknown';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Classify a failure from its message/stack plus normalized status. */
|
|
85
|
+
export function classifyFailure(text, status) {
|
|
86
|
+
const t = stripAnsi(text);
|
|
87
|
+
if (/SyntaxError|Unexpected token|Cannot find module|ERR_MODULE_NOT_FOUND/i.test(t))
|
|
88
|
+
return 'syntax';
|
|
89
|
+
if (/Invalid configuration|Unknown option|--project.*not found|No tests found/i.test(t))
|
|
90
|
+
return 'config';
|
|
91
|
+
if (/Target closed|browser has been closed|Target page, context or browser has been closed|Page crashed|Protocol error|browserType\.\w+:\s*Closed/i.test(t)) {
|
|
92
|
+
return 'browser-crash';
|
|
93
|
+
}
|
|
94
|
+
if (/ECONNREFUSED|ERR_CONNECTION_REFUSED|ERR_CONNECTION_RESET|ERR_NAME_NOT_RESOLVED|getaddrinfo ENOTFOUND|Process from config\.webServer|webServer/i.test(t)) {
|
|
95
|
+
return 'server-unreachable';
|
|
96
|
+
}
|
|
97
|
+
if (status === 'timedOut' || /timeout\s+\d+\s*m?s?\s*exceeded|timed out after|test timed out/i.test(t)) {
|
|
98
|
+
return 'timeout';
|
|
99
|
+
}
|
|
100
|
+
if (/expect\(|Expected:|Received:|toEqual|toBe\(|assertion failed|locator\./i.test(t)) {
|
|
101
|
+
return 'assertion';
|
|
102
|
+
}
|
|
103
|
+
return 'unknown';
|
|
104
|
+
}
|
|
105
|
+
function normalizeSpecFile(file, ctx) {
|
|
106
|
+
if (!file)
|
|
107
|
+
return '';
|
|
108
|
+
const normalized = normalizePath(file);
|
|
109
|
+
// Playwright addresses spec files relative to config.rootDir (the
|
|
110
|
+
// testDir), while every consumer here — run-test, diagnose-flaky,
|
|
111
|
+
// get-failure's next steps, list-tests — needs paths relative to the
|
|
112
|
+
// project root. Rebase: relative → resolve against rootDir, absolute →
|
|
113
|
+
// keep; then relativize against the project root when it is inside.
|
|
114
|
+
const absolute = isAbsolutePath(normalized)
|
|
115
|
+
? normalized
|
|
116
|
+
: resolvePath(ctx.rootDir ?? ctx.root, normalized);
|
|
117
|
+
if (isPathInside(absolute, ctx.root))
|
|
118
|
+
return relativeToRoot(ctx.root, absolute);
|
|
119
|
+
return normalized;
|
|
120
|
+
}
|
|
121
|
+
function walkSpec(spec, prefix, ctx) {
|
|
122
|
+
const titlePath = spec.title ? [...prefix, spec.title] : [...prefix];
|
|
123
|
+
if (titlePath.length === 0)
|
|
124
|
+
return;
|
|
125
|
+
const file = normalizeSpecFile(spec.file, ctx);
|
|
126
|
+
const line = spec.line;
|
|
127
|
+
const cases = spec.tests ?? [];
|
|
128
|
+
if (cases.length === 0) {
|
|
129
|
+
ctx.records.push({ titlePath, file, line, projects: [], outcomes: [] });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
for (const testCase of cases) {
|
|
133
|
+
const project = testCase.projectName;
|
|
134
|
+
if (project)
|
|
135
|
+
ctx.projectsSeen.add(project);
|
|
136
|
+
const results = testCase.results ?? [];
|
|
137
|
+
let outcome;
|
|
138
|
+
if (results.length === 0) {
|
|
139
|
+
outcome = { project, status: mapStatus(testCase.status) };
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const last = results[results.length - 1];
|
|
143
|
+
let status = mapStatus(last.status);
|
|
144
|
+
if (status === 'passed' && results.length > 1) {
|
|
145
|
+
const earlierFailed = results
|
|
146
|
+
.slice(0, -1)
|
|
147
|
+
.some((r) => mapStatus(r.status) === 'failed' || mapStatus(r.status) === 'timedOut');
|
|
148
|
+
if (earlierFailed)
|
|
149
|
+
status = 'flaky';
|
|
150
|
+
}
|
|
151
|
+
outcome = {
|
|
152
|
+
project,
|
|
153
|
+
status,
|
|
154
|
+
retry: last.retry,
|
|
155
|
+
error: last.error ?? last.errors?.[0],
|
|
156
|
+
durationMs: last.duration,
|
|
157
|
+
attachments: last.attachments,
|
|
158
|
+
stdout: flattenOutput(last.stdout),
|
|
159
|
+
};
|
|
160
|
+
if (typeof last.duration === 'number')
|
|
161
|
+
ctx.totalDuration += last.duration;
|
|
162
|
+
}
|
|
163
|
+
ctx.records.push({ titlePath, file, line, projects: project ? [project] : [], outcomes: [outcome] });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function walkSuite(suite, prefix, ctx) {
|
|
167
|
+
const titlePath = suite.title ? [...prefix, suite.title] : [...prefix];
|
|
168
|
+
for (const spec of suite.specs ?? [])
|
|
169
|
+
walkSpec(spec, titlePath, ctx);
|
|
170
|
+
for (const child of suite.suites ?? [])
|
|
171
|
+
walkSuite(child, titlePath, ctx);
|
|
172
|
+
}
|
|
173
|
+
function computeStats(records, duration) {
|
|
174
|
+
const stats = emptyStats();
|
|
175
|
+
stats.duration = duration;
|
|
176
|
+
for (const record of records) {
|
|
177
|
+
for (const outcome of record.outcomes) {
|
|
178
|
+
switch (outcome.status) {
|
|
179
|
+
case 'passed':
|
|
180
|
+
stats.expected += 1;
|
|
181
|
+
break;
|
|
182
|
+
case 'flaky':
|
|
183
|
+
stats.flaky += 1;
|
|
184
|
+
break;
|
|
185
|
+
case 'failed':
|
|
186
|
+
case 'timedOut':
|
|
187
|
+
stats.unexpected += 1;
|
|
188
|
+
break;
|
|
189
|
+
case 'skipped':
|
|
190
|
+
stats.skipped += 1;
|
|
191
|
+
break;
|
|
192
|
+
default:
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return stats;
|
|
198
|
+
}
|
|
199
|
+
function mergeStats(reported, computed) {
|
|
200
|
+
const num = (value, fallback) => typeof value === 'number' && Number.isFinite(value) ? value : fallback;
|
|
201
|
+
return {
|
|
202
|
+
expected: num(reported?.expected, computed.expected),
|
|
203
|
+
unexpected: num(reported?.unexpected, computed.unexpected),
|
|
204
|
+
flaky: num(reported?.flaky, computed.flaky),
|
|
205
|
+
skipped: num(reported?.skipped, computed.skipped),
|
|
206
|
+
duration: num(reported?.duration, computed.duration),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/* ------------------------------------------------------------------ */
|
|
210
|
+
/* Public API */
|
|
211
|
+
/* ------------------------------------------------------------------ */
|
|
212
|
+
/** Parse a JSON report from a raw string. Never throws. */
|
|
213
|
+
export function parseReportJson(raw, root = '', maxFailures = MAX_FAILURES) {
|
|
214
|
+
let parsed;
|
|
215
|
+
try {
|
|
216
|
+
parsed = JSON.parse(raw);
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
return {
|
|
220
|
+
stats: null,
|
|
221
|
+
failures: [],
|
|
222
|
+
failuresTruncated: false,
|
|
223
|
+
tests: [],
|
|
224
|
+
specCount: 0,
|
|
225
|
+
projects: [],
|
|
226
|
+
configPath: null,
|
|
227
|
+
parseError: `Playwright JSON report could not be parsed: ${err instanceof Error ? err.message : String(err)}`,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return parseReport(parsed, root, maxFailures);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Parse an already-deserialized Playwright JSON report into normalized
|
|
234
|
+
* stats, failures, and a flat test listing.
|
|
235
|
+
*/
|
|
236
|
+
export function parseReport(report, root = '', maxFailures = MAX_FAILURES) {
|
|
237
|
+
const base = {
|
|
238
|
+
stats: null,
|
|
239
|
+
failures: [],
|
|
240
|
+
failuresTruncated: false,
|
|
241
|
+
tests: [],
|
|
242
|
+
specCount: 0,
|
|
243
|
+
projects: [],
|
|
244
|
+
configPath: null,
|
|
245
|
+
};
|
|
246
|
+
if (report === null || typeof report !== 'object' || Array.isArray(report)) {
|
|
247
|
+
return { ...base, parseError: 'Playwright report was not a JSON object.' };
|
|
248
|
+
}
|
|
249
|
+
const typed = report;
|
|
250
|
+
const hasSuites = Array.isArray(typed.suites);
|
|
251
|
+
const hasErrors = Array.isArray(typed.errors);
|
|
252
|
+
const hasStats = typed.stats !== undefined && typed.stats !== null;
|
|
253
|
+
if (!hasSuites && !hasErrors && !hasStats) {
|
|
254
|
+
return { ...base, parseError: 'Playwright report contained no suites, errors, or stats.' };
|
|
255
|
+
}
|
|
256
|
+
const ctx = {
|
|
257
|
+
root: normalizePath(root || '.'),
|
|
258
|
+
rootDir: typeof typed.config?.rootDir === 'string' ? normalizePath(typed.config.rootDir) : null,
|
|
259
|
+
records: [],
|
|
260
|
+
totalDuration: 0,
|
|
261
|
+
projectsSeen: new Set(),
|
|
262
|
+
};
|
|
263
|
+
for (const suite of typed.suites ?? [])
|
|
264
|
+
walkSuite(suite, [], ctx);
|
|
265
|
+
const computed = computeStats(ctx.records, ctx.totalDuration);
|
|
266
|
+
const stats = mergeStats(typed.stats, computed);
|
|
267
|
+
const configPath = typed.config?.configFile
|
|
268
|
+
? normalizeSpecFile(typed.config.configFile, ctx) || null
|
|
269
|
+
: null;
|
|
270
|
+
const failing = [];
|
|
271
|
+
for (const record of ctx.records) {
|
|
272
|
+
for (const outcome of record.outcomes) {
|
|
273
|
+
if (outcome.status === 'failed' || outcome.status === 'timedOut') {
|
|
274
|
+
failing.push({ record, outcome });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const failures = [];
|
|
279
|
+
for (const { record, outcome } of failing.slice(0, maxFailures)) {
|
|
280
|
+
const err = outcome.error;
|
|
281
|
+
const message = stripAnsi(err?.message ?? '').trim() ||
|
|
282
|
+
(outcome.status === 'timedOut' ? 'Test timed out.' : 'Test failed.');
|
|
283
|
+
const stack = stripAnsi(err?.stack ?? '').trim() || undefined;
|
|
284
|
+
const failureKind = classifyFailure(`${message}\n${stack ?? ''}`, outcome.status);
|
|
285
|
+
failures.push({
|
|
286
|
+
file: record.file,
|
|
287
|
+
line: record.line,
|
|
288
|
+
title: record.titlePath.join(' › '),
|
|
289
|
+
project: outcome.project,
|
|
290
|
+
status: outcome.status,
|
|
291
|
+
failureKind,
|
|
292
|
+
retry: outcome.retry,
|
|
293
|
+
message,
|
|
294
|
+
stack,
|
|
295
|
+
codeframe: err?.codeframe ? stripAnsi(err.codeframe) : undefined,
|
|
296
|
+
expected: stringifyMaybe(err?.expected),
|
|
297
|
+
actual: stringifyMaybe(err?.actual),
|
|
298
|
+
durationMs: outcome.durationMs,
|
|
299
|
+
tracePath: resolveTracePath(outcome.attachments, ctx),
|
|
300
|
+
stdout: outcome.stdout,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
let failuresTruncated = failing.length > maxFailures;
|
|
304
|
+
let topLevelFailures = 0;
|
|
305
|
+
// Top-level errors (bad config, "no tests found", …) when no per-test
|
|
306
|
+
// failures were produced.
|
|
307
|
+
if (failures.length === 0 && (typed.errors?.length ?? 0) > 0) {
|
|
308
|
+
for (const err of (typed.errors ?? []).slice(0, maxFailures)) {
|
|
309
|
+
topLevelFailures += 1;
|
|
310
|
+
const message = stripAnsi(err?.message ?? '').trim() || 'Unknown top-level error.';
|
|
311
|
+
failures.push({
|
|
312
|
+
file: configPath ?? '',
|
|
313
|
+
line: err.location?.line,
|
|
314
|
+
title: 'configuration',
|
|
315
|
+
status: 'failed',
|
|
316
|
+
failureKind: classifyFailure(message, 'failed'),
|
|
317
|
+
message,
|
|
318
|
+
stack: stripAnsi(err?.stack ?? '').trim() || undefined,
|
|
319
|
+
codeframe: err?.codeframe ? stripAnsi(err.codeframe) : undefined,
|
|
320
|
+
expected: stringifyMaybe(err?.expected),
|
|
321
|
+
actual: stringifyMaybe(err?.actual),
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const tests = ctx.records.map((record) => ({
|
|
326
|
+
file: record.file,
|
|
327
|
+
title: record.titlePath.join(' › '),
|
|
328
|
+
line: record.line,
|
|
329
|
+
projects: record.projects.length > 0 ? record.projects : undefined,
|
|
330
|
+
}));
|
|
331
|
+
for (const project of typed.config?.projects ?? []) {
|
|
332
|
+
if (project?.name)
|
|
333
|
+
ctx.projectsSeen.add(project.name);
|
|
334
|
+
}
|
|
335
|
+
const totalTestCases = ctx.records.reduce((sum, record) => {
|
|
336
|
+
return sum + (record.outcomes.length > 0 ? record.outcomes.length : 1);
|
|
337
|
+
}, 0);
|
|
338
|
+
failuresTruncated = failuresTruncated || (typed.errors?.length ?? 0) > maxFailures;
|
|
339
|
+
if (topLevelFailures > 0)
|
|
340
|
+
stats.unexpected += topLevelFailures;
|
|
341
|
+
return {
|
|
342
|
+
stats,
|
|
343
|
+
failures,
|
|
344
|
+
failuresTruncated,
|
|
345
|
+
tests,
|
|
346
|
+
specCount: totalTestCases,
|
|
347
|
+
projects: [...ctx.projectsSeen],
|
|
348
|
+
configPath,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Best-effort extraction of a JSON object from mixed text (stdout that
|
|
353
|
+
* interleaves logs with the JSON reporter output).
|
|
354
|
+
*/
|
|
355
|
+
export function extractJsonFromText(text) {
|
|
356
|
+
const start = text.indexOf('{');
|
|
357
|
+
if (start < 0)
|
|
358
|
+
return null;
|
|
359
|
+
let end = text.lastIndexOf('}');
|
|
360
|
+
let attempts = 0;
|
|
361
|
+
while (end > start && attempts < 6) {
|
|
362
|
+
const candidate = text.slice(start, end + 1);
|
|
363
|
+
try {
|
|
364
|
+
JSON.parse(candidate);
|
|
365
|
+
return candidate;
|
|
366
|
+
}
|
|
367
|
+
catch {
|
|
368
|
+
end = text.lastIndexOf('}', end - 1);
|
|
369
|
+
attempts += 1;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
/** First line that looks like an actual error, else first content line. */
|
|
375
|
+
export function firstMeaningfulLine(text) {
|
|
376
|
+
const lines = stripAnsi(text)
|
|
377
|
+
.split(/\r?\n/)
|
|
378
|
+
.map((line) => line.trim())
|
|
379
|
+
.filter((line) => line !== '' && !/^(at |[-+]{3}|>)/.test(line));
|
|
380
|
+
const clip = (line) => (line.length > 400 ? `${line.slice(0, 400)}…` : line);
|
|
381
|
+
const errorLine = lines.find((line) => /error|exception|refused|not found|failed|timed out|timeout|enospc|enotfound|invalid|unexpected/i.test(line));
|
|
382
|
+
if (errorLine)
|
|
383
|
+
return clip(errorLine);
|
|
384
|
+
return lines.length > 0 ? clip(lines[0]) : undefined;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Turn raw process output into an ErrorKind + hint when no structured
|
|
388
|
+
* report exists. Returns null when nothing recognizable was found.
|
|
389
|
+
*/
|
|
390
|
+
export function diagnoseOutput(text) {
|
|
391
|
+
const t = stripAnsi(text);
|
|
392
|
+
if (t.trim() === '')
|
|
393
|
+
return null;
|
|
394
|
+
const first = firstMeaningfulLine(t) ?? 'Unknown error';
|
|
395
|
+
if (/ENOSPC|no space left on device|disk (is )?full|not enough space/i.test(t)) {
|
|
396
|
+
return {
|
|
397
|
+
errorKind: 'DISK_FULL',
|
|
398
|
+
errorMessage: first,
|
|
399
|
+
hint: 'The disk is full (or the report directory is not writable). Free up space and retry — traces/reports could not be written.',
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
if (/Executable doesn't exist|Please run the following command to install new browsers|browserType\.\w+:\s*Executable doesn't exist/i.test(t)) {
|
|
403
|
+
return {
|
|
404
|
+
errorKind: 'NO_PLAYWRIGHT',
|
|
405
|
+
errorMessage: first,
|
|
406
|
+
hint: 'Playwright browsers are not installed for this project. Run: npx playwright install chromium',
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
const syntax = /SyntaxError:([^\n]*)/.exec(t);
|
|
410
|
+
if (syntax) {
|
|
411
|
+
const loc = /at [^\n]*?((?:[A-Za-z]:)?[\w./\\-]+\.[cm]?[jt]sx?):(\d+)/.exec(t);
|
|
412
|
+
const where = loc ? ` (${loc[1]}:${loc[2]})` : '';
|
|
413
|
+
return {
|
|
414
|
+
errorKind: 'SYNTAX_ERROR',
|
|
415
|
+
errorMessage: `SyntaxError: ${syntax[1].trim()}${where}`,
|
|
416
|
+
hint: 'A test or config file has a syntax error. Fix it and re-run; the stack trace above points at the file and line.',
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
const cannotFindModule = /Cannot find module([^\n]*)/.exec(t);
|
|
420
|
+
if (cannotFindModule) {
|
|
421
|
+
return {
|
|
422
|
+
errorKind: 'SYNTAX_ERROR',
|
|
423
|
+
errorMessage: `Cannot find module${cannotFindModule[1].trim()}`,
|
|
424
|
+
hint: 'A required module is missing. Check import paths and run npm install (or the equivalent for your package manager).',
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (/ECONNREFUSED|ERR_CONNECTION_REFUSED|ERR_CONNECTION_RESET|ERR_NAME_NOT_RESOLVED|getaddrinfo ENOTFOUND|Process from config\.webServer|webServer|did not start/i.test(t)) {
|
|
428
|
+
return {
|
|
429
|
+
errorKind: 'SERVER_NOT_RUNNING',
|
|
430
|
+
errorMessage: first,
|
|
431
|
+
hint: 'Your app (dev server) does not appear to be reachable. Start it in another terminal (e.g. npm run dev / npm start), keep it running, then retry — or configure `webServer` in playwright.config.* so Playwright starts it automatically.',
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
if (/Target closed|browser has been closed|Target page, context or browser has been closed|Page crashed|Protocol error.*Target/i.test(t)) {
|
|
435
|
+
return {
|
|
436
|
+
errorKind: 'BROWSER_CRASH',
|
|
437
|
+
errorMessage: first,
|
|
438
|
+
hint: 'The browser process crashed or was closed unexpectedly. Retry the run; if it keeps happening run `npx playwright install --force` and make sure no other automation browser holds the profile.',
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
if (/timeout\s+\d+\s*m?s?\s*exceeded|timed out after|test timed out/i.test(t)) {
|
|
442
|
+
return {
|
|
443
|
+
errorKind: 'TIMEOUT',
|
|
444
|
+
errorMessage: first,
|
|
445
|
+
hint: 'The operation exceeded its timeout. Raise the timeout (timeoutMs on this tool, or test.setTimeout() in the spec) or investigate why the app/test hangs.',
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
/* ------------------------------------------------------------------ */
|
|
451
|
+
/* Config / test-file helpers */
|
|
452
|
+
/* ------------------------------------------------------------------ */
|
|
453
|
+
/** Extract `name: '…'` values from a playwright.config source. */
|
|
454
|
+
export function parseProjectNames(source) {
|
|
455
|
+
const names = new Set();
|
|
456
|
+
const re = /\bname\s*:\s*(['"])([^'"]{1,64})\1/g;
|
|
457
|
+
let match;
|
|
458
|
+
while ((match = re.exec(source)) !== null) {
|
|
459
|
+
names.add(match[2]);
|
|
460
|
+
}
|
|
461
|
+
return [...names];
|
|
462
|
+
}
|
|
463
|
+
const CALL_RE = /(?<![\w$.])test\s*(?:\.\s*(describe(?:\s*\.\s*(?:only|serial|parallel|each))?|only|skip|fixme|fail))?\s*\(\s*(['"`])((?:\\.|(?!\2)[^\\\n])*)\2/g;
|
|
464
|
+
/**
|
|
465
|
+
* Regex-based extraction of `test(...)` / `test.describe(...)` titles
|
|
466
|
+
* from a spec file. Used only as a fallback when Playwright itself
|
|
467
|
+
* cannot list tests (not installed, config broken, syntax error).
|
|
468
|
+
*/
|
|
469
|
+
export function extractTestTitles(source) {
|
|
470
|
+
const out = [];
|
|
471
|
+
const stack = [];
|
|
472
|
+
const lines = source.split(/\r?\n/);
|
|
473
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
474
|
+
const line = lines[i];
|
|
475
|
+
const indent = line.length - line.trimStart().length;
|
|
476
|
+
CALL_RE.lastIndex = 0;
|
|
477
|
+
let match;
|
|
478
|
+
while ((match = CALL_RE.exec(line)) !== null) {
|
|
479
|
+
const kind = match[1];
|
|
480
|
+
const title = match[3].replace(/\\(['"`])/g, '$1');
|
|
481
|
+
if (title === '')
|
|
482
|
+
continue;
|
|
483
|
+
if (kind !== undefined && kind.startsWith('describe')) {
|
|
484
|
+
stack.push({ title, indent });
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
// Plain test(), plus test.only / test.skip / test.fixme / test.fail.
|
|
488
|
+
const path = [...stack.map((entry) => entry.title), title].join(' › ');
|
|
489
|
+
out.push({ title: path, line: i + 1 });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Pop describes whose block ends on this line: `});` / `}`.
|
|
493
|
+
if (/^\s*[)}\]]+;?\s*$/.test(line)) {
|
|
494
|
+
while (stack.length > 0 && stack[stack.length - 1].indent >= indent) {
|
|
495
|
+
stack.pop();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return out;
|
|
500
|
+
}
|
|
501
|
+
//# sourceMappingURL=report-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-parser.js","sourceRoot":"","sources":["../../src/utils/report-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playwright trace reader.
|
|
3
|
+
*
|
|
4
|
+
* `get-failure` uses this to deliver the "magic" context from the
|
|
5
|
+
* blueprint: the exact error, the action that failed, the action log
|
|
6
|
+
* leading up to it, the DOM snapshot Playwright captured around the
|
|
7
|
+
* failure, and (when present) the `error-context` accessibility-tree
|
|
8
|
+
* attachment Playwright writes for failed expectations.
|
|
9
|
+
*
|
|
10
|
+
* trace.zip is a plain ZIP archive (deflate or stored) containing
|
|
11
|
+
* `*.trace` JSON-lines event logs plus resources (snapshots,
|
|
12
|
+
* screencasts, attachments). Real schema (Playwright 1.63, trace v9):
|
|
13
|
+
*
|
|
14
|
+
* {"type":"before","callId":"pw:api@43","class":"Test","method":"pw:api",
|
|
15
|
+
* "title":"Navigate","params":{"url":"/"},"startTime":955.76}
|
|
16
|
+
* {"type":"after","callId":"pw:api@43","endTime":1005.7,
|
|
17
|
+
* "error":{"message":"page.goto: net::ERR_CONNECTION_REFUSED …"}}
|
|
18
|
+
* {"type":"frame-snapshot","callId":"call@11","phase":"before",
|
|
19
|
+
* "snapshot":{"html":["HTML",{},["BODY",{},[…]]]}}
|
|
20
|
+
* {"type":"error","message":"…"} // standalone error event
|
|
21
|
+
*
|
|
22
|
+
* Legacy synthetic fields (`api`, string `snapshot` hashes, `error`
|
|
23
|
+
* directly) are also supported. Everything is parsed with Node
|
|
24
|
+
* built-ins — no dependencies.
|
|
25
|
+
*/
|
|
26
|
+
export interface TraceActionLogEntry {
|
|
27
|
+
api: string;
|
|
28
|
+
summary: string;
|
|
29
|
+
failed: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** A request that failed (4xx/5xx, transport error, or no response). */
|
|
32
|
+
export interface TraceFailedRequest {
|
|
33
|
+
method: string;
|
|
34
|
+
url: string;
|
|
35
|
+
/** HTTP status; undefined when the request never completed. */
|
|
36
|
+
status?: number;
|
|
37
|
+
statusText?: string;
|
|
38
|
+
/** Playwright resource type (document, fetch, xhr, script, …). */
|
|
39
|
+
resourceType?: string;
|
|
40
|
+
/** Transport-level error text, when Playwright recorded one. */
|
|
41
|
+
errorText?: string;
|
|
42
|
+
}
|
|
43
|
+
/** A console error/warning the page logged before the failure. */
|
|
44
|
+
export interface TraceConsoleMessage {
|
|
45
|
+
type: 'error' | 'warning';
|
|
46
|
+
text: string;
|
|
47
|
+
/** `url:line` of the log call, when known. */
|
|
48
|
+
location?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface FailureTraceContext {
|
|
51
|
+
/** Error message recorded in the trace (or best-effort text). */
|
|
52
|
+
error: string;
|
|
53
|
+
/** The action that was in flight when the error happened. */
|
|
54
|
+
action?: {
|
|
55
|
+
api: string;
|
|
56
|
+
selector?: string;
|
|
57
|
+
params?: string;
|
|
58
|
+
};
|
|
59
|
+
/** Timestamp of the failure relative to trace start (ms), if known. */
|
|
60
|
+
atMs?: number;
|
|
61
|
+
/** Raw DOM snapshot from the trace (already capped). */
|
|
62
|
+
snapshotHtml?: string;
|
|
63
|
+
snapshotTruncated?: boolean;
|
|
64
|
+
/** Window of HTML around the failing element, when locatable. */
|
|
65
|
+
snippet?: string;
|
|
66
|
+
/** Playwright's `error-context` attachment (accessibility tree at failure). */
|
|
67
|
+
errorContext?: string;
|
|
68
|
+
/** Recent actions before the failure, oldest first. */
|
|
69
|
+
actionLog: TraceActionLogEntry[];
|
|
70
|
+
/** Requests that failed (4xx/5xx/no-response) during the test. */
|
|
71
|
+
failedRequests: TraceFailedRequest[];
|
|
72
|
+
/** Total completed requests observed in the trace (context for the cap). */
|
|
73
|
+
networkTotal: number;
|
|
74
|
+
/** Console errors/warnings logged before the failure, oldest first. */
|
|
75
|
+
consoleMessages: TraceConsoleMessage[];
|
|
76
|
+
/** Non-fatal parsing issues (missing snapshot, unknown format…). */
|
|
77
|
+
warnings: string[];
|
|
78
|
+
}
|
|
79
|
+
/** Read a ZIP archive into a name → raw bytes map (built-ins only). */
|
|
80
|
+
export declare function readZipEntries(buf: Buffer): Map<string, Buffer>;
|
|
81
|
+
/**
|
|
82
|
+
* Playwright serializes DOM snapshots as tagged arrays:
|
|
83
|
+
* ["HTML", {"attr": "v"}, ["BODY", {}, ["hello"]]]
|
|
84
|
+
* Render them back to inspectable HTML.
|
|
85
|
+
*/
|
|
86
|
+
export declare function serializeDomTree(node: unknown, depth?: number): string | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Parse merged `.trace` JSON-lines into a structured failure context.
|
|
89
|
+
* Exported for unit tests with synthetic event streams.
|
|
90
|
+
*/
|
|
91
|
+
export declare function analyzeTraceEvents(lines: string | string[], snapshotLoader: (hash: string) => string | undefined, fileLoader?: (name: string) => string | undefined): FailureTraceContext;
|
|
92
|
+
/**
|
|
93
|
+
* Parse a Playwright `*.network` JSON-lines entry (HAR-style
|
|
94
|
+
* `resource-snapshot` events) and return the requests that failed
|
|
95
|
+
* (status >= 400, status 0, transport error, or no response at all)
|
|
96
|
+
* plus the total number of completed requests observed.
|
|
97
|
+
* Exported for unit tests.
|
|
98
|
+
*/
|
|
99
|
+
export declare function parseNetworkLog(text: string): {
|
|
100
|
+
failed: TraceFailedRequest[];
|
|
101
|
+
total: number;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Read a trace.zip produced by Playwright and extract the failure
|
|
105
|
+
* context: error, failed action, action log, DOM snapshot and the
|
|
106
|
+
* error-context attachment. Returns null when the file is
|
|
107
|
+
* missing/unreadable — callers degrade to a hint instead of failing.
|
|
108
|
+
*/
|
|
109
|
+
export declare function readFailureTrace(tracePath: string): Promise<FailureTraceContext | null>;
|