store screenshots in zip file
This commit is contained in:
parent
651f5a3ea4
commit
f7420c651c
|
|
@ -151,6 +151,14 @@ export class Snapshotter {
|
|||
snapshot.resourceOverrides.push({ url, ref: content });
|
||||
}
|
||||
}
|
||||
|
||||
for (const [sha1, contents] of Object.entries(data.canvasRenderResults)) {
|
||||
this._delegate.onSnapshotterBlob({
|
||||
sha1, buffer: Buffer.from(contents, 'base64')
|
||||
});
|
||||
snapshot.resourceOverrides.push({ url: 'TODO: this is required but unused', sha1 });
|
||||
}
|
||||
|
||||
this._delegate.onFrameSnapshot(snapshot);
|
||||
});
|
||||
await Promise.all(snapshots);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ export type SnapshotData = {
|
|||
url: string,
|
||||
timestamp: number,
|
||||
collectionTime: number,
|
||||
canvasRenderResults: Record<string, string>,
|
||||
};
|
||||
|
||||
export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript: boolean) {
|
||||
|
|
@ -86,6 +87,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript:
|
|||
private _readingStyleSheet = false; // To avoid invalidating due to our own reads.
|
||||
private _fakeBase: HTMLBaseElement;
|
||||
private _observer: MutationObserver;
|
||||
private _capturedCanvases = new Set<string>();
|
||||
|
||||
constructor() {
|
||||
const invalidateCSSGroupingRule = (rule: CSSGroupingRule) => {
|
||||
|
|
@ -319,14 +321,15 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript:
|
|||
this._handleMutations(this._observer.takeRecords());
|
||||
|
||||
const definedCustomElements = new Set<string>();
|
||||
const canvasRenderResults: Record<string, string> = {};
|
||||
|
||||
const visitNode = (node: Node | ShadowRoot): { equals: boolean, n: NodeSnapshot } | undefined => {
|
||||
const nodeType = node.nodeType;
|
||||
const nodeName = nodeType === Node.DOCUMENT_FRAGMENT_NODE ? 'template' : node.nodeName;
|
||||
|
||||
if (nodeType !== Node.ELEMENT_NODE &&
|
||||
nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
|
||||
nodeType !== Node.TEXT_NODE)
|
||||
nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
|
||||
nodeType !== Node.TEXT_NODE)
|
||||
return;
|
||||
if (nodeName === 'SCRIPT')
|
||||
return;
|
||||
|
|
@ -406,7 +409,19 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript:
|
|||
|
||||
if (nodeName === 'CANVAS') {
|
||||
const canvas = node as HTMLCanvasElement;
|
||||
attrs['__playwright_canvas_'] = canvas.toDataURL('image/webp', 1);
|
||||
const requestedMIME = 'image/webp';
|
||||
const dataURL = canvas.toDataURL(requestedMIME);
|
||||
const actualMIME = dataURL.substring('data:'.length, dataURL.indexOf(';'));
|
||||
const contentsB64 = dataURL.substring(dataURL.indexOf(',') + 1);
|
||||
const sha = '' + contentsB64.length; // TODO
|
||||
|
||||
attrs['__playwright_canvas_sha_'] = sha;
|
||||
attrs['__playwright_canvas_mime_'] = actualMIME;
|
||||
|
||||
if (!this._capturedCanvases.has(sha)) {
|
||||
this._capturedCanvases.add(sha);
|
||||
canvasRenderResults[sha] = contentsB64;
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeType === Node.DOCUMENT_FRAGMENT_NODE)
|
||||
|
|
@ -579,6 +594,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript:
|
|||
url: location.href,
|
||||
timestamp,
|
||||
collectionTime: 0,
|
||||
canvasRenderResults,
|
||||
};
|
||||
|
||||
for (const sheet of this._staleStyleSheets) {
|
||||
|
|
|
|||
|
|
@ -285,7 +285,13 @@ function snapshotScript(...targetIds: (string | undefined)[]) {
|
|||
const context = canvas.getContext('2d');
|
||||
context?.drawImage(img, 0, 0);
|
||||
};
|
||||
img.src = canvas.getAttribute('__playwright_canvas_')!;
|
||||
const url = new URL(window.location.href);
|
||||
const index = url.pathname.lastIndexOf('/snapshot/');
|
||||
if (index !== -1)
|
||||
url.pathname = url.pathname.substring(0, index + 1);
|
||||
url.pathname += `sha1/${canvas.getAttribute('__playwright_canvas_sha_')}`;
|
||||
url.searchParams.set('ct', canvas.getAttribute('__playwright_canvas_mime_')!);
|
||||
img.src = url.toString();
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ async function doFetch(event: FetchEvent): Promise<Response> {
|
|||
// Sha1 for sources is based on the file path, can't load it of a random model.
|
||||
const sha1 = relativePath.slice('/sha1/'.length);
|
||||
for (const trace of loadedTraces.values()) {
|
||||
const blob = await trace.traceModel.resourceForSha1(sha1);
|
||||
const blob = await trace.traceModel.resourceForSha1(sha1, url.searchParams.get('ct'));
|
||||
if (blob)
|
||||
return new Response(blob, { status: 200, headers: downloadHeaders(url.searchParams) });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,11 +112,11 @@ export class TraceModel {
|
|||
return this._backend.hasEntry(filename);
|
||||
}
|
||||
|
||||
async resourceForSha1(sha1: string): Promise<Blob | undefined> {
|
||||
async resourceForSha1(sha1: string, contentTypeOverride?: string | null): Promise<Blob | undefined> {
|
||||
const blob = await this._backend.readBlob('resources/' + sha1);
|
||||
if (!blob)
|
||||
return;
|
||||
return new Blob([blob], { type: this._resourceToContentType.get(sha1) || 'application/octet-stream' });
|
||||
return new Blob([blob], { type: contentTypeOverride || this._resourceToContentType.get(sha1) || 'application/octet-stream' });
|
||||
}
|
||||
|
||||
storage(): SnapshotStorage {
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 8.7 KiB |
Loading…
Reference in a new issue