browser-commander 0.33.1 → 0.33.2
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.33.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0013b28: The failure screenshot that `browser-commander/tests` writes for a failed scenario captures the view without a clip for Playwright and Puppeteer pages that have no fixed viewport (issue #180), as trace checkpoints and default screenshots already do. A clipped engine capture could leave a resized headful window drawn at its old size. Pages with a fixed viewport and other engines keep the engine's screenshot.
|
|
8
|
+
|
|
3
9
|
## 0.33.1
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
package/src/tests/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import path from 'node:path';
|
|
|
11
11
|
import { test as baseTest } from 'test-anywhere';
|
|
12
12
|
import { launchBrowser } from '../browser/launcher.js';
|
|
13
13
|
import { makeBrowserCommander } from '../factory.js';
|
|
14
|
+
import { captureStableViewport } from '../capture/viewport.js';
|
|
14
15
|
import {
|
|
15
16
|
finishScenarioTrace,
|
|
16
17
|
resolveTestDownloads,
|
|
@@ -571,7 +572,19 @@ export async function writeFailureArtifacts(options = {}) {
|
|
|
571
572
|
if (page && typeof page.screenshot === 'function') {
|
|
572
573
|
const screenshotPath = path.join(artifactsDir, `${safeName}.png`);
|
|
573
574
|
try {
|
|
574
|
-
|
|
575
|
+
// A clipped engine capture can leave a resized headful window drawn at
|
|
576
|
+
// its old size (issue #180); without a fixed viewport, capture the view.
|
|
577
|
+
if (['playwright', 'puppeteer'].includes(engine)) {
|
|
578
|
+
const shot = await captureStableViewport(page, engine, {
|
|
579
|
+
type: 'png',
|
|
580
|
+
path: screenshotPath,
|
|
581
|
+
});
|
|
582
|
+
if (shot.engine === 'cdp') {
|
|
583
|
+
writeFileSync(screenshotPath, shot.bytes);
|
|
584
|
+
}
|
|
585
|
+
} else {
|
|
586
|
+
await page.screenshot({ path: screenshotPath });
|
|
587
|
+
}
|
|
575
588
|
artifacts.push(screenshotPath);
|
|
576
589
|
} catch (screenshotError) {
|
|
577
590
|
const screenshotErrorPath = path.join(
|
|
@@ -232,6 +232,7 @@ describe('browser-commander/tests', () => {
|
|
|
232
232
|
page: {
|
|
233
233
|
screenshot: async ({ path: screenshotPath }) => {
|
|
234
234
|
assert.ok(screenshotPath.endsWith('.png'));
|
|
235
|
+
return Buffer.from('png');
|
|
235
236
|
},
|
|
236
237
|
},
|
|
237
238
|
error: new Error('broken'),
|
|
@@ -241,6 +242,7 @@ describe('browser-commander/tests', () => {
|
|
|
241
242
|
});
|
|
242
243
|
|
|
243
244
|
assert.strictEqual(artifacts.length, 2);
|
|
245
|
+
assert.ok(artifacts[1].endsWith('.png'), artifacts[1]);
|
|
244
246
|
const errorJson = JSON.parse(readFileSync(artifacts[0], 'utf8'));
|
|
245
247
|
assert.strictEqual(errorJson.message, 'broken');
|
|
246
248
|
assert.strictEqual(errorJson.engine, 'playwright');
|
|
@@ -5,6 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import { startTrace } from '../../../src/traces/recorder.js';
|
|
6
6
|
import { TRACE_MODE } from '../../../src/traces/schema.js';
|
|
7
7
|
import { screenshot } from '../../../src/capture/index.js';
|
|
8
|
+
import { writeFailureArtifacts } from '../../../src/tests/index.js';
|
|
8
9
|
import {
|
|
9
10
|
createFakeCommander,
|
|
10
11
|
createFakePage,
|
|
@@ -45,6 +46,22 @@ function cdpFake({ viewport = null, failWith, engine = 'playwright' } = {}) {
|
|
|
45
46
|
return { page, calls };
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
/** One clip-less CDP capture of the view, and no engine screenshot. */
|
|
50
|
+
function assertViewCapture(calls) {
|
|
51
|
+
assert.deepEqual(calls.cdp, [
|
|
52
|
+
{
|
|
53
|
+
method: 'Page.captureScreenshot',
|
|
54
|
+
params: {
|
|
55
|
+
format: 'png',
|
|
56
|
+
fromSurface: false,
|
|
57
|
+
captureBeyondViewport: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
assert.equal(calls.engine.length, 0);
|
|
62
|
+
assert.equal(calls.detached, 1);
|
|
63
|
+
}
|
|
64
|
+
|
|
48
65
|
describe('trace checkpoint screenshots (issue #180)', () => {
|
|
49
66
|
const directory = useTempTraceDirectory();
|
|
50
67
|
|
|
@@ -74,18 +91,7 @@ describe('trace checkpoint screenshots (issue #180)', () => {
|
|
|
74
91
|
await checkpointShot(page, { withCommander, engine }),
|
|
75
92
|
'cdp-png'
|
|
76
93
|
);
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
method: 'Page.captureScreenshot',
|
|
80
|
-
params: {
|
|
81
|
-
format: 'png',
|
|
82
|
-
fromSurface: false,
|
|
83
|
-
captureBeyondViewport: false,
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
]);
|
|
87
|
-
assert.equal(calls.engine.length, 0);
|
|
88
|
-
assert.equal(calls.detached, 1);
|
|
94
|
+
assertViewCapture(calls);
|
|
89
95
|
});
|
|
90
96
|
}
|
|
91
97
|
}
|
|
@@ -171,3 +177,48 @@ describe('default commander screenshots (issue #180)', () => {
|
|
|
171
177
|
});
|
|
172
178
|
}
|
|
173
179
|
});
|
|
180
|
+
|
|
181
|
+
describe('failure artifact screenshots (issue #180)', () => {
|
|
182
|
+
const directory = useTempTraceDirectory();
|
|
183
|
+
|
|
184
|
+
/** The PNG artifact a failed scenario writes, read back as text. */
|
|
185
|
+
async function failureShot(page, engine) {
|
|
186
|
+
page.screenshot = async (options) => {
|
|
187
|
+
page.engineCalls.push(options);
|
|
188
|
+
await fs.writeFile(options.path, 'engine-png');
|
|
189
|
+
return Buffer.from('engine-png');
|
|
190
|
+
};
|
|
191
|
+
const [, shot] = await writeFailureArtifacts({
|
|
192
|
+
page,
|
|
193
|
+
error: new Error('broken'),
|
|
194
|
+
testId: 'resized',
|
|
195
|
+
engine,
|
|
196
|
+
artifactsDir: directory.path,
|
|
197
|
+
});
|
|
198
|
+
assert.ok(shot.endsWith('.png'), shot);
|
|
199
|
+
return (await fs.readFile(shot)).toString();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
for (const engine of ['playwright', 'puppeteer']) {
|
|
203
|
+
it(`${engine} without a fixed viewport sends no clip`, async () => {
|
|
204
|
+
const { page, calls } = cdpFake({ engine });
|
|
205
|
+
page.engineCalls = calls.engine;
|
|
206
|
+
assert.equal(await failureShot(page, engine), 'cdp-png');
|
|
207
|
+
assertViewCapture(calls);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
for (const [name, engine, viewport] of [
|
|
212
|
+
['playwright with a fixed viewport', 'playwright', { width: 8, height: 6 }],
|
|
213
|
+
['puppeteer with a fixed viewport', 'puppeteer', { width: 8, height: 6 }],
|
|
214
|
+
['selenium', 'selenium', null],
|
|
215
|
+
]) {
|
|
216
|
+
it(`${name} keeps the engine screenshot`, async () => {
|
|
217
|
+
const page =
|
|
218
|
+
engine === 'selenium' ? {} : cdpFake({ engine, viewport }).page;
|
|
219
|
+
page.engineCalls = [];
|
|
220
|
+
assert.equal(await failureShot(page, engine), 'engine-png');
|
|
221
|
+
assert.equal(page.engineCalls.length, 1);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
});
|