diff --git a/packages/integration-tests/suites/replay/errorResponse/test.ts b/packages/integration-tests/suites/replay/errorResponse/test.ts index d81d16196b8e..2c40666096ee 100644 --- a/packages/integration-tests/suites/replay/errorResponse/test.ts +++ b/packages/integration-tests/suites/replay/errorResponse/test.ts @@ -39,6 +39,5 @@ sentryTest('should stop recording after receiving an error response', async ({ g const replay = await getReplaySnapshot(page); - // @ts-ignore private API expect(replay._isEnabled).toBe(false); }); diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts b/packages/integration-tests/suites/replay/sessionInactive/test.ts index e4a1e6d8b243..ed53f155feea 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts @@ -52,9 +52,7 @@ sentryTest('handles an inactive session', async ({ getLocalTestPath, page }) => // nothing happened because no activity/inactivity was detected const replay = await getReplaySnapshot(page); - // @ts-ignore private api expect(replay._isEnabled).toEqual(true); - // @ts-ignore private api expect(replay._isPaused).toEqual(false); // Now we trigger a blur event, which should move the session to paused mode @@ -63,9 +61,7 @@ sentryTest('handles an inactive session', async ({ getLocalTestPath, page }) => }); const replay2 = await getReplaySnapshot(page); - // @ts-ignore private api expect(replay2._isEnabled).toEqual(true); - // @ts-ignore private api expect(replay2._isPaused).toEqual(true); // Trigger an action, should re-start the recording @@ -73,9 +69,7 @@ sentryTest('handles an inactive session', async ({ getLocalTestPath, page }) => const req1 = await reqPromise1; const replay3 = await getReplaySnapshot(page); - // @ts-ignore private api expect(replay3._isEnabled).toEqual(true); - // @ts-ignore private api expect(replay3._isPaused).toEqual(false); const replayEvent1 = getReplayEvent(req1); diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/init.js b/packages/integration-tests/suites/replay/sessionMaxAge/init.js new file mode 100644 index 000000000000..cf98205a5576 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/init.js @@ -0,0 +1,22 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; +window.Replay = new Sentry.Replay({ + flushMinDelay: 500, + flushMaxDelay: 500, +}); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + sampleRate: 0, + replaysSessionSampleRate: 1.0, + replaysOnErrorSampleRate: 0.0, + debug: true, + + integrations: [window.Replay], +}); + +window.Replay._replay.timeouts = { + sessionIdle: 300000, // default: 5min + maxSessionLife: 4000, // this is usually 60min, but we want to test this with shorter times +}; diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/template.html b/packages/integration-tests/suites/replay/sessionMaxAge/template.html new file mode 100644 index 000000000000..7223a20f82ba --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/template.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts new file mode 100644 index 000000000000..89ad76ea4d4a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts @@ -0,0 +1,89 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../utils/fixtures'; +import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates'; +import { + getFullRecordingSnapshots, + getReplayEvent, + getReplaySnapshot, + normalize, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; + +// Session should be max. 4s long +const SESSION_MAX_AGE = 4000; + +/* + The main difference between this and sessionExpiry test, is that here we wait for the overall time (4s) + in multiple steps (2s, 2s) instead of waiting for the whole time at once (4s). +*/ +sentryTest('handles session that exceeds max age', async ({ getLocalTestPath, page }) => { + if (shouldSkipReplayTest()) { + sentryTest.skip(); + } + + const reqPromise0 = waitForReplayRequest(page, 0); + const reqPromise1 = waitForReplayRequest(page, 1); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + + const replay0 = await getReplaySnapshot(page); + // We use the `initialTimestamp` of the replay to do any time based calculations + const startTimestamp = replay0._context.initialTimestamp; + + const req0 = await reqPromise0; + + const replayEvent0 = getReplayEvent(req0); + expect(replayEvent0).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots0 = getFullRecordingSnapshots(req0); + expect(fullSnapshots0.length).toEqual(1); + const stringifiedSnapshot = normalize(fullSnapshots0[0]); + expect(stringifiedSnapshot).toMatchSnapshot('snapshot-0.json'); + + // Wait again for a new segment 0 (=new session) + const reqPromise2 = waitForReplayRequest(page, 0); + + // Wait for an incremental snapshot + // Wait half of the session max age (after initial flush), but account for potentially slow runners + const timePassed1 = Date.now() - startTimestamp; + await new Promise(resolve => setTimeout(resolve, Math.max(SESSION_MAX_AGE / 2 - timePassed1, 0))); + await page.click('#button1'); + + const req1 = await reqPromise1; + const replayEvent1 = getReplayEvent(req1); + + expect(replayEvent1).toEqual(getExpectedReplayEvent({ replay_start_timestamp: undefined, segment_id: 1, urls: [] })); + + const replay1 = await getReplaySnapshot(page); + const oldSessionId = replay1.session?.id; + + // Wait for session to expire + const timePassed2 = Date.now() - startTimestamp; + await new Promise(resolve => setTimeout(resolve, Math.max(SESSION_MAX_AGE - timePassed2, 0))); + await page.click('#button2'); + + const req2 = await reqPromise2; + const replay2 = await getReplaySnapshot(page); + + expect(replay2.session?.id).not.toEqual(oldSessionId); + + const replayEvent2 = getReplayEvent(req2); + expect(replayEvent2).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots2 = getFullRecordingSnapshots(req2); + expect(fullSnapshots2.length).toEqual(1); + const stringifiedSnapshot2 = normalize(fullSnapshots2[0]); + expect(stringifiedSnapshot2).toMatchSnapshot('snapshot-2.json'); +}); diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-chromium.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-chromium.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-chromium.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-firefox.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-firefox.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-firefox.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-webkit.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-webkit.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-webkit.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-chromium.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-chromium.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-chromium.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-firefox.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-firefox.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-firefox.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-webkit.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-webkit.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-webkit.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/utils/replayHelpers.ts b/packages/integration-tests/utils/replayHelpers.ts index a4dd02c068a4..c5c3e1f50ae9 100644 --- a/packages/integration-tests/utils/replayHelpers.ts +++ b/packages/integration-tests/utils/replayHelpers.ts @@ -1,4 +1,9 @@ -import type { RecordingEvent, ReplayContainer } from '@sentry/replay/build/npm/types/types'; +import type { + InternalEventContext, + RecordingEvent, + ReplayContainer, + Session, +} from '@sentry/replay/build/npm/types/types'; import type { eventWithTime } from '@sentry/replay/build/npm/types/types/rrweb'; import type { Breadcrumb, Event, ReplayEvent } from '@sentry/types'; import pako from 'pako'; @@ -67,9 +72,22 @@ export function isReplayEvent(event: Event): event is ReplayEvent { * Note that due to how this works with playwright, this is a POJO copy of replay. * This means that we cannot access any methods on it, and also not mutate it in any way. */ -export async function getReplaySnapshot(page: Page): Promise { - const replayIntegration = await page.evaluate<{ _replay: ReplayContainer }>('window.Replay'); - return replayIntegration._replay; +export async function getReplaySnapshot( + page: Page, +): Promise<{ _isPaused: boolean; _isEnabled: boolean; _context: InternalEventContext; session: Session | undefined }> { + return await page.evaluate(() => { + const replayIntegration = (window as unknown as Window & { Replay: { _replay: ReplayContainer } }).Replay; + const replay = replayIntegration._replay; + + const replaySnapshot = { + _isPaused: replay.isPaused(), + _isEnabled: replay.isEnabled(), + _context: replay.getContext(), + session: replay.session, + }; + + return replaySnapshot; + }); } export const REPLAY_DEFAULT_FLUSH_MAX_DELAY = 5_000; diff --git a/rollup/plugins/bundlePlugins.js b/rollup/plugins/bundlePlugins.js index 752b3908f2e8..49dcaefbdf73 100644 --- a/rollup/plugins/bundlePlugins.js +++ b/rollup/plugins/bundlePlugins.js @@ -118,8 +118,6 @@ export function makeTerserPlugin() { '_support', // We want to keep some replay fields unmangled to enable integration tests to access them '_replay', - '_isEnabled', - '_isPaused', // We also can't mangle rrweb private fields when bundling rrweb in the replay CDN bundles '_cssText', // We want to keep the _integrations variable unmangled to send all installed integrations from replay