diff --git a/packages/replay/src/replay.ts b/packages/replay/src/replay.ts index 30ccda422544..0d3d40fb94dc 100644 --- a/packages/replay/src/replay.ts +++ b/packages/replay/src/replay.ts @@ -27,6 +27,7 @@ import { clearSession } from './session/clearSession'; import { loadOrCreateSession } from './session/loadOrCreateSession'; import { saveSession } from './session/saveSession'; import { shouldRefreshSession } from './session/shouldRefreshSession'; + import type { AddEventResult, AddUpdateCallback, @@ -294,6 +295,12 @@ export class ReplayContainer implements ReplayContainerInterface { logInfoNextTick('[Replay] Starting replay in session mode', this._options._experiments.traceInternals); + // Required as user activity is initially set in + // constructor, so if `start()` is called after + // session idle expiration, a replay will not be + // created due to an idle timeout. + this._updateUserActivity(); + const session = loadOrCreateSession( { maxReplayDuration: this._options.maxReplayDuration, diff --git a/packages/replay/test/integration/beforeAddRecordingEvent.test.ts b/packages/replay/test/integration/beforeAddRecordingEvent.test.ts index e6800f4e53d0..035d566def43 100644 --- a/packages/replay/test/integration/beforeAddRecordingEvent.test.ts +++ b/packages/replay/test/integration/beforeAddRecordingEvent.test.ts @@ -2,8 +2,7 @@ import * as SentryCore from '@sentry/core'; import type { Transport } from '@sentry/types'; import * as SentryUtils from '@sentry/utils'; -// eslint-disable-next-line deprecation/deprecation -import type { Replay } from '../../src'; +import type { replayIntegration } from '../../src/integration'; import type { ReplayContainer } from '../../src/replay'; import { clearSession } from '../../src/session/clearSession'; import { createPerformanceEntries } from '../../src/util/createPerformanceEntries'; @@ -24,8 +23,7 @@ type MockTransportSend = jest.MockedFunction; describe('Integration | beforeAddRecordingEvent', () => { let replay: ReplayContainer; - // eslint-disable-next-line deprecation/deprecation - let integration: Replay; + let integration: ReturnType; let mockTransportSend: MockTransportSend; let mockSendReplayRequest: jest.SpyInstance; let domHandler: DomHandler; diff --git a/packages/replay/test/integration/start.test.ts b/packages/replay/test/integration/start.test.ts new file mode 100644 index 000000000000..7fbef9f8149c --- /dev/null +++ b/packages/replay/test/integration/start.test.ts @@ -0,0 +1,53 @@ +import { getClient } from '@sentry/core'; +import type { Transport } from '@sentry/types'; + +import { DEFAULT_FLUSH_MIN_DELAY, SESSION_IDLE_EXPIRE_DURATION } from '../../src/constants'; +import type { replayIntegration } from '../../src/integration'; +import type { ReplayContainer } from '../../src/replay'; +import { BASE_TIMESTAMP } from '../index'; +import { resetSdkMock } from '../mocks/resetSdkMock'; +import { useFakeTimers } from '../utils/use-fake-timers'; + +useFakeTimers(); + +describe('Integration | start', () => { + let replay: ReplayContainer; + let integration: ReturnType; + + beforeEach(async () => { + ({ replay, integration } = await resetSdkMock({ + replayOptions: { + stickySession: false, + }, + sentryOptions: { + replaysSessionSampleRate: 0.0, + }, + })); + + const mockTransport = getClient()?.getTransport()?.send as jest.MockedFunction; + mockTransport?.mockClear(); + jest.runAllTimers(); + await new Promise(process.nextTick); + }); + + afterEach(async () => { + integration.stop(); + + jest.runAllTimers(); + await new Promise(process.nextTick); + jest.setSystemTime(new Date(BASE_TIMESTAMP)); + }); + + it('sends replay when calling `start()` after [SESSION_IDLE_EXPIRE_DURATION]ms', async () => { + jest.advanceTimersByTime(SESSION_IDLE_EXPIRE_DURATION + 1); + + integration.start(); + + jest.advanceTimersByTime(DEFAULT_FLUSH_MIN_DELAY); + await new Promise(process.nextTick); + + expect(replay).toHaveLastSentReplay({ + recordingPayloadHeader: { segment_id: 0 }, + }); + }); +}); diff --git a/packages/replay/test/integration/stop.test.ts b/packages/replay/test/integration/stop.test.ts index 35bc44f0c80f..de0d212de8e9 100644 --- a/packages/replay/test/integration/stop.test.ts +++ b/packages/replay/test/integration/stop.test.ts @@ -1,8 +1,7 @@ import * as SentryUtils from '@sentry/utils'; -// eslint-disable-next-line deprecation/deprecation -import type { Replay } from '../../src'; import { WINDOW } from '../../src/constants'; +import type { replayIntegration } from '../../src/integration'; import type { ReplayContainer } from '../../src/replay'; import { clearSession } from '../../src/session/clearSession'; import { addEvent } from '../../src/util/addEvent'; @@ -18,8 +17,7 @@ type MockRunFlush = jest.MockedFunction; describe('Integration | stop', () => { let replay: ReplayContainer; - // eslint-disable-next-line deprecation/deprecation - let integration: Replay; + let integration: ReturnType; const prevLocation = WINDOW.location; const { record: mockRecord } = mockRrweb();