feat(tracing): record canvas screenshots

This commit is contained in:
Simon Knott 2024-08-06 16:00:00 +02:00
parent dbc4bc84d6
commit 651f5a3ea4
No known key found for this signature in database
GPG key ID: 8CEDC00028084AEC
12 changed files with 38 additions and 2 deletions

View file

@ -107,7 +107,7 @@ export class Snapshotter {
async captureSnapshot(page: Page, callId: string, snapshotName: string, element?: ElementHandle): Promise<void> {
// Prepare expression synchronously.
const expression = `window["${this._snapshotStreamer}"].captureSnapshot(${JSON.stringify(snapshotName)})`;
const expression = `window["${this._snapshotStreamer}"].captureSnapshot()`;
// In a best-effort manner, without waiting for it, mark target element.
element?.callFunctionNoReply((element: Element, callId: string) => {

View file

@ -404,6 +404,11 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript:
}
};
if (nodeName === 'CANVAS') {
const canvas = node as HTMLCanvasElement;
attrs['__playwright_canvas_'] = canvas.toDataURL('image/webp', 1);
}
if (nodeType === Node.DOCUMENT_FRAGMENT_NODE)
attrs[kShadowAttribute] = 'open';

View file

@ -278,6 +278,16 @@ function snapshotScript(...targetIds: (string | undefined)[]) {
}
}
for (const element of root.querySelectorAll('canvas')) {
const canvas = element as HTMLCanvasElement;
const img = new Image();
img.onload = () => {
const context = canvas.getContext('2d');
context?.drawImage(img, 0, 0);
};
img.src = canvas.getAttribute('__playwright_canvas_')!;
}
{
const body = root.querySelector(`body[__playwright_custom_elements__]`);
if (body && window.customElements) {

View file

@ -35,8 +35,9 @@ function attributeSetFloats(gl, prog, attr_name, rsize, arr) {
gl.vertexAttribPointer(attr, rsize, gl.FLOAT, false, 0, 0);
}
var preserveDrawingBuffer = new URLSearchParams(location.search).get('preserveDrawingBuffer') !== null
var gl = document.getElementById("webgl")
.getContext("experimental-webgl");
.getContext("webgl", { preserveDrawingBuffer });
gl.clearColor(0.8, 0.8, 0.8, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

View file

@ -237,6 +237,9 @@ export class TestServer {
filePath = path.join(this._dirPath, pathName.substring(1));
}
if (filePath.lastIndexOf('?') !== -1)
filePath = filePath.substring(0, filePath.lastIndexOf('?'));
if (this._cachedPathPrefix !== null && filePath.startsWith(this._cachedPathPrefix)) {
if (request.headers['if-modified-since']) {
response.statusCode = 304; // not modified

View file

@ -1378,3 +1378,20 @@ test('should show baseURL in metadata pane', {
await traceViewer.showMetadataTab();
await expect(traceViewer.metadataTab).toContainText('baseURL:https://example.com');
});
test.describe('should show canvas', () => {
test('works for 2D', async ({ page, runAndTrace, server }) => {
const traceViewer = await runAndTrace(async () => {
await page.goto(server.PREFIX + '/screenshots/canvas.html');
});
await expect(traceViewer.snapshotContainer).toHaveScreenshot();
});
test('webgl works with preserveDrawingBuffer', async ({ runAndTrace, page, server }) => {
const traceViewer = await runAndTrace(async () => {
await page.goto(server.PREFIX + '/screenshots/webgl.html?preserveDrawingBuffer');
});
await expect(traceViewer.snapshotContainer).toHaveScreenshot();
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB