From 909a47cdbf7c618cf84ef4b2c64447e84107e80a Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 9 Sep 2024 10:53:36 +0200 Subject: [PATCH] use frameswap timestamp for finding screenshot --- .../src/server/trace/recorder/snapshotter.ts | 1 + .../server/trace/recorder/snapshotterInjected.ts | 2 ++ .../src/server/trace/recorder/tracing.ts | 3 ++- packages/trace-viewer/src/entries.ts | 1 + packages/trace-viewer/src/snapshotServer.ts | 1 + packages/trace-viewer/src/ui/snapshotTab.tsx | 16 ++++++++++------ packages/trace/src/snapshot.ts | 1 + packages/trace/src/trace.ts | 1 + 8 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/playwright-core/src/server/trace/recorder/snapshotter.ts b/packages/playwright-core/src/server/trace/recorder/snapshotter.ts index 48bfea7302..60d0e01836 100644 --- a/packages/playwright-core/src/server/trace/recorder/snapshotter.ts +++ b/packages/playwright-core/src/server/trace/recorder/snapshotter.ts @@ -137,6 +137,7 @@ export class Snapshotter { html: data.html, viewport: data.viewport, timestamp: monotonicTime(), + absoluteTimestamp: data.absoluteTimestamp, collectionTime: data.collectionTime, resourceOverrides: [], isMainFrame: page.mainFrame() === frame diff --git a/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts b/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts index 14e34c8aee..5c46810d22 100644 --- a/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts +++ b/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts @@ -28,6 +28,7 @@ export type SnapshotData = { viewport: { width: number, height: number }, url: string, timestamp: number, + absoluteTimestamp: number, // milliseconds since epoch collectionTime: number, }; @@ -573,6 +574,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript: }, url: location.href, timestamp, + absoluteTimestamp: Date.now(), collectionTime: 0, }; diff --git a/packages/playwright-core/src/server/trace/recorder/tracing.ts b/packages/playwright-core/src/server/trace/recorder/tracing.ts index 1dec4f536a..395b64c254 100644 --- a/packages/playwright-core/src/server/trace/recorder/tracing.ts +++ b/packages/playwright-core/src/server/trace/recorder/tracing.ts @@ -472,7 +472,8 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps sha1, width: params.width, height: params.height, - timestamp: monotonicTime() + timestamp: monotonicTime(), + frameSwapTimestamp: params.timestamp ? params.timestamp * 1000 : undefined, }; // Make sure to write the screencast frame before adding a reference to it. this._appendResource(sha1, params.buffer); diff --git a/packages/trace-viewer/src/entries.ts b/packages/trace-viewer/src/entries.ts index 98d39927f7..98f7eef78f 100644 --- a/packages/trace-viewer/src/entries.ts +++ b/packages/trace-viewer/src/entries.ts @@ -45,6 +45,7 @@ export type PageEntry = { screencastFrames: { sha1: string, timestamp: number, + frameSwapTimestamp?: number, width: number, height: number, }[]; diff --git a/packages/trace-viewer/src/snapshotServer.ts b/packages/trace-viewer/src/snapshotServer.ts index d41dcbdbbd..48ed34119e 100644 --- a/packages/trace-viewer/src/snapshotServer.ts +++ b/packages/trace-viewer/src/snapshotServer.ts @@ -46,6 +46,7 @@ export class SnapshotServer { viewport: snapshot.viewport(), url: snapshot.snapshot().frameUrl, timestamp: snapshot.snapshot().timestamp, + absoluteTimestamp: snapshot.snapshot().absoluteTimestamp, } : { error: 'No snapshot found' }); diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index 229d9f8cef..790c731b3a 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -30,12 +30,12 @@ import { locatorOrSelectorAsSelector } from '@isomorphic/locatorParser'; import { TabbedPaneTab } from '@web/components/tabbedPane'; import { BrowserFrame } from './browserFrame'; -function findClosest(items: T[], target: number) { +function findClosest(items: T[], metric: (v: T) => number, target: number) { return items.find((item, index) => { if (index === items.length - 1) return true; const next = items[index + 1]; - return Math.abs(item.timestamp - target) < Math.abs(next.timestamp - target); + return Math.abs(metric(item) - target) < Math.abs(metric(next) - target); }); } @@ -101,7 +101,7 @@ export const SnapshotTab: React.FunctionComponent<{ const iframeRef0 = React.useRef(null); const iframeRef1 = React.useRef(null); - const [snapshotInfo, setSnapshotInfo] = React.useState<{ viewport: typeof kDefaultViewport, url: string, timestamp?: number }>({ viewport: kDefaultViewport, url: '', timestamp: undefined }); + const [snapshotInfo, setSnapshotInfo] = React.useState<{ viewport: typeof kDefaultViewport, url: string, timestamp?: number, absoluteTimestamp?: undefined }>({ viewport: kDefaultViewport, url: '' }); const loadingRef = React.useRef({ iteration: 0, visibleIframe: 0 }); React.useEffect(() => { @@ -110,7 +110,7 @@ export const SnapshotTab: React.FunctionComponent<{ const newVisibleIframe = 1 - loadingRef.current.visibleIframe; loadingRef.current.iteration = thisIteration; - const newSnapshotInfo = { url: '', viewport: kDefaultViewport, timestamp: undefined }; + const newSnapshotInfo = { url: '', viewport: kDefaultViewport, timestamp: undefined, absoluteTimestamp: undefined }; if (snapshotInfoUrl) { const response = await fetch(snapshotInfoUrl); const info = await response.json(); @@ -118,6 +118,7 @@ export const SnapshotTab: React.FunctionComponent<{ newSnapshotInfo.url = info.url; newSnapshotInfo.viewport = info.viewport; newSnapshotInfo.timestamp = info.timestamp; + newSnapshotInfo.absoluteTimestamp = info.absoluteTimestamp; } } @@ -169,10 +170,13 @@ export const SnapshotTab: React.FunctionComponent<{ const page = action ? pageForAction(action) : undefined; const screencastFrame = React.useMemo( () => { + if (snapshotInfo.absoluteTimestamp && page?.screencastFrames[0]?.frameSwapTimestamp) + return findClosest(page.screencastFrames, frame => frame.frameSwapTimestamp!, snapshotInfo.absoluteTimestamp); + if (snapshotInfo.timestamp && page?.screencastFrames) - return findClosest(page.screencastFrames, snapshotInfo.timestamp); + return findClosest(page.screencastFrames, frame => frame.timestamp, snapshotInfo.timestamp); }, - [page?.screencastFrames, snapshotInfo.timestamp] + [page?.screencastFrames, snapshotInfo.timestamp, snapshotInfo.absoluteTimestamp] ); return