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,608 @@
|
|
|
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
|
+
import { readFile } from 'node:fs/promises';
|
|
27
|
+
import { gunzipSync, inflateRawSync } from 'node:zlib';
|
|
28
|
+
import { normalizePath } from './path-utils.js';
|
|
29
|
+
/** Cap so one huge trace cannot blow up the tool payload. */
|
|
30
|
+
const MAX_HTML_CHARS = 12_000;
|
|
31
|
+
const MAX_CONTEXT_CHARS = 6_000;
|
|
32
|
+
const MAX_ACTION_LOG = 12;
|
|
33
|
+
const MAX_SNIPPET_RADIUS = 900;
|
|
34
|
+
const MAX_FAILED_REQUESTS = 8;
|
|
35
|
+
const MAX_CONSOLE_MESSAGES = 10;
|
|
36
|
+
/** Hooks/fixtures are noise in the action log. */
|
|
37
|
+
const NOISE_METHODS = new Set(['hook', 'fixture']);
|
|
38
|
+
function findEocd(buf) {
|
|
39
|
+
const min = Math.max(0, buf.length - 0xffff - 22);
|
|
40
|
+
for (let i = buf.length - 22; i >= min; i -= 1) {
|
|
41
|
+
if (buf.readUInt32LE(i) === 0x06054b50)
|
|
42
|
+
return i;
|
|
43
|
+
}
|
|
44
|
+
return -1;
|
|
45
|
+
}
|
|
46
|
+
/** Read a ZIP archive into a name → raw bytes map (built-ins only). */
|
|
47
|
+
export function readZipEntries(buf) {
|
|
48
|
+
const out = new Map();
|
|
49
|
+
const eocd = findEocd(buf);
|
|
50
|
+
if (eocd < 0)
|
|
51
|
+
throw new Error('Not a ZIP archive (no end-of-central-directory record)');
|
|
52
|
+
const entryCount = buf.readUInt16LE(eocd + 10);
|
|
53
|
+
let offset = buf.readUInt32LE(eocd + 16);
|
|
54
|
+
const central = [];
|
|
55
|
+
for (let i = 0; i < entryCount && i < 50_000; i += 1) {
|
|
56
|
+
if (offset + 46 > buf.length || buf.readUInt32LE(offset) !== 0x02014b50)
|
|
57
|
+
break;
|
|
58
|
+
const compressionMethod = buf.readUInt16LE(offset + 10);
|
|
59
|
+
const compressedSize = buf.readUInt32LE(offset + 20);
|
|
60
|
+
const localHeaderOffset = buf.readUInt32LE(offset + 42);
|
|
61
|
+
const nameLength = buf.readUInt16LE(offset + 28);
|
|
62
|
+
const extraLength = buf.readUInt16LE(offset + 30);
|
|
63
|
+
const commentLength = buf.readUInt16LE(offset + 32);
|
|
64
|
+
const name = buf.toString('utf8', offset + 46, offset + 46 + nameLength);
|
|
65
|
+
central.push([name, { compressionMethod, compressedSize, localHeaderOffset }]);
|
|
66
|
+
offset += 46 + nameLength + extraLength + commentLength;
|
|
67
|
+
}
|
|
68
|
+
for (const [name, entry] of central) {
|
|
69
|
+
const lh = entry.localHeaderOffset;
|
|
70
|
+
if (lh + 30 > buf.length || buf.readUInt32LE(lh) !== 0x04034b50)
|
|
71
|
+
continue;
|
|
72
|
+
const nameLength = buf.readUInt16LE(lh + 26);
|
|
73
|
+
const extraLength = buf.readUInt16LE(lh + 28);
|
|
74
|
+
const start = lh + 30 + nameLength + extraLength;
|
|
75
|
+
const end = start + entry.compressedSize;
|
|
76
|
+
if (end > buf.length)
|
|
77
|
+
continue;
|
|
78
|
+
const raw = buf.subarray(start, end);
|
|
79
|
+
try {
|
|
80
|
+
if (entry.compressionMethod === 0)
|
|
81
|
+
out.set(name, Buffer.from(raw));
|
|
82
|
+
else if (entry.compressionMethod === 8)
|
|
83
|
+
out.set(name, inflateRawSync(raw));
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Skip unreadable entry; callers surface missing snapshots as warnings.
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
function escapeHtml(text) {
|
|
92
|
+
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Playwright serializes DOM snapshots as tagged arrays:
|
|
96
|
+
* ["HTML", {"attr": "v"}, ["BODY", {}, ["hello"]]]
|
|
97
|
+
* Render them back to inspectable HTML.
|
|
98
|
+
*/
|
|
99
|
+
export function serializeDomTree(node, depth = 0) {
|
|
100
|
+
if (depth > 200)
|
|
101
|
+
return undefined;
|
|
102
|
+
if (typeof node === 'string')
|
|
103
|
+
return escapeHtml(node);
|
|
104
|
+
if (!Array.isArray(node) || node.length === 0)
|
|
105
|
+
return undefined;
|
|
106
|
+
const tag = node[0];
|
|
107
|
+
if (typeof tag !== 'string')
|
|
108
|
+
return undefined;
|
|
109
|
+
if (tag.startsWith('#')) {
|
|
110
|
+
// Text/comment nodes carry their content in [1] or as siblings.
|
|
111
|
+
const text = node[1];
|
|
112
|
+
return typeof text === 'string' ? escapeHtml(text) : '';
|
|
113
|
+
}
|
|
114
|
+
const attrs = node[1] && typeof node[1] === 'object' && !Array.isArray(node[1]) ? node[1] : {};
|
|
115
|
+
const children = node.slice(Array.isArray(node[1]) || typeof node[1] !== 'object' || node[1] === null ? 1 : 2);
|
|
116
|
+
let attrText = '';
|
|
117
|
+
for (const [name, value] of Object.entries(attrs)) {
|
|
118
|
+
if (name.startsWith('#') || value === undefined || value === null)
|
|
119
|
+
continue;
|
|
120
|
+
const rendered = typeof value === 'string' ? value : String(value);
|
|
121
|
+
attrText += ` ${name}="${escapeHtml(rendered)}"`;
|
|
122
|
+
}
|
|
123
|
+
const inner = children
|
|
124
|
+
.map((child) => serializeDomTree(child, depth + 1) ?? '')
|
|
125
|
+
.join('');
|
|
126
|
+
return `<${tag.toLowerCase()}${attrText}>${inner}</${tag.toLowerCase()}>`;
|
|
127
|
+
}
|
|
128
|
+
function errorMessage(error) {
|
|
129
|
+
if (error === undefined || error === null)
|
|
130
|
+
return undefined;
|
|
131
|
+
if (typeof error === 'string')
|
|
132
|
+
return error;
|
|
133
|
+
if (typeof error === 'object') {
|
|
134
|
+
const message = error.message;
|
|
135
|
+
if (typeof message === 'string' && message.trim() !== '')
|
|
136
|
+
return message;
|
|
137
|
+
try {
|
|
138
|
+
return JSON.stringify(error);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return String(error);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return String(error);
|
|
145
|
+
}
|
|
146
|
+
/** Error carried by an event: `error` field, or standalone type:'error'. */
|
|
147
|
+
function eventError(event) {
|
|
148
|
+
if (event.error !== undefined)
|
|
149
|
+
return errorMessage(event.error);
|
|
150
|
+
if (event.type === 'error' && typeof event.message === 'string' && event.message.trim() !== '') {
|
|
151
|
+
return event.message;
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
function summarizeParams(params) {
|
|
156
|
+
if (!params)
|
|
157
|
+
return { summary: '' };
|
|
158
|
+
const parts = [];
|
|
159
|
+
let selector;
|
|
160
|
+
for (const [key, value] of Object.entries(params)) {
|
|
161
|
+
if (key === 'element' || key === 'stack')
|
|
162
|
+
continue;
|
|
163
|
+
let text;
|
|
164
|
+
if (typeof value === 'string')
|
|
165
|
+
text = value;
|
|
166
|
+
else if (typeof value === 'number' || typeof value === 'boolean')
|
|
167
|
+
text = String(value);
|
|
168
|
+
else if (value && typeof value === 'object') {
|
|
169
|
+
const inner = value;
|
|
170
|
+
if (typeof inner.selector === 'string')
|
|
171
|
+
text = inner.selector;
|
|
172
|
+
else
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (text === undefined)
|
|
176
|
+
continue;
|
|
177
|
+
if (key === 'selector')
|
|
178
|
+
selector = text;
|
|
179
|
+
if (parts.length < 3) {
|
|
180
|
+
parts.push(`${key}=${text.length > 60 ? `${text.slice(0, 60)}…` : text}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { summary: parts.join(' '), selector };
|
|
184
|
+
}
|
|
185
|
+
function actionInfo(event) {
|
|
186
|
+
if (typeof event.api === 'string') {
|
|
187
|
+
const { summary, selector } = summarizeParams(event.params);
|
|
188
|
+
return { api: event.api, summary, selector, startTime: event.startTime, callId: event.callId };
|
|
189
|
+
}
|
|
190
|
+
if (event.type !== 'before')
|
|
191
|
+
return undefined;
|
|
192
|
+
if (typeof event.method === 'string' && NOISE_METHODS.has(event.method))
|
|
193
|
+
return undefined;
|
|
194
|
+
const { summary, selector } = summarizeParams(event.params);
|
|
195
|
+
const api = (typeof event.title === 'string' && event.title !== '' ? event.title : undefined) ??
|
|
196
|
+
[event.class, event.method].filter(Boolean).join('.') ??
|
|
197
|
+
'step';
|
|
198
|
+
return { api, summary, selector, startTime: event.startTime, callId: event.callId };
|
|
199
|
+
}
|
|
200
|
+
function snapshotFrom(event) {
|
|
201
|
+
const snapshot = event.snapshot;
|
|
202
|
+
if (typeof snapshot === 'string')
|
|
203
|
+
return { hash: snapshot };
|
|
204
|
+
if (snapshot && typeof snapshot === 'object') {
|
|
205
|
+
const s = snapshot;
|
|
206
|
+
if (typeof s.hash === 'string')
|
|
207
|
+
return { hash: s.hash };
|
|
208
|
+
if (s.html !== undefined) {
|
|
209
|
+
const html = serializeDomTree(s.html);
|
|
210
|
+
if (html)
|
|
211
|
+
return { html };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return {};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Parse merged `.trace` JSON-lines into a structured failure context.
|
|
218
|
+
* Exported for unit tests with synthetic event streams.
|
|
219
|
+
*/
|
|
220
|
+
export function analyzeTraceEvents(lines, snapshotLoader, fileLoader) {
|
|
221
|
+
const rawLines = Array.isArray(lines) ? lines : lines.split(/\r?\n/);
|
|
222
|
+
const warnings = [];
|
|
223
|
+
const actionLog = [];
|
|
224
|
+
const consoleMessages = [];
|
|
225
|
+
const events = [];
|
|
226
|
+
for (const line of rawLines) {
|
|
227
|
+
const trimmed = line.trim();
|
|
228
|
+
if (trimmed === '')
|
|
229
|
+
continue;
|
|
230
|
+
try {
|
|
231
|
+
events.push(JSON.parse(trimmed));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// Tolerate partial lines from a killed run.
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (events.length === 0) {
|
|
238
|
+
warnings.push('The trace contained no parseable events (the run may have been killed mid-write).');
|
|
239
|
+
}
|
|
240
|
+
let firstTimestamp;
|
|
241
|
+
const pendingByCall = new Map();
|
|
242
|
+
let pendingSingle;
|
|
243
|
+
const snapshots = [];
|
|
244
|
+
const beforeTime = new Map();
|
|
245
|
+
let currentHash;
|
|
246
|
+
let errorContextFile;
|
|
247
|
+
let failure;
|
|
248
|
+
const recordAction = (entry) => {
|
|
249
|
+
actionLog.push(entry);
|
|
250
|
+
if (actionLog.length > MAX_ACTION_LOG)
|
|
251
|
+
actionLog.shift();
|
|
252
|
+
};
|
|
253
|
+
const takePending = (event) => {
|
|
254
|
+
if (event.callId) {
|
|
255
|
+
const info = pendingByCall.get(event.callId);
|
|
256
|
+
if (info)
|
|
257
|
+
pendingByCall.delete(event.callId);
|
|
258
|
+
return info;
|
|
259
|
+
}
|
|
260
|
+
const info = pendingSingle;
|
|
261
|
+
pendingSingle = undefined;
|
|
262
|
+
return info;
|
|
263
|
+
};
|
|
264
|
+
for (const event of events) {
|
|
265
|
+
const time = event.startTime ?? event.time ?? event.endTime;
|
|
266
|
+
if (time !== undefined && firstTimestamp === undefined)
|
|
267
|
+
firstTimestamp = time;
|
|
268
|
+
if (event.type === 'console') {
|
|
269
|
+
const kind = event.messageType === 'error'
|
|
270
|
+
? 'error'
|
|
271
|
+
: event.messageType === 'warning'
|
|
272
|
+
? 'warning'
|
|
273
|
+
: undefined;
|
|
274
|
+
if (kind) {
|
|
275
|
+
const loc = event.location;
|
|
276
|
+
consoleMessages.push({
|
|
277
|
+
type: kind,
|
|
278
|
+
text: typeof event.text === 'string' ? event.text : '',
|
|
279
|
+
location: loc?.url !== undefined
|
|
280
|
+
? `${loc.url}${loc.lineNumber !== undefined ? `:${loc.lineNumber}` : ''}`
|
|
281
|
+
: undefined,
|
|
282
|
+
});
|
|
283
|
+
if (consoleMessages.length > MAX_CONSOLE_MESSAGES)
|
|
284
|
+
consoleMessages.shift();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (event.snapshot !== undefined) {
|
|
288
|
+
const { html, hash } = snapshotFrom(event);
|
|
289
|
+
if (hash)
|
|
290
|
+
currentHash = hash;
|
|
291
|
+
if (html || hash) {
|
|
292
|
+
snapshots.push({
|
|
293
|
+
html,
|
|
294
|
+
hash,
|
|
295
|
+
callId: event.callId,
|
|
296
|
+
time: event.startTime ?? (event.callId ? beforeTime.get(event.callId) : undefined),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
const started = actionInfo(event);
|
|
301
|
+
if (started) {
|
|
302
|
+
if (started.startTime !== undefined && started.callId)
|
|
303
|
+
beforeTime.set(started.callId, started.startTime);
|
|
304
|
+
if (started.callId)
|
|
305
|
+
pendingByCall.set(started.callId, started);
|
|
306
|
+
else
|
|
307
|
+
pendingSingle = started;
|
|
308
|
+
}
|
|
309
|
+
for (const attachment of event.attachments ?? []) {
|
|
310
|
+
const name = attachment.name ?? '';
|
|
311
|
+
const contentType = attachment.contentType ?? '';
|
|
312
|
+
if (attachment.file && (name === 'error-context' || contentType === 'text/markdown')) {
|
|
313
|
+
errorContextFile = attachment.file;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const error = eventError(event);
|
|
317
|
+
if (error !== undefined && !failure) {
|
|
318
|
+
const info = takePending(event);
|
|
319
|
+
const snap = snapshotFrom(event);
|
|
320
|
+
failure = {
|
|
321
|
+
error,
|
|
322
|
+
action: info,
|
|
323
|
+
time: event.endTime ?? event.startTime ?? event.time ?? info?.startTime,
|
|
324
|
+
callId: event.callId ?? info?.callId,
|
|
325
|
+
hash: snap.hash,
|
|
326
|
+
html: snap.html,
|
|
327
|
+
};
|
|
328
|
+
if (info)
|
|
329
|
+
recordAction({ api: info.api, summary: info.summary, failed: true });
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (event.type === 'after') {
|
|
333
|
+
const info = takePending(event);
|
|
334
|
+
if (info) {
|
|
335
|
+
recordAction({ api: info.api, summary: info.summary, failed: eventError(event) !== undefined });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Steps still in flight when the trace ended (killed run).
|
|
340
|
+
for (const info of pendingByCall.values()) {
|
|
341
|
+
if (!NOISE_METHODS.has(info.api.toLowerCase())) {
|
|
342
|
+
recordAction({ api: info.api, summary: info.summary, failed: false });
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (pendingSingle) {
|
|
346
|
+
recordAction({ api: pendingSingle.api, summary: pendingSingle.summary, failed: false });
|
|
347
|
+
}
|
|
348
|
+
// Choose the snapshot closest to (but not after) the failure.
|
|
349
|
+
let chosen;
|
|
350
|
+
if (failure) {
|
|
351
|
+
if (failure.callId)
|
|
352
|
+
chosen = [...snapshots].reverse().find((s) => s.callId === failure.callId);
|
|
353
|
+
if (!chosen && failure.time !== undefined) {
|
|
354
|
+
chosen = [...snapshots]
|
|
355
|
+
.filter((s) => s.time === undefined || s.time <= failure.time)
|
|
356
|
+
.pop();
|
|
357
|
+
}
|
|
358
|
+
if (!chosen)
|
|
359
|
+
chosen = snapshots[snapshots.length - 1];
|
|
360
|
+
}
|
|
361
|
+
const snapshotHash = failure?.hash ?? chosen?.hash ?? currentHash;
|
|
362
|
+
const snapshotTreeHtml = failure?.html ?? chosen?.html;
|
|
363
|
+
let snapshotHtml;
|
|
364
|
+
let snapshotTruncated = false;
|
|
365
|
+
const truncate = (html) => {
|
|
366
|
+
if (html.length > MAX_HTML_CHARS) {
|
|
367
|
+
snapshotTruncated = true;
|
|
368
|
+
return html.slice(0, MAX_HTML_CHARS);
|
|
369
|
+
}
|
|
370
|
+
return html;
|
|
371
|
+
};
|
|
372
|
+
if (snapshotTreeHtml) {
|
|
373
|
+
snapshotHtml = truncate(snapshotTreeHtml);
|
|
374
|
+
}
|
|
375
|
+
else if (snapshotHash) {
|
|
376
|
+
const loaded = snapshotLoader(snapshotHash);
|
|
377
|
+
if (loaded === undefined) {
|
|
378
|
+
warnings.push(`DOM snapshot "${snapshotHash}" was not present in the trace archive.`);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
snapshotHtml = truncate(loaded);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else if (events.length > 0) {
|
|
385
|
+
warnings.push('No DOM snapshot was recorded before the failure (the page may never have loaded).');
|
|
386
|
+
}
|
|
387
|
+
let errorContext;
|
|
388
|
+
if (errorContextFile && fileLoader) {
|
|
389
|
+
const content = fileLoader(errorContextFile);
|
|
390
|
+
if (content && content.trim() !== '') {
|
|
391
|
+
errorContext =
|
|
392
|
+
content.length > MAX_CONTEXT_CHARS ? `${content.slice(0, MAX_CONTEXT_CHARS)}…` : content;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
const context = {
|
|
396
|
+
error: failure?.error ??
|
|
397
|
+
(events.length > 0 ? 'The trace recorded an error without a message.' : 'No trace data.'),
|
|
398
|
+
action: failure?.action
|
|
399
|
+
? {
|
|
400
|
+
api: failure.action.api,
|
|
401
|
+
selector: failure.action.selector,
|
|
402
|
+
params: failure.action.summary,
|
|
403
|
+
}
|
|
404
|
+
: undefined,
|
|
405
|
+
atMs: failure?.time !== undefined && firstTimestamp !== undefined
|
|
406
|
+
? Math.max(0, Math.round(failure.time - firstTimestamp))
|
|
407
|
+
: undefined,
|
|
408
|
+
snapshotHtml,
|
|
409
|
+
snapshotTruncated,
|
|
410
|
+
errorContext,
|
|
411
|
+
actionLog,
|
|
412
|
+
consoleMessages,
|
|
413
|
+
failedRequests: [],
|
|
414
|
+
networkTotal: 0,
|
|
415
|
+
warnings,
|
|
416
|
+
};
|
|
417
|
+
const snippet = buildSnippet(snapshotHtml, failure?.action?.selector);
|
|
418
|
+
if (snippet)
|
|
419
|
+
context.snippet = snippet;
|
|
420
|
+
return context;
|
|
421
|
+
}
|
|
422
|
+
/** Window of snapshot HTML around the failing element, when locatable. */
|
|
423
|
+
function buildSnippet(html, selector) {
|
|
424
|
+
if (!html)
|
|
425
|
+
return undefined;
|
|
426
|
+
const candidates = [];
|
|
427
|
+
if (selector) {
|
|
428
|
+
candidates.push(selector);
|
|
429
|
+
const id = /#([\w-]+)/.exec(selector);
|
|
430
|
+
if (id)
|
|
431
|
+
candidates.push(`id="${id[1]}"`);
|
|
432
|
+
const cls = /\.([\w-]+)/.exec(selector);
|
|
433
|
+
if (cls)
|
|
434
|
+
candidates.push(cls[1]);
|
|
435
|
+
const attr = /\[([\w-]+)=["']?([^"'\]]+)/.exec(selector);
|
|
436
|
+
if (attr)
|
|
437
|
+
candidates.push(`${attr[1]}="${attr[2]}"`);
|
|
438
|
+
}
|
|
439
|
+
for (const candidate of candidates) {
|
|
440
|
+
if (candidate === '')
|
|
441
|
+
continue;
|
|
442
|
+
const index = html.indexOf(candidate);
|
|
443
|
+
if (index < 0)
|
|
444
|
+
continue;
|
|
445
|
+
const start = Math.max(0, index - MAX_SNIPPET_RADIUS);
|
|
446
|
+
const end = Math.min(html.length, index + candidate.length + MAX_SNIPPET_RADIUS);
|
|
447
|
+
const prefix = start > 0 ? '…' : '';
|
|
448
|
+
const suffix = end < html.length ? '…' : '';
|
|
449
|
+
return `${prefix}${html.slice(start, end)}${suffix}`;
|
|
450
|
+
}
|
|
451
|
+
// Fall back to the start of <body> so the agent still gets real DOM.
|
|
452
|
+
const body = html.indexOf('<body');
|
|
453
|
+
if (body >= 0)
|
|
454
|
+
return html.slice(body, Math.min(html.length, body + MAX_SNIPPET_RADIUS * 2));
|
|
455
|
+
return undefined;
|
|
456
|
+
}
|
|
457
|
+
/* ------------------------------------------------------------------ */
|
|
458
|
+
/* Public API */
|
|
459
|
+
/* ------------------------------------------------------------------ */
|
|
460
|
+
function loadFromZip(entries, names) {
|
|
461
|
+
for (const name of names) {
|
|
462
|
+
const buf = entries.get(name);
|
|
463
|
+
if (!buf)
|
|
464
|
+
continue;
|
|
465
|
+
try {
|
|
466
|
+
return gunzipSync(buf).toString('utf8');
|
|
467
|
+
}
|
|
468
|
+
catch {
|
|
469
|
+
try {
|
|
470
|
+
return inflateRawSync(buf).toString('utf8');
|
|
471
|
+
}
|
|
472
|
+
catch {
|
|
473
|
+
return buf.toString('utf8');
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return undefined;
|
|
478
|
+
}
|
|
479
|
+
function loadSnapshotSync(entries, hash) {
|
|
480
|
+
return loadFromZip(entries, [`resources/${hash}`, hash, `${hash}.html`, `resources/${hash}.html`]);
|
|
481
|
+
}
|
|
482
|
+
/** Decode a trace entry that may be raw JSON, deflated or gzipped. */
|
|
483
|
+
function decodeEntryText(data) {
|
|
484
|
+
try {
|
|
485
|
+
return gunzipSync(data).toString('utf8');
|
|
486
|
+
}
|
|
487
|
+
catch {
|
|
488
|
+
try {
|
|
489
|
+
return inflateRawSync(data).toString('utf8');
|
|
490
|
+
}
|
|
491
|
+
catch {
|
|
492
|
+
return data.toString('utf8');
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Parse a Playwright `*.network` JSON-lines entry (HAR-style
|
|
498
|
+
* `resource-snapshot` events) and return the requests that failed
|
|
499
|
+
* (status >= 400, status 0, transport error, or no response at all)
|
|
500
|
+
* plus the total number of completed requests observed.
|
|
501
|
+
* Exported for unit tests.
|
|
502
|
+
*/
|
|
503
|
+
export function parseNetworkLog(text) {
|
|
504
|
+
const failed = [];
|
|
505
|
+
let total = 0;
|
|
506
|
+
for (const line of text.split(/\r?\n/)) {
|
|
507
|
+
const trimmed = line.trim();
|
|
508
|
+
if (trimmed === '')
|
|
509
|
+
continue;
|
|
510
|
+
let event;
|
|
511
|
+
try {
|
|
512
|
+
event = JSON.parse(trimmed);
|
|
513
|
+
}
|
|
514
|
+
catch {
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
if (event.type !== 'resource-snapshot' || !event.snapshot)
|
|
518
|
+
continue;
|
|
519
|
+
const snap = event.snapshot;
|
|
520
|
+
total += 1;
|
|
521
|
+
const req = snap.request ?? {};
|
|
522
|
+
const resp = snap.response ?? undefined;
|
|
523
|
+
const status = typeof resp?.status === 'number' ? resp.status : undefined;
|
|
524
|
+
const errRaw = snap.error;
|
|
525
|
+
const errorText = typeof errRaw === 'string'
|
|
526
|
+
? errRaw
|
|
527
|
+
: errRaw && typeof errRaw === 'object' && typeof errRaw.message === 'string'
|
|
528
|
+
? errRaw.message
|
|
529
|
+
: undefined;
|
|
530
|
+
const isFailure = errorText !== undefined || status === undefined || status >= 400 || status === 0;
|
|
531
|
+
if (!isFailure)
|
|
532
|
+
continue;
|
|
533
|
+
if (failed.length >= MAX_FAILED_REQUESTS)
|
|
534
|
+
continue; // still counted in `total`
|
|
535
|
+
failed.push({
|
|
536
|
+
method: typeof req.method === 'string' ? req.method : 'GET',
|
|
537
|
+
url: typeof req.url === 'string' ? req.url : '',
|
|
538
|
+
status: status !== undefined && status !== 0 ? status : undefined,
|
|
539
|
+
statusText: typeof resp?.statusText === 'string' ? resp.statusText : undefined,
|
|
540
|
+
resourceType: typeof snap._resourceType === 'string' ? snap._resourceType : undefined,
|
|
541
|
+
errorText: status === 0 || status === undefined ? (errorText ?? 'request failed') : errorText,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
return { failed, total };
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Read a trace.zip produced by Playwright and extract the failure
|
|
548
|
+
* context: error, failed action, action log, DOM snapshot and the
|
|
549
|
+
* error-context attachment. Returns null when the file is
|
|
550
|
+
* missing/unreadable — callers degrade to a hint instead of failing.
|
|
551
|
+
*/
|
|
552
|
+
export async function readFailureTrace(tracePath) {
|
|
553
|
+
let buf;
|
|
554
|
+
try {
|
|
555
|
+
buf = await readFile(tracePath);
|
|
556
|
+
}
|
|
557
|
+
catch {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
let entries;
|
|
561
|
+
try {
|
|
562
|
+
entries = readZipEntries(buf);
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
return {
|
|
566
|
+
error: 'The trace archive could not be read.',
|
|
567
|
+
actionLog: [],
|
|
568
|
+
consoleMessages: [],
|
|
569
|
+
failedRequests: [],
|
|
570
|
+
networkTotal: 0,
|
|
571
|
+
warnings: [`Failed to parse ${normalizePath(tracePath)} as a ZIP archive.`],
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
const traceLines = [];
|
|
575
|
+
for (const [name, data] of entries) {
|
|
576
|
+
if (name.endsWith('.trace')) {
|
|
577
|
+
traceLines.push(...decodeEntryText(data).split(/\r?\n/));
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (traceLines.length === 0) {
|
|
581
|
+
return {
|
|
582
|
+
error: 'The trace archive contained no event log.',
|
|
583
|
+
actionLog: [],
|
|
584
|
+
consoleMessages: [],
|
|
585
|
+
failedRequests: [],
|
|
586
|
+
networkTotal: 0,
|
|
587
|
+
warnings: [`No *.trace entries found in ${normalizePath(tracePath)}.`],
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
const context = analyzeTraceEvents(traceLines, (hash) => loadSnapshotSync(entries, hash), (name) => loadFromZip(entries, [name, `attachments/${name}`]));
|
|
591
|
+
// Network diagnostics: merge the *.network resource logs.
|
|
592
|
+
let networkTotal = 0;
|
|
593
|
+
const failedRequests = [];
|
|
594
|
+
for (const [name, data] of entries) {
|
|
595
|
+
if (!name.endsWith('.network'))
|
|
596
|
+
continue;
|
|
597
|
+
const parsed = parseNetworkLog(decodeEntryText(data));
|
|
598
|
+
networkTotal += parsed.total;
|
|
599
|
+
for (const req of parsed.failed) {
|
|
600
|
+
if (failedRequests.length < MAX_FAILED_REQUESTS)
|
|
601
|
+
failedRequests.push(req);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
context.failedRequests = failedRequests;
|
|
605
|
+
context.networkTotal = networkTotal;
|
|
606
|
+
return context;
|
|
607
|
+
}
|
|
608
|
+
//# sourceMappingURL=trace-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-reader.js","sourceRoot":"","sources":["../../src/utils/trace-reader.ts"],"names":[],"mappings":"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"}
|