mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: custom error if HTML report gets uploaded in Trace Viewer (#17558)
Fixes https://github.com/microsoft/playwright/issues/17309
This commit is contained in:
parent
d6dbfe547f
commit
cf75f8ca20
@ -35,15 +35,27 @@ const loadedTraces = new Map<string, { traceModel: TraceModel, snapshotServer: S
|
|||||||
|
|
||||||
const clientIdToTraceUrls = new MultiMap<string, string>();
|
const clientIdToTraceUrls = new MultiMap<string, string>();
|
||||||
|
|
||||||
async function loadTrace(trace: string, clientId: string, progress: (done: number, total: number) => void): Promise<TraceModel> {
|
async function loadTrace(traceUrl: string, traceFileName: string | null, clientId: string, progress: (done: number, total: number) => void): Promise<TraceModel> {
|
||||||
const entry = loadedTraces.get(trace);
|
const entry = loadedTraces.get(traceUrl);
|
||||||
clientIdToTraceUrls.set(clientId, trace);
|
clientIdToTraceUrls.set(clientId, traceUrl);
|
||||||
if (entry)
|
if (entry)
|
||||||
return entry.traceModel;
|
return entry.traceModel;
|
||||||
const traceModel = new TraceModel();
|
const traceModel = new TraceModel();
|
||||||
await traceModel.load(trace, progress);
|
try {
|
||||||
|
await traceModel.load(traceUrl, progress);
|
||||||
|
} catch (error: any) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
if (error?.message?.includes('Cannot find .trace file') && await traceModel.hasEntry('index.html'))
|
||||||
|
throw new Error('Could not load trace. Did you upload a Playwright HTML report instead? Make sure to extract the archive first and then double-click the index.html file or put it on a web server.');
|
||||||
|
else if (traceFileName)
|
||||||
|
throw new Error(`Could not load trace from ${traceFileName}. Make sure to upload a valid Playwright trace.`);
|
||||||
|
else
|
||||||
|
throw new Error(`Could not load trace from ${traceUrl}. Make sure a valid Playwright Trace is accessible over this url.`);
|
||||||
|
}
|
||||||
const snapshotServer = new SnapshotServer(traceModel.storage());
|
const snapshotServer = new SnapshotServer(traceModel.storage());
|
||||||
loadedTraces.set(trace, { traceModel, snapshotServer });
|
loadedTraces.set(traceUrl, { traceModel, snapshotServer });
|
||||||
return traceModel;
|
return traceModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,21 +77,15 @@ async function doFetch(event: FetchEvent): Promise<Response> {
|
|||||||
|
|
||||||
if (relativePath === '/context') {
|
if (relativePath === '/context') {
|
||||||
try {
|
try {
|
||||||
const traceModel = await loadTrace(traceUrl, event.clientId, (done: number, total: number) => {
|
const traceModel = await loadTrace(traceUrl, url.searchParams.get('traceFileName'), event.clientId, (done: number, total: number) => {
|
||||||
client.postMessage({ method: 'progress', params: { done, total } });
|
client.postMessage({ method: 'progress', params: { done, total } });
|
||||||
});
|
});
|
||||||
return new Response(JSON.stringify(traceModel!.contextEntry), {
|
return new Response(JSON.stringify(traceModel!.contextEntry), {
|
||||||
status: 200,
|
status: 200,
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: any) {
|
||||||
// eslint-disable-next-line no-console
|
return new Response(JSON.stringify({ error: error?.message }), {
|
||||||
console.error(error);
|
|
||||||
const traceFileName = url.searchParams.get('traceFileName')!;
|
|
||||||
return new Response(JSON.stringify({
|
|
||||||
error: traceFileName ? `Could not load trace from ${traceFileName}. Make sure to upload a valid Playwright trace.` :
|
|
||||||
`Could not load trace from ${traceUrl}. Make sure a valid Playwright Trace is accessible over this url.`,
|
|
||||||
}), {
|
|
||||||
status: 500,
|
status: 500,
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
|
|||||||
@ -31,6 +31,7 @@ export class TraceModel {
|
|||||||
private _snapshotStorage: PersistentSnapshotStorage | undefined;
|
private _snapshotStorage: PersistentSnapshotStorage | undefined;
|
||||||
private _entries = new Map<string, zip.Entry>();
|
private _entries = new Map<string, zip.Entry>();
|
||||||
private _version: number | undefined;
|
private _version: number | undefined;
|
||||||
|
private _zipReader: zip.ZipReader | undefined;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.contextEntry = createEmptyContext();
|
this.contextEntry = createEmptyContext();
|
||||||
@ -46,12 +47,12 @@ export class TraceModel {
|
|||||||
|
|
||||||
async load(traceURL: string, progress: (done: number, total: number) => void) {
|
async load(traceURL: string, progress: (done: number, total: number) => void) {
|
||||||
this.contextEntry.traceUrl = traceURL;
|
this.contextEntry.traceUrl = traceURL;
|
||||||
const zipReader = new zipjs.ZipReader( // @ts-ignore
|
this._zipReader = new zipjs.ZipReader( // @ts-ignore
|
||||||
new zipjs.HttpReader(this._formatUrl(traceURL), { mode: 'cors', preventHeadRequest: true }),
|
new zipjs.HttpReader(this._formatUrl(traceURL), { mode: 'cors', preventHeadRequest: true }),
|
||||||
{ useWebWorkers: false }) as zip.ZipReader;
|
{ useWebWorkers: false }) as zip.ZipReader;
|
||||||
let traceEntry: zip.Entry | undefined;
|
let traceEntry: zip.Entry | undefined;
|
||||||
let networkEntry: zip.Entry | undefined;
|
let networkEntry: zip.Entry | undefined;
|
||||||
for (const entry of await zipReader.getEntries({ onprogress: progress })) {
|
for (const entry of await this._zipReader.getEntries({ onprogress: progress })) {
|
||||||
if (entry.filename.endsWith('.trace'))
|
if (entry.filename.endsWith('.trace'))
|
||||||
traceEntry = entry;
|
traceEntry = entry;
|
||||||
if (entry.filename.endsWith('.network'))
|
if (entry.filename.endsWith('.network'))
|
||||||
@ -60,10 +61,13 @@ export class TraceModel {
|
|||||||
this.contextEntry.hasSource = true;
|
this.contextEntry.hasSource = true;
|
||||||
this._entries.set(entry.filename, entry);
|
this._entries.set(entry.filename, entry);
|
||||||
}
|
}
|
||||||
|
if (!traceEntry)
|
||||||
|
throw new Error('Cannot find .trace file');
|
||||||
|
|
||||||
this._snapshotStorage = new PersistentSnapshotStorage(this._entries);
|
this._snapshotStorage = new PersistentSnapshotStorage(this._entries);
|
||||||
|
|
||||||
const traceWriter = new zipjs.TextWriter() as zip.TextWriter;
|
const traceWriter = new zipjs.TextWriter() as zip.TextWriter;
|
||||||
await traceEntry!.getData!(traceWriter);
|
await traceEntry.getData!(traceWriter);
|
||||||
for (const line of (await traceWriter.getData()).split('\n'))
|
for (const line of (await traceWriter.getData()).split('\n'))
|
||||||
this.appendEvent(line);
|
this.appendEvent(line);
|
||||||
|
|
||||||
@ -76,6 +80,16 @@ export class TraceModel {
|
|||||||
this._build();
|
this._build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async hasEntry(filename: string): Promise<boolean> {
|
||||||
|
if (!this._zipReader)
|
||||||
|
return false;
|
||||||
|
for (const entry of await this._zipReader.getEntries()) {
|
||||||
|
if (entry.filename === filename)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
async resourceForSha1(sha1: string): Promise<Blob | undefined> {
|
async resourceForSha1(sha1: string): Promise<Blob | undefined> {
|
||||||
const entry = this._entries.get('resources/' + sha1);
|
const entry = this._entries.get('resources/' + sha1);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
|
|||||||
@ -286,7 +286,7 @@ for (const webPackage of ['html-reporter', 'recorder', 'trace-viewer']) {
|
|||||||
`packages/web/src/`,
|
`packages/web/src/`,
|
||||||
],
|
],
|
||||||
command: 'npx',
|
command: 'npx',
|
||||||
args: ['vite', 'build'],
|
args: ['vite', 'build', ...(watchMode ? ['--sourcemap'] : [])],
|
||||||
cwd: path.join(__dirname, '..', '..', 'packages', webPackage),
|
cwd: path.join(__dirname, '..', '..', 'packages', webPackage),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -335,7 +335,7 @@ if (lintMode) {
|
|||||||
command: 'npx',
|
command: 'npx',
|
||||||
args: ['tsc', ...(watchMode ? ['-w'] : []), '-p', quotePath(filePath(`packages/${webPackage}`))],
|
args: ['tsc', ...(watchMode ? ['-w'] : []), '-p', quotePath(filePath(`packages/${webPackage}`))],
|
||||||
shell: true,
|
shell: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user