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,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual regression core: PNG decode/encode and a pixel diff.
|
|
3
|
+
*
|
|
4
|
+
* Playwright screenshots are 8-bit non-interlaced PNGs, so a small
|
|
5
|
+
* built-in codec covers them without adding dependencies. The diff
|
|
6
|
+
* reports how much changed, *where* it changed (merged grid regions),
|
|
7
|
+
* and the average color shift — powering the "you changed the button
|
|
8
|
+
* from blue to red" message from the blueprint.
|
|
9
|
+
*/
|
|
10
|
+
import { deflateSync, inflateSync } from 'node:zlib';
|
|
11
|
+
/* ------------------------------------------------------------------ */
|
|
12
|
+
/* CRC32 + PNG chunks */
|
|
13
|
+
/* ------------------------------------------------------------------ */
|
|
14
|
+
const CRC_TABLE = (() => {
|
|
15
|
+
const table = new Uint32Array(256);
|
|
16
|
+
for (let n = 0; n < 256; n += 1) {
|
|
17
|
+
let c = n;
|
|
18
|
+
for (let k = 0; k < 8; k += 1)
|
|
19
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
20
|
+
table[n] = c >>> 0;
|
|
21
|
+
}
|
|
22
|
+
return table;
|
|
23
|
+
})();
|
|
24
|
+
function crc32(buf) {
|
|
25
|
+
let c = 0xffffffff;
|
|
26
|
+
for (let i = 0; i < buf.length; i += 1)
|
|
27
|
+
c = CRC_TABLE[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
|
28
|
+
return (c ^ 0xffffffff) >>> 0;
|
|
29
|
+
}
|
|
30
|
+
function chunk(type, data) {
|
|
31
|
+
const out = Buffer.alloc(12 + data.length);
|
|
32
|
+
out.writeUInt32BE(data.length, 0);
|
|
33
|
+
out.write(type, 4, 'ascii');
|
|
34
|
+
data.copy(out, 8);
|
|
35
|
+
out.writeUInt32BE(crc32(out.subarray(4, 8 + data.length)), 8 + data.length);
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/* ------------------------------------------------------------------ */
|
|
39
|
+
/* Decode */
|
|
40
|
+
/* ------------------------------------------------------------------ */
|
|
41
|
+
function paeth(a, b, c) {
|
|
42
|
+
const p = a + b - c;
|
|
43
|
+
const pa = Math.abs(p - a);
|
|
44
|
+
const pb = Math.abs(p - b);
|
|
45
|
+
const pc = Math.abs(p - c);
|
|
46
|
+
if (pa <= pb && pa <= pc)
|
|
47
|
+
return a;
|
|
48
|
+
if (pb <= pc)
|
|
49
|
+
return b;
|
|
50
|
+
return c;
|
|
51
|
+
}
|
|
52
|
+
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
53
|
+
/** Decode an 8-bit, non-interlaced PNG (gray/RGB/palette/alpha variants). */
|
|
54
|
+
export function decodePng(buf) {
|
|
55
|
+
if (buf.length < 8 || !buf.subarray(0, 8).equals(PNG_SIGNATURE)) {
|
|
56
|
+
throw new Error('Not a PNG file (bad signature)');
|
|
57
|
+
}
|
|
58
|
+
let width = 0;
|
|
59
|
+
let height = 0;
|
|
60
|
+
let bitDepth = 0;
|
|
61
|
+
let colorType = 0;
|
|
62
|
+
let interlace = 0;
|
|
63
|
+
const idat = [];
|
|
64
|
+
let palette = null;
|
|
65
|
+
let offset = 8;
|
|
66
|
+
while (offset + 8 <= buf.length) {
|
|
67
|
+
const length = buf.readUInt32BE(offset);
|
|
68
|
+
const type = buf.toString('ascii', offset + 4, offset + 8);
|
|
69
|
+
const data = buf.subarray(offset + 8, offset + 8 + length);
|
|
70
|
+
if (offset + 12 + length > buf.length)
|
|
71
|
+
break;
|
|
72
|
+
if (type === 'IHDR') {
|
|
73
|
+
width = data.readUInt32BE(0);
|
|
74
|
+
height = data.readUInt32BE(4);
|
|
75
|
+
bitDepth = data[8];
|
|
76
|
+
colorType = data[9];
|
|
77
|
+
interlace = data[12];
|
|
78
|
+
}
|
|
79
|
+
else if (type === 'IDAT') {
|
|
80
|
+
idat.push(Buffer.from(data));
|
|
81
|
+
}
|
|
82
|
+
else if (type === 'PLTE') {
|
|
83
|
+
palette = Buffer.from(data);
|
|
84
|
+
}
|
|
85
|
+
else if (type === 'IEND') {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
offset += 12 + length;
|
|
89
|
+
}
|
|
90
|
+
if (width <= 0 || height <= 0)
|
|
91
|
+
throw new Error('PNG is missing a valid IHDR chunk');
|
|
92
|
+
if (bitDepth !== 8)
|
|
93
|
+
throw new Error(`Unsupported PNG bit depth ${bitDepth} (only 8 supported)`);
|
|
94
|
+
if (interlace !== 0)
|
|
95
|
+
throw new Error('Interlaced PNGs are not supported');
|
|
96
|
+
if (colorType === 3 && !palette)
|
|
97
|
+
throw new Error('Palette PNG is missing its PLTE chunk');
|
|
98
|
+
const channels = colorType === 6 ? 4 : colorType === 2 ? 3 : colorType === 4 ? 2 : 1;
|
|
99
|
+
const stride = width * channels;
|
|
100
|
+
const raw = inflateSync(Buffer.concat(idat));
|
|
101
|
+
if (raw.length < height * (stride + 1))
|
|
102
|
+
throw new Error('PNG data is truncated');
|
|
103
|
+
// Unfilter scanlines.
|
|
104
|
+
const pixels = new Uint8Array(height * stride);
|
|
105
|
+
let pos = 0;
|
|
106
|
+
let prevRow = new Uint8Array(stride);
|
|
107
|
+
for (let y = 0; y < height; y += 1) {
|
|
108
|
+
const filter = raw[pos];
|
|
109
|
+
pos += 1;
|
|
110
|
+
const row = new Uint8Array(stride);
|
|
111
|
+
for (let i = 0; i < stride; i += 1) {
|
|
112
|
+
const x = raw[pos + i];
|
|
113
|
+
const a = i >= channels ? row[i - channels] : 0;
|
|
114
|
+
const b = prevRow[i];
|
|
115
|
+
const c = i >= channels ? prevRow[i - channels] : 0;
|
|
116
|
+
let value;
|
|
117
|
+
switch (filter) {
|
|
118
|
+
case 0:
|
|
119
|
+
value = x;
|
|
120
|
+
break;
|
|
121
|
+
case 1:
|
|
122
|
+
value = x + a;
|
|
123
|
+
break;
|
|
124
|
+
case 2:
|
|
125
|
+
value = x + b;
|
|
126
|
+
break;
|
|
127
|
+
case 3:
|
|
128
|
+
value = x + ((a + b) >> 1);
|
|
129
|
+
break;
|
|
130
|
+
case 4:
|
|
131
|
+
value = x + paeth(a, b, c);
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(`Unsupported PNG filter type ${filter}`);
|
|
135
|
+
}
|
|
136
|
+
row[i] = value & 0xff;
|
|
137
|
+
}
|
|
138
|
+
pos += stride;
|
|
139
|
+
pixels.set(row, y * stride);
|
|
140
|
+
prevRow = row;
|
|
141
|
+
}
|
|
142
|
+
// Expand to RGBA.
|
|
143
|
+
const out = new Uint8Array(width * height * 4);
|
|
144
|
+
for (let i = 0; i < width * height; i += 1) {
|
|
145
|
+
const src = i * channels;
|
|
146
|
+
const dst = i * 4;
|
|
147
|
+
if (colorType === 6) {
|
|
148
|
+
out[dst] = pixels[src];
|
|
149
|
+
out[dst + 1] = pixels[src + 1];
|
|
150
|
+
out[dst + 2] = pixels[src + 2];
|
|
151
|
+
out[dst + 3] = pixels[src + 3];
|
|
152
|
+
}
|
|
153
|
+
else if (colorType === 2) {
|
|
154
|
+
out[dst] = pixels[src];
|
|
155
|
+
out[dst + 1] = pixels[src + 1];
|
|
156
|
+
out[dst + 2] = pixels[src + 2];
|
|
157
|
+
out[dst + 3] = 255;
|
|
158
|
+
}
|
|
159
|
+
else if (colorType === 0) {
|
|
160
|
+
out[dst] = out[dst + 1] = out[dst + 2] = pixels[src];
|
|
161
|
+
out[dst + 3] = 255;
|
|
162
|
+
}
|
|
163
|
+
else if (colorType === 4) {
|
|
164
|
+
out[dst] = out[dst + 1] = out[dst + 2] = pixels[src];
|
|
165
|
+
out[dst + 3] = pixels[src + 1];
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const index = pixels[src];
|
|
169
|
+
out[dst] = palette[index * 3];
|
|
170
|
+
out[dst + 1] = palette[index * 3 + 1];
|
|
171
|
+
out[dst + 2] = palette[index * 3 + 2];
|
|
172
|
+
out[dst + 3] = 255;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return { width, height, data: out };
|
|
176
|
+
}
|
|
177
|
+
/* ------------------------------------------------------------------ */
|
|
178
|
+
/* Encode */
|
|
179
|
+
/* ------------------------------------------------------------------ */
|
|
180
|
+
/** Encode an RGBA image as a PNG (filter 0, default compression). */
|
|
181
|
+
export function encodePng(image) {
|
|
182
|
+
const { width, height, data } = image;
|
|
183
|
+
const stride = width * 4;
|
|
184
|
+
const raw = Buffer.alloc(height * (stride + 1));
|
|
185
|
+
for (let y = 0; y < height; y += 1) {
|
|
186
|
+
const rowStart = y * (stride + 1);
|
|
187
|
+
raw[rowStart] = 0; // filter: None
|
|
188
|
+
Buffer.from(data.buffer, data.byteOffset + y * stride, stride).copy(raw, rowStart + 1);
|
|
189
|
+
}
|
|
190
|
+
const ihdr = Buffer.alloc(13);
|
|
191
|
+
ihdr.writeUInt32BE(width, 0);
|
|
192
|
+
ihdr.writeUInt32BE(height, 4);
|
|
193
|
+
ihdr[8] = 8; // bit depth
|
|
194
|
+
ihdr[9] = 6; // color type RGBA
|
|
195
|
+
ihdr[10] = 0; // compression
|
|
196
|
+
ihdr[11] = 0; // filter
|
|
197
|
+
ihdr[12] = 0; // interlace
|
|
198
|
+
return Buffer.concat([
|
|
199
|
+
PNG_SIGNATURE,
|
|
200
|
+
chunk('IHDR', ihdr),
|
|
201
|
+
chunk('IDAT', deflateSync(raw)),
|
|
202
|
+
chunk('IEND', Buffer.alloc(0)),
|
|
203
|
+
]);
|
|
204
|
+
}
|
|
205
|
+
function averageColor(before, after, changed) {
|
|
206
|
+
let br = 0;
|
|
207
|
+
let bg = 0;
|
|
208
|
+
let bb = 0;
|
|
209
|
+
let ar = 0;
|
|
210
|
+
let ag = 0;
|
|
211
|
+
let ab = 0;
|
|
212
|
+
let n = 0;
|
|
213
|
+
for (let p = 0; p < changed.length; p += 1) {
|
|
214
|
+
if (!changed[p])
|
|
215
|
+
continue;
|
|
216
|
+
const i = p * 4;
|
|
217
|
+
br += before.data[i];
|
|
218
|
+
bg += before.data[i + 1];
|
|
219
|
+
bb += before.data[i + 2];
|
|
220
|
+
ar += after.data[i];
|
|
221
|
+
ag += after.data[i + 1];
|
|
222
|
+
ab += after.data[i + 2];
|
|
223
|
+
n += 1;
|
|
224
|
+
}
|
|
225
|
+
if (n === 0)
|
|
226
|
+
return { before: { r: 0, g: 0, b: 0 }, after: { r: 0, g: 0, b: 0 } };
|
|
227
|
+
return {
|
|
228
|
+
before: { r: Math.round(br / n), g: Math.round(bg / n), b: Math.round(bb / n) },
|
|
229
|
+
after: { r: Math.round(ar / n), g: Math.round(ag / n), b: Math.round(ab / n) },
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Compare two screenshots. When dimensions differ, the overlapping
|
|
234
|
+
* region is compared and the remainder counts as changed.
|
|
235
|
+
*/
|
|
236
|
+
export function diffImages(before, after, options = {}) {
|
|
237
|
+
const pixelThreshold = options.pixelThreshold ?? 60;
|
|
238
|
+
const cellSize = options.cellSize ?? 24;
|
|
239
|
+
const cellRatio = options.cellRatio ?? 0.05;
|
|
240
|
+
const width = Math.max(before.width, after.width);
|
|
241
|
+
const height = Math.max(before.height, after.height);
|
|
242
|
+
const totalPixels = width * height;
|
|
243
|
+
const dimensionsChanged = before.width !== after.width || before.height !== after.height;
|
|
244
|
+
const compareWidth = Math.min(before.width, after.width);
|
|
245
|
+
const compareHeight = Math.min(before.height, after.height);
|
|
246
|
+
const changed = new Uint8Array(totalPixels);
|
|
247
|
+
let diffPixels = 0;
|
|
248
|
+
for (let y = 0; y < compareHeight; y += 1) {
|
|
249
|
+
for (let x = 0; x < compareWidth; x += 1) {
|
|
250
|
+
const bi = (y * before.width + x) * 4;
|
|
251
|
+
const ai = (y * after.width + x) * 4;
|
|
252
|
+
const delta = Math.abs(before.data[bi] - after.data[ai]) +
|
|
253
|
+
Math.abs(before.data[bi + 1] - after.data[ai + 1]) +
|
|
254
|
+
Math.abs(before.data[bi + 2] - after.data[ai + 2]) +
|
|
255
|
+
Math.abs(before.data[bi + 3] - after.data[ai + 3]);
|
|
256
|
+
if (delta > pixelThreshold) {
|
|
257
|
+
changed[y * width + x] = 1;
|
|
258
|
+
diffPixels += 1;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Pixels outside the overlap always count as changed.
|
|
263
|
+
const overlap = compareWidth * compareHeight;
|
|
264
|
+
const outside = totalPixels - overlap;
|
|
265
|
+
if (outside > 0) {
|
|
266
|
+
diffPixels += outside;
|
|
267
|
+
for (let y = 0; y < height; y += 1) {
|
|
268
|
+
for (let x = 0; x < width; x += 1) {
|
|
269
|
+
if (x >= compareWidth || y >= compareHeight)
|
|
270
|
+
changed[y * width + x] = 1;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Cluster changed pixels into grid cells, then merge adjacent cells.
|
|
275
|
+
const cols = Math.ceil(width / cellSize);
|
|
276
|
+
const rows = Math.ceil(height / cellSize);
|
|
277
|
+
const cellPixels = cellSize * cellSize;
|
|
278
|
+
const active = new Uint8Array(cols * rows);
|
|
279
|
+
// A cell counts when at least cellRatio of it changed (small cells: ≥2 px).
|
|
280
|
+
const cellCount = new Uint32Array(cols * rows);
|
|
281
|
+
for (let y = 0; y < height; y += 1) {
|
|
282
|
+
for (let x = 0; x < width; x += 1) {
|
|
283
|
+
if (changed[y * width + x])
|
|
284
|
+
cellCount[Math.floor(y / cellSize) * cols + Math.floor(x / cellSize)] += 1;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
for (let i = 0; i < active.length; i += 1) {
|
|
288
|
+
const needed = Math.max(2, Math.ceil(cellPixels * cellRatio));
|
|
289
|
+
active[i] = cellCount[i] >= needed ? 1 : 0;
|
|
290
|
+
}
|
|
291
|
+
const regions = [];
|
|
292
|
+
const visited = new Uint8Array(cols * rows);
|
|
293
|
+
for (let cell = 0; cell < active.length; cell += 1) {
|
|
294
|
+
if (!active[cell] || visited[cell])
|
|
295
|
+
continue;
|
|
296
|
+
// BFS over adjacent active cells.
|
|
297
|
+
const queue = [cell];
|
|
298
|
+
visited[cell] = 1;
|
|
299
|
+
let minX = cols;
|
|
300
|
+
let minY = rows;
|
|
301
|
+
let maxX = 0;
|
|
302
|
+
let maxY = 0;
|
|
303
|
+
let pixels = 0;
|
|
304
|
+
while (queue.length > 0) {
|
|
305
|
+
const current = queue.pop();
|
|
306
|
+
const cx = current % cols;
|
|
307
|
+
const cy = Math.floor(current / cols);
|
|
308
|
+
minX = Math.min(minX, cx);
|
|
309
|
+
minY = Math.min(minY, cy);
|
|
310
|
+
maxX = Math.max(maxX, cx);
|
|
311
|
+
maxY = Math.max(maxY, cy);
|
|
312
|
+
pixels += cellCount[current];
|
|
313
|
+
const neighbors = [
|
|
314
|
+
cx > 0 ? current - 1 : -1,
|
|
315
|
+
cx < cols - 1 ? current + 1 : -1,
|
|
316
|
+
cy > 0 ? current - cols : -1,
|
|
317
|
+
cy < rows - 1 ? current + cols : -1,
|
|
318
|
+
];
|
|
319
|
+
for (const next of neighbors) {
|
|
320
|
+
if (next >= 0 && active[next] && !visited[next]) {
|
|
321
|
+
visited[next] = 1;
|
|
322
|
+
queue.push(next);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
regions.push({
|
|
327
|
+
x: minX * cellSize,
|
|
328
|
+
y: minY * cellSize,
|
|
329
|
+
width: Math.min(width, (maxX + 1) * cellSize) - minX * cellSize,
|
|
330
|
+
height: Math.min(height, (maxY + 1) * cellSize) - minY * cellSize,
|
|
331
|
+
pixels,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
regions.sort((a, b) => b.pixels - a.pixels);
|
|
335
|
+
const avgs = averageColor(before, after, changed);
|
|
336
|
+
// Annotated diff image: dimmed baseline, changed pixels in red.
|
|
337
|
+
const diffImage = { width, height, data: new Uint8Array(width * height * 4) };
|
|
338
|
+
for (let y = 0; y < height; y += 1) {
|
|
339
|
+
for (let x = 0; x < width; x += 1) {
|
|
340
|
+
const p = y * width + x;
|
|
341
|
+
const out = p * 4;
|
|
342
|
+
if (changed[p]) {
|
|
343
|
+
diffImage.data[out] = 255;
|
|
344
|
+
diffImage.data[out + 1] = 40;
|
|
345
|
+
diffImage.data[out + 2] = 40;
|
|
346
|
+
diffImage.data[out + 3] = 255;
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
const bi = y < before.height && x < before.width ? (y * before.width + x) * 4 : -1;
|
|
350
|
+
const gray = bi >= 0
|
|
351
|
+
? Math.round(before.data[bi] * 0.299 + before.data[bi + 1] * 0.587 + before.data[bi + 2] * 0.114)
|
|
352
|
+
: 255;
|
|
353
|
+
diffImage.data[out] = gray;
|
|
354
|
+
diffImage.data[out + 1] = gray;
|
|
355
|
+
diffImage.data[out + 2] = gray;
|
|
356
|
+
diffImage.data[out + 3] = 255;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return {
|
|
361
|
+
width,
|
|
362
|
+
height,
|
|
363
|
+
totalPixels,
|
|
364
|
+
diffPixels,
|
|
365
|
+
percent: totalPixels === 0 ? 0 : Math.round((diffPixels / totalPixels) * 10_000) / 100,
|
|
366
|
+
dimensionsChanged,
|
|
367
|
+
regions: regions.slice(0, 5),
|
|
368
|
+
beforeAvg: diffPixels > 0 ? avgs.before : undefined,
|
|
369
|
+
afterAvg: diffPixels > 0 ? avgs.after : undefined,
|
|
370
|
+
diffImage,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=image-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-diff.js","sourceRoot":"","sources":["../../src/utils/image-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* IMPORTANT: MCP over stdio reserves stdout for protocol messages, so
|
|
5
|
+
* every log line is written to stderr. Logging must never throw — a full
|
|
6
|
+
* disk or closed stream must not take the server down.
|
|
7
|
+
*/
|
|
8
|
+
import type { LogContext, LogLevel, Logger } from '../types/index.js';
|
|
9
|
+
export interface LogStream {
|
|
10
|
+
write(chunk: string): void;
|
|
11
|
+
}
|
|
12
|
+
export interface LoggerOptions {
|
|
13
|
+
level?: LogLevel;
|
|
14
|
+
format?: 'text' | 'json';
|
|
15
|
+
bindings?: LogContext;
|
|
16
|
+
stream?: LogStream;
|
|
17
|
+
}
|
|
18
|
+
/** Create a logger. Defaults come from LOG_LEVEL / LOG_FORMAT env vars. */
|
|
19
|
+
export declare function createLogger(options?: LoggerOptions): Logger;
|
|
20
|
+
/** Shared root logger used across the server. */
|
|
21
|
+
export declare const logger: Logger;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* IMPORTANT: MCP over stdio reserves stdout for protocol messages, so
|
|
5
|
+
* every log line is written to stderr. Logging must never throw — a full
|
|
6
|
+
* disk or closed stream must not take the server down.
|
|
7
|
+
*/
|
|
8
|
+
const LEVEL_ORDER = {
|
|
9
|
+
debug: 0,
|
|
10
|
+
info: 1,
|
|
11
|
+
warn: 2,
|
|
12
|
+
error: 3,
|
|
13
|
+
silent: 4,
|
|
14
|
+
};
|
|
15
|
+
function parseLevel(raw) {
|
|
16
|
+
if (!raw)
|
|
17
|
+
return undefined;
|
|
18
|
+
const value = raw.trim().toLowerCase();
|
|
19
|
+
return Object.prototype.hasOwnProperty.call(LEVEL_ORDER, value) ? value : undefined;
|
|
20
|
+
}
|
|
21
|
+
function parseFormat(raw) {
|
|
22
|
+
if (!raw)
|
|
23
|
+
return undefined;
|
|
24
|
+
const value = raw.trim().toLowerCase();
|
|
25
|
+
return value === 'json' || value === 'ndjson' ? 'json' : value === 'text' ? 'text' : undefined;
|
|
26
|
+
}
|
|
27
|
+
function serializeError(err) {
|
|
28
|
+
if (err instanceof Error) {
|
|
29
|
+
return {
|
|
30
|
+
name: err.name,
|
|
31
|
+
message: err.message,
|
|
32
|
+
stack: err.stack,
|
|
33
|
+
...(err.cause !== undefined ? { cause: String(err.cause) } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return { message: String(err) };
|
|
37
|
+
}
|
|
38
|
+
function normalizeContext(context) {
|
|
39
|
+
const out = {};
|
|
40
|
+
for (const [key, value] of Object.entries(context)) {
|
|
41
|
+
if (value === undefined)
|
|
42
|
+
continue;
|
|
43
|
+
out[key] = value instanceof Error ? serializeError(value) : value;
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function stringifyValue(value) {
|
|
48
|
+
if (typeof value === 'string')
|
|
49
|
+
return JSON.stringify(value);
|
|
50
|
+
if (typeof value === 'number' || typeof value === 'boolean' || value === null)
|
|
51
|
+
return String(value);
|
|
52
|
+
if (value instanceof Error)
|
|
53
|
+
return JSON.stringify(value.message);
|
|
54
|
+
try {
|
|
55
|
+
const json = JSON.stringify(value);
|
|
56
|
+
return json === undefined ? String(value) : json;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return String(value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function formatContextText(context) {
|
|
63
|
+
const parts = [];
|
|
64
|
+
for (const [key, value] of Object.entries(context)) {
|
|
65
|
+
parts.push(`${key}=${stringifyValue(value)}`);
|
|
66
|
+
}
|
|
67
|
+
return parts.length > 0 ? ` ${parts.join(' ')}` : '';
|
|
68
|
+
}
|
|
69
|
+
class StdLogger {
|
|
70
|
+
level;
|
|
71
|
+
format;
|
|
72
|
+
bindings;
|
|
73
|
+
stream;
|
|
74
|
+
constructor(level, format, bindings, stream) {
|
|
75
|
+
this.level = level;
|
|
76
|
+
this.format = format;
|
|
77
|
+
this.bindings = bindings;
|
|
78
|
+
this.stream = stream;
|
|
79
|
+
}
|
|
80
|
+
enabled(level) {
|
|
81
|
+
if (this.level === 'silent')
|
|
82
|
+
return false;
|
|
83
|
+
return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level];
|
|
84
|
+
}
|
|
85
|
+
emit(level, message, context) {
|
|
86
|
+
if (!this.enabled(level))
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
const merged = normalizeContext({ ...this.bindings, ...(context ?? {}) });
|
|
90
|
+
if (this.format === 'json') {
|
|
91
|
+
this.stream.write(`${JSON.stringify({ time: new Date().toISOString(), level, message, ...merged })}\n`);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const name = typeof merged.name === 'string' ? ` [${merged.name}]` : '';
|
|
95
|
+
delete merged.name;
|
|
96
|
+
this.stream.write(`${new Date().toISOString()} ${level.toUpperCase().padEnd(5)}${name} ${message}${formatContextText(merged)}\n`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Logging must never break the server (e.g. closed pipe, full disk).
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
debug(message, context) {
|
|
104
|
+
this.emit('debug', message, context);
|
|
105
|
+
}
|
|
106
|
+
info(message, context) {
|
|
107
|
+
this.emit('info', message, context);
|
|
108
|
+
}
|
|
109
|
+
warn(message, context) {
|
|
110
|
+
this.emit('warn', message, context);
|
|
111
|
+
}
|
|
112
|
+
error(message, context) {
|
|
113
|
+
this.emit('error', message, context);
|
|
114
|
+
}
|
|
115
|
+
child(bindings) {
|
|
116
|
+
return new StdLogger(this.level, this.format, { ...this.bindings, ...bindings }, this.stream);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Create a logger. Defaults come from LOG_LEVEL / LOG_FORMAT env vars. */
|
|
120
|
+
export function createLogger(options = {}) {
|
|
121
|
+
const level = options.level ?? parseLevel(process.env.LOG_LEVEL ?? process.env.MCP_LOG_LEVEL) ?? 'info';
|
|
122
|
+
const format = options.format ?? parseFormat(process.env.LOG_FORMAT ?? process.env.MCP_LOG_FORMAT) ?? 'text';
|
|
123
|
+
const stream = options.stream ?? {
|
|
124
|
+
write: (chunk) => {
|
|
125
|
+
process.stderr.write(chunk);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
return new StdLogger(level, format, options.bindings ?? {}, stream);
|
|
129
|
+
}
|
|
130
|
+
/** Shared root logger used across the server. */
|
|
131
|
+
export const logger = createLogger({ bindings: { name: 'playwright-e2e-mcp' } });
|
|
132
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform path handling.
|
|
3
|
+
*
|
|
4
|
+
* All path logic here is *lexical* (string based, no fs access) so that
|
|
5
|
+
* Windows paths behave correctly when unit tests run on macOS/Linux and
|
|
6
|
+
* vice versa. Backslashes are normalized everywhere, drive letters and
|
|
7
|
+
* UNC prefixes are preserved, and user-supplied paths are sandboxed to
|
|
8
|
+
* the project root to block "../../etc/passwd" style escapes.
|
|
9
|
+
*/
|
|
10
|
+
/** Replace backslashes with slashes, collapsing duplicate separators. */
|
|
11
|
+
export declare function normalizeSeparators(p: string): string;
|
|
12
|
+
/** True when the path is Windows-style (drive letter or UNC). */
|
|
13
|
+
export declare function isWindowsPath(p: string): boolean;
|
|
14
|
+
/** True for absolute paths on either platform (/, C:/ or //unc). */
|
|
15
|
+
export declare function isAbsolutePath(p: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Normalize separators and collapse `.` / `..` segments lexically.
|
|
18
|
+
* Leading `..` on relative paths is preserved; escapes above an absolute
|
|
19
|
+
* root (/, C:/, //server) are dropped.
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizePath(p: string): string;
|
|
22
|
+
/** Resolve `target` against `base` (both normalized lexically). */
|
|
23
|
+
export declare function resolvePath(base: string, target: string): string;
|
|
24
|
+
/** Lexical containment check (case-insensitive for drive/UNC paths). */
|
|
25
|
+
export declare function isPathInside(child: string, parent: string): boolean;
|
|
26
|
+
/** Expand a leading `~` to the user's home directory. */
|
|
27
|
+
export declare function expandHome(p: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Sandbox a user-supplied path to the project root.
|
|
30
|
+
*
|
|
31
|
+
* Accepts relative or absolute inputs, expands `~`, normalizes
|
|
32
|
+
* separators, then verifies the result stays inside `projectRoot`.
|
|
33
|
+
* Throws PlaywrightMcpError(INVALID_PATH) for traversal escapes,
|
|
34
|
+
* absolute paths outside the root, URLs, null bytes, and empty values.
|
|
35
|
+
*
|
|
36
|
+
* @returns Normalized absolute path with forward slashes.
|
|
37
|
+
*/
|
|
38
|
+
export declare function sanitizeUserPath(input: unknown, projectRoot: string): string;
|
|
39
|
+
/** Convert a normalized path to the host platform's native form. */
|
|
40
|
+
export declare function toNativePath(p: string): string;
|
|
41
|
+
/** Always-forward-slash form (used in messages and tool output). */
|
|
42
|
+
export declare function toPosixPath(p: string): string;
|
|
43
|
+
/** Path of `p` relative to `root`, posix style; absolute if not inside. */
|
|
44
|
+
export declare function relativeToRoot(root: string, p: string): string;
|
|
45
|
+
/** Build an absolute path under the project root. */
|
|
46
|
+
export declare function joinProjectPath(root: string, ...segments: string[]): string;
|
|
47
|
+
/** A unique path inside the OS temp dir (used for JSON reports). */
|
|
48
|
+
export declare function tempFilePath(prefix: string, extension?: string): string;
|
|
49
|
+
/** True when a filename looks like a Playwright test/spec file. */
|
|
50
|
+
export declare function isTestFile(p: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Validate a free-form CLI argument list: rejects NUL bytes and
|
|
53
|
+
* shell-looking metacharacters that could smuggle extra commands.
|
|
54
|
+
*/
|
|
55
|
+
export declare function sanitizeCliArg(arg: string): string;
|