diff --git a/packages/trace-viewer/src/sw.ts b/packages/trace-viewer/src/sw.ts index 841056f45746c..14d26c2a36c3b 100644 --- a/packages/trace-viewer/src/sw.ts +++ b/packages/trace-viewer/src/sw.ts @@ -19,6 +19,7 @@ import { unwrapPopoutUrl } from './snapshotRenderer'; import { SnapshotServer } from './snapshotServer'; import { TraceModel } from './traceModel'; import { FetchTraceModelBackend, ZipTraceModelBackend } from './traceModelBackends'; +import { TraceVersionError } from './traceModernizer'; // @ts-ignore declare const self: ServiceWorkerGlobalScope; @@ -57,6 +58,8 @@ async function loadTrace(traceUrl: string, traceFileName: string | null, clientI 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.'); + if (error instanceof TraceVersionError) + throw new Error(`Could not load trace from ${traceFileName || traceUrl}. ${error.message}`); if (traceFileName) throw new Error(`Could not load trace from ${traceFileName}. Make sure to upload a valid Playwright trace.`); throw new Error(`Could not load trace from ${traceUrl}. Make sure a valid Playwright Trace is accessible over this url.`); diff --git a/packages/trace-viewer/src/traceModernizer.ts b/packages/trace-viewer/src/traceModernizer.ts index a2a987318cd24..e7c65ac41fca1 100644 --- a/packages/trace-viewer/src/traceModernizer.ts +++ b/packages/trace-viewer/src/traceModernizer.ts @@ -22,6 +22,15 @@ import type * as traceV6 from './versions/traceV6'; import type { ActionEntry, ContextEntry, PageEntry } from './entries'; import type { SnapshotStorage } from './snapshotStorage'; +export class TraceVersionError extends Error { + constructor(message: string) { + super(message); + this.name = 'TraceVersionError'; + } +} + +const latestVersion: trace.VERSION = 7; + export class TraceModernizer { private _contextEntry: ContextEntry; private _snapshotStorage: SnapshotStorage; @@ -71,6 +80,8 @@ export class TraceModernizer { const contextEntry = this._contextEntry; switch (event.type) { case 'context-options': { + if (event.version > latestVersion) + throw new TraceVersionError('The trace was created by a newer version of Playwright and is not supported by this version of the viewer. Please use latest Playwright to open the trace.'); this._version = event.version; contextEntry.origin = event.origin; contextEntry.browserName = event.browserName; @@ -181,9 +192,8 @@ export class TraceModernizer { let version = this._version || event.version; if (version === undefined) return [event]; - const lastVersion: trace.VERSION = 7; let events = [event]; - for (; version < lastVersion; ++version) + for (; version < latestVersion; ++version) events = (this as any)[`_modernize_${version}_to_${version + 1}`].call(this, events); return events; } diff --git a/tests/assets/trace-from-the-future.zip b/tests/assets/trace-from-the-future.zip new file mode 100644 index 0000000000000..4100bf93c6305 Binary files /dev/null and b/tests/assets/trace-from-the-future.zip differ diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 01e68269ec9c2..1b31c904c1437 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -120,6 +120,11 @@ test('should open simple trace viewer', async ({ showTraceViewer }) => { ]); }); +test('should complain about newer version of trace in old viewer', async ({ showTraceViewer, asset }, testInfo) => { + const traceViewer = await showTraceViewer([asset('trace-from-the-future.zip')]); + await expect(traceViewer.page.getByText('The trace was created by a newer version of Playwright and is not supported by this version of the viewer.')).toBeVisible(); +}); + test('should contain action info', async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer([traceFile]); await traceViewer.selectAction('locator.click');