diff --git a/packages/e2e-tests/tests/repaint-02.test.ts b/packages/e2e-tests/tests/repaint-02.test.ts index 901ea128975..6f527269783 100644 --- a/packages/e2e-tests/tests/repaint-02.test.ts +++ b/packages/e2e-tests/tests/repaint-02.test.ts @@ -11,14 +11,14 @@ test("repaint-02: repaints on hover", async ({ }) => { await startTest(page, recordingId, testScope); - const initialScreenShot = await getGraphicsDataUrl(page); + const endingScreenShot = await getGraphicsDataUrl(page); const testLink = getTestRows(page).first(); await testLink.click(); - // Wait for the test to open and focus + // Wait for the test to open await waitFor(async () => { - await expect(await getGraphicsDataUrl(page)).not.toBe(initialScreenShot); + await expect(await getGraphicsDataUrl(page)).not.toBe(endingScreenShot); }); // By default, the screenshot shown should correspond to the start of the test diff --git a/packages/e2e-tests/tests/repaint-03.test.ts b/packages/e2e-tests/tests/repaint-03.test.ts index eb6c7a0a257..e6096256cd5 100644 --- a/packages/e2e-tests/tests/repaint-03.test.ts +++ b/packages/e2e-tests/tests/repaint-03.test.ts @@ -11,14 +11,13 @@ test("repaint-03: repaints on seek", async ({ pageWithMeta: { page, recordingId, await startTest(page, recordingId, testScope); const endingScreenShot = await getGraphicsDataUrl(page); - const initialFocusBeginTime = await getFocusBeginTime(page); const testLink = getTestRows(page).first(); await testLink.click(); - // Wait for the test to open and focus + // Wait for the test to open await waitFor(async () => { - await expect(await getFocusBeginTime(page)).not.toBe(initialFocusBeginTime); + await expect(await getGraphicsDataUrl(page)).not.toBe(endingScreenShot); }); // By default, the screenshot shown should correspond to the start of the test diff --git a/packages/shared/test-suites/RecordingTestMetadata.ts b/packages/shared/test-suites/RecordingTestMetadata.ts index da139e0a520..6dec8611c44 100644 --- a/packages/shared/test-suites/RecordingTestMetadata.ts +++ b/packages/shared/test-suites/RecordingTestMetadata.ts @@ -921,14 +921,9 @@ export async function processPlaywrightTestRecording( id, result, source, - timeStampedPointRange: getPlaywrightTestTimeStampedPointRange(events), + timeStampedPointRange: null, }; } else if (isTestRecordingV3(testRecording)) { - if (!testRecording.timeStampedPointRange) { - testRecording.timeStampedPointRange = getPlaywrightTestTimeStampedPointRange( - testRecording.events - ); - } return testRecording; } else { // This function does not support the legacy TestItem format @@ -936,7 +931,7 @@ export async function processPlaywrightTestRecording( } } -function getPlaywrightTestTimeStampedPointRange( +export function getPlaywrightTestTimeStampedPointRange( events: RecordingTestMetadataV3.TestRecording["events"] ) { const allEventsSections = Object.values(events); diff --git a/src/ui/components/TestSuite/views/TestRecording/Panel.tsx b/src/ui/components/TestSuite/views/TestRecording/Panel.tsx index 98a0631e2c5..20ff49fc8c0 100644 --- a/src/ui/components/TestSuite/views/TestRecording/Panel.tsx +++ b/src/ui/components/TestSuite/views/TestRecording/Panel.tsx @@ -49,21 +49,26 @@ export default function Panel() { }); // We only want to cache the test event details when the focus window has been updated - // to match the range of the test recording. Experimentation shows there can be some renders + // to match the range of the test recording in the case of Cypress tests. Experimentation shows there can be some renders // where the focus range and test range are mismatched, so try to avoid caching in those cases. + // + // Entering the panel in the case of Playwright recording doesn't change the focus range. + // Playwright recordings are usually much shorter given each page is recorded separately + // and it's OK to prefetch all of the test event details for them right away. const enableCache = - focusWindow && - testRecording.timeStampedPointRange?.begin && - isExecutionPointsWithinRange( - focusWindow.begin.point, - testRecording.timeStampedPointRange.begin.point, - testRecording.timeStampedPointRange.end.point - ) && - isExecutionPointsWithinRange( - focusWindow.end.point, - testRecording.timeStampedPointRange.begin.point, - testRecording.timeStampedPointRange.end.point - ); + testRecording.testRunnerName === "playwright" || + (focusWindow && + testRecording.timeStampedPointRange && + isExecutionPointsWithinRange( + focusWindow.begin.point, + testRecording.timeStampedPointRange.begin.point, + testRecording.timeStampedPointRange.end.point + ) && + isExecutionPointsWithinRange( + focusWindow.end.point, + testRecording.timeStampedPointRange.begin.point, + testRecording.timeStampedPointRange.end.point + )); useImperativeIntervalCacheValues( testEventDetailsIntervalCache, diff --git a/src/ui/components/TestSuite/views/TestRecording/useTestEventContextMenu.tsx b/src/ui/components/TestSuite/views/TestRecording/useTestEventContextMenu.tsx index 44f41599e93..2f4ba693094 100644 --- a/src/ui/components/TestSuite/views/TestRecording/useTestEventContextMenu.tsx +++ b/src/ui/components/TestSuite/views/TestRecording/useTestEventContextMenu.tsx @@ -111,7 +111,7 @@ function PlayToHereMenuItem({ testEvent }: { testEvent: TestEvent }) { const beginTimeStampedPoint = testRecording.timeStampedPointRange?.begin ?? null; const endPoint = getTestEventExecutionPoint(testEvent); - if (beginTimeStampedPoint == null || endPoint == null) { + if (endPoint == null) { return null; } @@ -120,7 +120,7 @@ function PlayToHereMenuItem({ testEvent }: { testEvent: TestEvent }) { dispatch( startPlayback({ - beginTime: beginTimeStampedPoint.time, + beginTime: beginTimeStampedPoint?.time ?? 0, endTime: getTestEventTime(testEvent), }) ); diff --git a/src/ui/components/TestSuite/views/TestSuiteContext.tsx b/src/ui/components/TestSuite/views/TestSuiteContext.tsx index 288557a2ab8..44be042acc2 100644 --- a/src/ui/components/TestSuite/views/TestSuiteContext.tsx +++ b/src/ui/components/TestSuite/views/TestSuiteContext.tsx @@ -11,7 +11,11 @@ import { import { FocusContext } from "replay-next/src/contexts/FocusContext"; import { SessionContext } from "replay-next/src/contexts/SessionContext"; import { TimelineContext } from "replay-next/src/contexts/TimelineContext"; -import { TestEvent, TestRecording } from "shared/test-suites/RecordingTestMetadata"; +import { + TestEvent, + TestRecording, + getPlaywrightTestTimeStampedPointRange, +} from "shared/test-suites/RecordingTestMetadata"; type TestSuiteContextType = { setTestRecording: (value: TestRecording | null) => Promise; @@ -57,8 +61,13 @@ export function TestSuiteContextRoot({ children }: PropsWithChildren) { sync: true, } ); - - seekToTime(timeStampedPointRange.begin.time, timeStampedPointRange.begin.point, false); + } + let beginPoint = timeStampedPointRange?.begin; + if (testRecording.testRunnerName === "playwright") { + beginPoint = getPlaywrightTestTimeStampedPointRange(testRecording.events)?.begin; + } + if (beginPoint) { + seekToTime(beginPoint.time, beginPoint.point, false); } } else { await updateForTimelineImprecise([0, duration], {