diff --git a/packages/browser-integration-tests/utils/replayHelpers.ts b/packages/browser-integration-tests/utils/replayHelpers.ts index 5ddcf0c46e05..bbc02d50494f 100644 --- a/packages/browser-integration-tests/utils/replayHelpers.ts +++ b/packages/browser-integration-tests/utils/replayHelpers.ts @@ -1,12 +1,12 @@ import type { fullSnapshotEvent, incrementalSnapshotEvent } from '@sentry-internal/rrweb'; import { EventType } from '@sentry-internal/rrweb'; +import type { ReplayEventWithTime } from '@sentry/browser'; 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, ReplayRecordingMode } from '@sentry/types'; import pako from 'pako'; import type { Page, Request, Response } from 'playwright'; @@ -22,12 +22,12 @@ export type PerformanceSpan = { data: Record; }; -export type FullRecordingSnapshot = eventWithTime & { +export type FullRecordingSnapshot = ReplayEventWithTime & { timestamp: 0; data: fullSnapshotEvent['data']; }; -export type IncrementalRecordingSnapshot = eventWithTime & { +export type IncrementalRecordingSnapshot = ReplayEventWithTime & { timestamp: 0; data: incrementalSnapshotEvent['data']; }; @@ -270,7 +270,7 @@ function getOptionsEvents(replayRequest: Request): CustomRecordingEvent[] { export function getDecompressedRecordingEvents(resOrReq: Request | Response): RecordingSnapshot[] { const replayRequest = getRequest(resOrReq); return ( - (replayEnvelopeRequestParser(replayRequest, 5) as eventWithTime[]) + (replayEnvelopeRequestParser(replayRequest, 5) as ReplayEventWithTime[]) .sort((a, b) => a.timestamp - b.timestamp) // source 1 is MouseMove, which is a bit flaky and we don't care about .filter( diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 4ca6c7352261..60a2bef7a2f9 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -21,6 +21,18 @@ const INTEGRATIONS = { export { INTEGRATIONS as Integrations }; export { Replay } from '@sentry/replay'; +export type { + ReplayEventType, + ReplayEventWithTime, + ReplayBreadcrumbFrame, + ReplayBreadcrumbFrameEvent, + ReplayOptionFrameEvent, + ReplayFrame, + ReplayFrameEvent, + ReplaySpanFrame, + ReplaySpanFrameEvent, +} from '@sentry/replay'; + export { BrowserTracing, defaultRequestInstrumentationOptions, diff --git a/packages/replay/.eslintignore b/packages/replay/.eslintignore index 82f028e93347..c76c6c2d64d1 100644 --- a/packages/replay/.eslintignore +++ b/packages/replay/.eslintignore @@ -4,5 +4,3 @@ demo/build/ # TODO: Check if we can re-introduce linting in demo demo metrics -# For whatever reason, the eslint-ignore comment in this file is not working, so skipping this file -src/types/rrweb.ts diff --git a/packages/replay/.eslintrc.js b/packages/replay/.eslintrc.js index 6db928fcb1b9..4f69827ac50b 100644 --- a/packages/replay/.eslintrc.js +++ b/packages/replay/.eslintrc.js @@ -32,5 +32,11 @@ module.exports = { '@typescript-eslint/no-floating-promises': 'off', }, }, + { + files: ['src/types/deprecated.ts'], + rules: { + '@typescript-eslint/naming-convention': 'off', + }, + }, ], }; diff --git a/packages/replay/src/coreHandlers/handleClick.ts b/packages/replay/src/coreHandlers/handleClick.ts index c4243c1e7e1b..91928ea6ac3f 100644 --- a/packages/replay/src/coreHandlers/handleClick.ts +++ b/packages/replay/src/coreHandlers/handleClick.ts @@ -1,7 +1,13 @@ import type { Breadcrumb } from '@sentry/types'; import { WINDOW } from '../constants'; -import type { MultiClickFrame, ReplayClickDetector, ReplayContainer, SlowClickConfig, SlowClickFrame } from '../types'; +import type { + ReplayClickDetector, + ReplayContainer, + ReplayMultiClickFrame, + ReplaySlowClickFrame, + SlowClickConfig, +} from '../types'; import { timestampToS } from '../util/timestamp'; import { addBreadcrumbEvent } from './util/addBreadcrumbEvent'; import { getClickTargetNode } from './util/domUtils'; @@ -216,7 +222,7 @@ export class ClickDetector implements ReplayClickDetector { const timeAfterClickMs = Math.min(click.mutationAfter || this._timeout, this._timeout) * 1000; const endReason = timeAfterClickMs < this._timeout * 1000 ? 'mutation' : 'timeout'; - const breadcrumb: SlowClickFrame = { + const breadcrumb: ReplaySlowClickFrame = { type: 'default', message: clickBreadcrumb.message, timestamp: clickBreadcrumb.timestamp, @@ -239,7 +245,7 @@ export class ClickDetector implements ReplayClickDetector { // Multi click if (clickCount > 1) { - const breadcrumb: MultiClickFrame = { + const breadcrumb: ReplayMultiClickFrame = { type: 'default', message: clickBreadcrumb.message, timestamp: clickBreadcrumb.timestamp, diff --git a/packages/replay/src/index.ts b/packages/replay/src/index.ts index 3b05202fc541..412354f1dc54 100644 --- a/packages/replay/src/index.ts +++ b/packages/replay/src/index.ts @@ -1,12 +1,16 @@ export { Replay } from './integration'; + export type { - EventType, - eventWithTime, - BreadcrumbFrame, - BreadcrumbFrameEvent, - OptionFrameEvent, + ReplayEventType, + ReplayEventWithTime, + ReplayBreadcrumbFrame, + ReplayBreadcrumbFrameEvent, + ReplayOptionFrameEvent, ReplayFrame, ReplayFrameEvent, - SpanFrame, - SpanFrameEvent, + ReplaySpanFrame, + ReplaySpanFrameEvent, } from './types'; + +// TODO (v8): Remove deprecated types +export * from './types/deprecated'; diff --git a/packages/replay/src/replay.ts b/packages/replay/src/replay.ts index eec3edf45083..a96910e02f31 100644 --- a/packages/replay/src/replay.ts +++ b/packages/replay/src/replay.ts @@ -25,12 +25,12 @@ import type { AddEventResult, AddUpdateCallback, AllPerformanceEntry, - BreadcrumbFrame, EventBuffer, InternalEventContext, PopEventContext, RecordingEvent, RecordingOptions, + ReplayBreadcrumbFrame, ReplayContainer as ReplayContainerInterface, ReplayPluginOptions, SendBufferedReplayOptions, @@ -38,6 +38,7 @@ import type { SlowClickConfig, Timeouts, } from './types'; +import { ReplayEventTypeCustom } from './types'; import { addEvent } from './util/addEvent'; import { addGlobalListeners } from './util/addGlobalListeners'; import { addMemoryEntry } from './util/addMemoryEntry'; @@ -688,7 +689,7 @@ export class ReplayContainer implements ReplayContainerInterface { this.addUpdate(() => { void addEvent(this, { - type: EventType.Custom, + type: ReplayEventTypeCustom, timestamp: breadcrumb.timestamp || 0, data: { tag: 'breadcrumb', @@ -919,7 +920,7 @@ export class ReplayContainer implements ReplayContainerInterface { /** * Tasks to run when we consider a page to be hidden (via blurring and/or visibility) */ - private _doChangeToBackgroundTasks(breadcrumb?: BreadcrumbFrame): void { + private _doChangeToBackgroundTasks(breadcrumb?: ReplayBreadcrumbFrame): void { if (!this.session) { return; } @@ -939,7 +940,7 @@ export class ReplayContainer implements ReplayContainerInterface { /** * Tasks to run when we consider a page to be visible (via focus and/or visibility) */ - private _doChangeToForegroundTasks(breadcrumb?: BreadcrumbFrame): void { + private _doChangeToForegroundTasks(breadcrumb?: ReplayBreadcrumbFrame): void { if (!this.session) { return; } @@ -992,7 +993,7 @@ export class ReplayContainer implements ReplayContainerInterface { /** * Helper to create (and buffer) a replay breadcrumb from a core SDK breadcrumb */ - private _createCustomBreadcrumb(breadcrumb: BreadcrumbFrame): void { + private _createCustomBreadcrumb(breadcrumb: ReplayBreadcrumbFrame): void { this.addUpdate(() => { void this.throttledAddEvent({ type: EventType.Custom, diff --git a/packages/replay/src/types/deprecated.ts b/packages/replay/src/types/deprecated.ts new file mode 100644 index 000000000000..ff57070bf2ee --- /dev/null +++ b/packages/replay/src/types/deprecated.ts @@ -0,0 +1,30 @@ +import type { + ReplayBreadcrumbFrame, + ReplayBreadcrumbFrameEvent, + ReplayEventType, + ReplayEventWithTime, + ReplayOptionFrameEvent, + ReplaySpanFrame, + ReplaySpanFrameEvent, +} from '.'; + +/** @deprecated use ReplayEventType instead */ +export type EventType = ReplayEventType; + +/** @deprecated use ReplayEventWithTime instead */ +export type eventWithTime = ReplayEventWithTime; + +/** @deprecated use ReplayBreadcrumbFrame instead */ +export type BreadcrumbFrame = ReplayBreadcrumbFrame; + +/** @deprecated use ReplayBreadcrumbFrameEvent instead */ +export type BreadcrumbFrameEvent = ReplayBreadcrumbFrameEvent; + +/** @deprecated use ReplayOptionFrameEvent instead */ +export type OptionFrameEvent = ReplayOptionFrameEvent; + +/** @deprecated use ReplaySpanFrame instead */ +export type SpanFrame = ReplaySpanFrame; + +/** @deprecated use ReplaySpanFrameEvent instead */ +export type SpanFrameEvent = ReplaySpanFrameEvent; diff --git a/packages/replay/src/types/replay.ts b/packages/replay/src/types/replay.ts index 00f363003979..1ae48dfecfc3 100644 --- a/packages/replay/src/types/replay.ts +++ b/packages/replay/src/types/replay.ts @@ -13,10 +13,10 @@ import type { SKIPPED, THROTTLED } from '../util/throttle'; import type { AllPerformanceEntry } from './performance'; import type { ReplayFrameEvent } from './replayFrame'; import type { ReplayNetworkRequestOrResponse } from './request'; -import type { eventWithTime, recordOptions } from './rrweb'; +import type { ReplayEventWithTime, RrwebRecordOptions } from './rrweb'; -export type RecordingEvent = ReplayFrameEvent | eventWithTime; -export type RecordingOptions = recordOptions; +export type RecordingEvent = ReplayFrameEvent | ReplayEventWithTime; +export type RecordingOptions = RrwebRecordOptions; export interface SendReplayData { recordingData: ReplayRecordingData; diff --git a/packages/replay/src/types/replayFrame.ts b/packages/replay/src/types/replayFrame.ts index 5eca0be68466..296556b6c6d0 100644 --- a/packages/replay/src/types/replayFrame.ts +++ b/packages/replay/src/types/replayFrame.ts @@ -9,11 +9,11 @@ import type { PaintData, ResourceData, } from './performance'; -import type { EventType } from './rrweb'; +import type { ReplayEventTypeCustom } from './rrweb'; type AnyRecord = Record; // eslint-disable-line @typescript-eslint/no-explicit-any -interface BaseBreadcrumbFrame { +interface ReplayBaseBreadcrumbFrame { timestamp: number; /** * For compatibility reasons @@ -24,7 +24,7 @@ interface BaseBreadcrumbFrame { message?: string; } -interface BaseDomFrameData { +interface ReplayBaseDomFrameData { nodeId?: number; node?: { id: number; @@ -35,84 +35,84 @@ interface BaseDomFrameData { } /* Breadcrumbs from Core SDK */ -interface ConsoleFrameData { +interface ReplayConsoleFrameData { logger: string; arguments?: unknown[]; } -interface ConsoleFrame extends BaseBreadcrumbFrame { +interface ReplayConsoleFrame extends ReplayBaseBreadcrumbFrame { category: 'console'; level: Breadcrumb['level']; message: string; - data: ConsoleFrameData; + data: ReplayConsoleFrameData; } -type ClickFrameData = BaseDomFrameData; -interface ClickFrame extends BaseBreadcrumbFrame { +type ReplayClickFrameData = ReplayBaseDomFrameData; +interface ReplayClickFrame extends ReplayBaseBreadcrumbFrame { category: 'ui.click'; message: string; - data: ClickFrameData; + data: ReplayClickFrameData; } -interface InputFrame extends BaseBreadcrumbFrame { +interface ReplayInputFrame extends ReplayBaseBreadcrumbFrame { category: 'ui.input'; message: string; } /* Breadcrumbs from Replay */ -interface MutationFrameData { +interface ReplayMutationFrameData { count: number; limit: boolean; } -interface MutationFrame extends BaseBreadcrumbFrame { +interface ReplayMutationFrame extends ReplayBaseBreadcrumbFrame { category: 'replay.mutations'; - data: MutationFrameData; + data: ReplayMutationFrameData; } -interface KeyboardEventFrameData extends BaseDomFrameData { +interface ReplayKeyboardEventFrameData extends ReplayBaseDomFrameData { metaKey: boolean; shiftKey: boolean; ctrlKey: boolean; altKey: boolean; key: string; } -interface KeyboardEventFrame extends BaseBreadcrumbFrame { +interface ReplayKeyboardEventFrame extends ReplayBaseBreadcrumbFrame { category: 'ui.keyDown'; - data: KeyboardEventFrameData; + data: ReplayKeyboardEventFrameData; } -interface BlurFrame extends BaseBreadcrumbFrame { +interface ReplayBlurFrame extends ReplayBaseBreadcrumbFrame { category: 'ui.blur'; } -interface FocusFrame extends BaseBreadcrumbFrame { +interface ReplayFocusFrame extends ReplayBaseBreadcrumbFrame { category: 'ui.focus'; } -interface SlowClickFrameData extends ClickFrameData { +interface ReplaySlowClickFrameData extends ReplayClickFrameData { url: string; route?: string; timeAfterClickMs: number; endReason: string; clickCount?: number; } -export interface SlowClickFrame extends BaseBreadcrumbFrame { +export interface ReplaySlowClickFrame extends ReplayBaseBreadcrumbFrame { category: 'ui.slowClickDetected'; - data: SlowClickFrameData; + data: ReplaySlowClickFrameData; } -interface MultiClickFrameData extends ClickFrameData { +interface ReplayMultiClickFrameData extends ReplayClickFrameData { url: string; route?: string; clickCount: number; metric: true; } -export interface MultiClickFrame extends BaseBreadcrumbFrame { +export interface ReplayMultiClickFrame extends ReplayBaseBreadcrumbFrame { category: 'ui.multiClick'; - data: MultiClickFrameData; + data: ReplayMultiClickFrameData; } -interface OptionFrame { +interface ReplayOptionFrame { blockAllMedia: boolean; errorSampleRate: number; maskAllInputs: boolean; @@ -126,19 +126,19 @@ interface OptionFrame { useCompressionOption: boolean; } -export type BreadcrumbFrame = - | ConsoleFrame - | ClickFrame - | InputFrame - | KeyboardEventFrame - | BlurFrame - | FocusFrame - | SlowClickFrame - | MultiClickFrame - | MutationFrame - | BaseBreadcrumbFrame; +export type ReplayBreadcrumbFrame = + | ReplayConsoleFrame + | ReplayClickFrame + | ReplayInputFrame + | ReplayKeyboardEventFrame + | ReplayBlurFrame + | ReplayFocusFrame + | ReplaySlowClickFrame + | ReplayMultiClickFrame + | ReplayMutationFrame + | ReplayBaseBreadcrumbFrame; -interface BaseSpanFrame { +interface ReplayBaseSpanFrame { op: string; description: string; startTimestamp: number; @@ -146,55 +146,61 @@ interface BaseSpanFrame { data?: undefined | AnyRecord; } -interface HistoryFrame extends BaseSpanFrame { +interface ReplayHistoryFrame extends ReplayBaseSpanFrame { data: HistoryData; op: 'navigation.push'; } -interface LargestContentfulPaintFrame extends BaseSpanFrame { +interface ReplayLargestContentfulPaintFrame extends ReplayBaseSpanFrame { data: LargestContentfulPaintData; op: 'largest-contentful-paint'; } -interface MemoryFrame extends BaseSpanFrame { +interface ReplayMemoryFrame extends ReplayBaseSpanFrame { data: MemoryData; op: 'memory'; } -interface NavigationFrame extends BaseSpanFrame { +interface ReplayNavigationFrame extends ReplayBaseSpanFrame { data: NavigationData; op: 'navigation.navigate' | 'navigation.reload' | 'navigation.back_forward'; } -interface PaintFrame extends BaseSpanFrame { +interface ReplayPaintFrame extends ReplayBaseSpanFrame { data: PaintData; op: 'paint'; } -interface RequestFrame extends BaseSpanFrame { +interface ReplayRequestFrame extends ReplayBaseSpanFrame { data: NetworkRequestData; op: 'resource.fetch' | 'resource.xhr'; } -interface ResourceFrame extends BaseSpanFrame { +interface ReplayResourceFrame extends ReplayBaseSpanFrame { data: ResourceData; - op: 'resource.css' | 'resource.iframe' | 'resource.img' | 'resource.link' | 'resource.other' | 'resource.script'; -} - -export type SpanFrame = - | BaseSpanFrame - | HistoryFrame - | RequestFrame - | LargestContentfulPaintFrame - | MemoryFrame - | NavigationFrame - | PaintFrame - | ResourceFrame; - -export type ReplayFrame = BreadcrumbFrame | SpanFrame; + op: + | 'resource.css' + | 'resource.ReplayiFrame' + | 'resource.img' + | 'resource.link' + | 'resource.other' + | 'resource.script'; +} + +export type ReplaySpanFrame = + | ReplayBaseSpanFrame + | ReplayHistoryFrame + | ReplayRequestFrame + | ReplayLargestContentfulPaintFrame + | ReplayMemoryFrame + | ReplayNavigationFrame + | ReplayPaintFrame + | ReplayResourceFrame; + +export type ReplayFrame = ReplayBreadcrumbFrame | ReplaySpanFrame; interface RecordingCustomEvent { - type: EventType.Custom; + type: typeof ReplayEventTypeCustom; timestamp: number; data: { tag: string; @@ -202,10 +208,10 @@ interface RecordingCustomEvent { }; } -export interface BreadcrumbFrameEvent extends RecordingCustomEvent { +export interface ReplayBreadcrumbFrameEvent extends RecordingCustomEvent { data: { tag: 'breadcrumb'; - payload: BreadcrumbFrame; + payload: ReplayBreadcrumbFrame; /** * This will indicate to backend to additionally log as a metric */ @@ -213,18 +219,18 @@ export interface BreadcrumbFrameEvent extends RecordingCustomEvent { }; } -export interface SpanFrameEvent extends RecordingCustomEvent { +export interface ReplaySpanFrameEvent extends RecordingCustomEvent { data: { tag: 'performanceSpan'; - payload: SpanFrame; + payload: ReplaySpanFrame; }; } -export interface OptionFrameEvent extends RecordingCustomEvent { +export interface ReplayOptionFrameEvent extends RecordingCustomEvent { data: { tag: 'options'; - payload: OptionFrame; + payload: ReplayOptionFrame; }; } -export type ReplayFrameEvent = BreadcrumbFrameEvent | SpanFrameEvent | OptionFrameEvent; +export type ReplayFrameEvent = ReplayBreadcrumbFrameEvent | ReplaySpanFrameEvent | ReplayOptionFrameEvent; diff --git a/packages/replay/src/types/rrweb.ts b/packages/replay/src/types/rrweb.ts index 75a596fb4385..bc78c5811b12 100644 --- a/packages/replay/src/types/rrweb.ts +++ b/packages/replay/src/types/rrweb.ts @@ -1,25 +1,29 @@ -/* eslint-disable @typescript-eslint/naming-convention */ - -type blockClass = string | RegExp; -type maskTextClass = string | RegExp; +type ClassOption = string | RegExp; /** Duplicate this from @sentry-internal/rrweb so we can export this as well. */ -export enum EventType { - DomContentLoaded = 0, - Load = 1, - FullSnapshot = 2, - IncrementalSnapshot = 3, - Meta = 4, - Custom = 5, - Plugin = 6, -} +export const ReplayEventTypeDomContentLoaded = 0; +export const ReplayEventTypeLoad = 1; +export const ReplayEventTypeFullSnapshot = 2; +export const ReplayEventTypeIncrementalSnapshot = 3; +export const ReplayEventTypeMeta = 4; +export const ReplayEventTypeCustom = 5; +export const ReplayEventTypePlugin = 6; + +export type ReplayEventType = + | typeof ReplayEventTypeDomContentLoaded + | typeof ReplayEventTypeLoad + | typeof ReplayEventTypeFullSnapshot + | typeof ReplayEventTypeIncrementalSnapshot + | typeof ReplayEventTypeMeta + | typeof ReplayEventTypeCustom + | typeof ReplayEventTypePlugin; /** * This is a partial copy of rrweb's eventWithTime type which only contains the properties * we specifcally need in the SDK. */ -export type eventWithTime = { - type: EventType; +export type ReplayEventWithTime = { + type: ReplayEventType; data: unknown; timestamp: number; delay?: number; @@ -30,12 +34,12 @@ export type eventWithTime = { * we specifically us in the SDK. Users can specify additional properties, hence we add the * Record union type. */ -export type recordOptions = { +export type RrwebRecordOptions = { maskAllText?: boolean; maskAllInputs?: boolean; - blockClass?: blockClass; + blockClass?: ClassOption; ignoreClass?: string; - maskTextClass?: maskTextClass; + maskTextClass?: ClassOption; maskTextSelector?: string; blockSelector?: string; maskInputOptions?: Record; diff --git a/packages/replay/src/util/createBreadcrumb.ts b/packages/replay/src/util/createBreadcrumb.ts index 5cf044333876..6f053f08617b 100644 --- a/packages/replay/src/util/createBreadcrumb.ts +++ b/packages/replay/src/util/createBreadcrumb.ts @@ -1,11 +1,11 @@ -import type { BreadcrumbFrame } from '../types/replayFrame'; +import type { ReplayBreadcrumbFrame } from '../types/replayFrame'; /** * Create a breadcrumb for a replay. */ export function createBreadcrumb( - breadcrumb: Omit & Partial>, -): BreadcrumbFrame { + breadcrumb: Omit & Partial>, +): ReplayBreadcrumbFrame { return { timestamp: Date.now() / 1000, type: 'default', diff --git a/packages/replay/src/util/handleRecordingEmit.ts b/packages/replay/src/util/handleRecordingEmit.ts index 9e22e57f6255..f8f00c820ad9 100644 --- a/packages/replay/src/util/handleRecordingEmit.ts +++ b/packages/replay/src/util/handleRecordingEmit.ts @@ -2,7 +2,7 @@ import { EventType } from '@sentry-internal/rrweb'; import { logger } from '@sentry/utils'; import { saveSession } from '../session/saveSession'; -import type { AddEventResult, OptionFrameEvent, RecordingEvent, ReplayContainer } from '../types'; +import type { AddEventResult, RecordingEvent, ReplayContainer, ReplayOptionFrameEvent } from '../types'; import { addEvent } from './addEvent'; import { logInfo } from './log'; @@ -102,7 +102,7 @@ export function getHandleRecordingEmit(replay: ReplayContainer): RecordingEmitCa /** * Exported for tests */ -export function createOptionsEvent(replay: ReplayContainer): OptionFrameEvent { +export function createOptionsEvent(replay: ReplayContainer): ReplayOptionFrameEvent { const options = replay.getOptions(); return { type: EventType.Custom, diff --git a/packages/replay/test/integration/errorSampleRate.test.ts b/packages/replay/test/integration/errorSampleRate.test.ts index e56edae0f723..0db920894291 100644 --- a/packages/replay/test/integration/errorSampleRate.test.ts +++ b/packages/replay/test/integration/errorSampleRate.test.ts @@ -17,6 +17,7 @@ import type { RecordMock } from '../index'; import { BASE_TIMESTAMP } from '../index'; import { resetSdkMock } from '../mocks/resetSdkMock'; import type { DomHandler } from '../types'; +import { getTestEventCheckout, getTestEventIncremental } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -58,7 +59,7 @@ describe('Integration | errorSampleRate', () => { }); it('uploads a replay when `Sentry.captureException` is called and continues recording', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); const optionsEvent = createOptionsEvent(replay); @@ -144,7 +145,7 @@ describe('Integration | errorSampleRate', () => { }); it('manually flushes replay and does not continue to record', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); const optionsEvent = createOptionsEvent(replay); @@ -227,7 +228,7 @@ describe('Integration | errorSampleRate', () => { }); it('handles multiple simultaneous flushes', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); const optionsEvent = createOptionsEvent(replay); @@ -368,7 +369,7 @@ describe('Integration | errorSampleRate', () => { const ELAPSED = 5000; jest.advanceTimersByTime(ELAPSED); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); addEvent(replay, TEST_EVENT); document.dispatchEvent(new Event('visibilitychange')); @@ -381,7 +382,7 @@ describe('Integration | errorSampleRate', () => { }); it('does not upload a replay event if 5 seconds have elapsed since the last replay event occurred', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); // Pretend 5 seconds have passed const ELAPSED = 5000; @@ -396,7 +397,7 @@ describe('Integration | errorSampleRate', () => { }); it('does not upload a replay event if 15 seconds have elapsed since the last replay upload', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); // Fire a new event every 4 seconds, 4 times [...Array(4)].forEach(() => { mockRecord._emitter(TEST_EVENT); @@ -462,11 +463,10 @@ describe('Integration | errorSampleRate', () => { jest.advanceTimersByTime(waitTime + 1); await new Promise(process.nextTick); - const TEST_EVENT = { + const TEST_EVENT = getTestEventIncremental({ data: { name: 'lost event' }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); mockRecord._emitter(TEST_EVENT); jest.runAllTimers(); @@ -506,11 +506,10 @@ describe('Integration | errorSampleRate', () => { jest.advanceTimersByTime(waitTime + 1); await new Promise(process.nextTick); - const TEST_EVENT = { + const TEST_EVENT = getTestEventIncremental({ data: { name: 'lost event' }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); mockRecord._emitter(TEST_EVENT); jest.runAllTimers(); @@ -566,11 +565,10 @@ describe('Integration | errorSampleRate', () => { // Idle for 15 minutes jest.advanceTimersByTime(SESSION_IDLE_EXPIRE_DURATION + 1); - const TEST_EVENT = { + const TEST_EVENT = getTestEventIncremental({ data: { name: 'lost event' }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); mockRecord._emitter(TEST_EVENT); expect(replay).not.toHaveLastSentReplay(); @@ -615,7 +613,7 @@ describe('Integration | errorSampleRate', () => { }); it('has the correct timestamps with deferred root event and last replay update', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); const optionsEvent = createOptionsEvent(replay); @@ -658,7 +656,7 @@ describe('Integration | errorSampleRate', () => { it('has correct timestamps when error occurs much later than initial pageload/checkout', async () => { const ELAPSED = BUFFER_CHECKOUT_TIME; const TICK = 20; - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); // add a mock performance event @@ -710,7 +708,7 @@ describe('Integration | errorSampleRate', () => { it('stops replay when user goes idle', async () => { jest.setSystemTime(BASE_TIMESTAMP); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled(); @@ -753,7 +751,7 @@ describe('Integration | errorSampleRate', () => { const sessionId = replay.session?.id; jest.setSystemTime(BASE_TIMESTAMP); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled(); @@ -821,7 +819,7 @@ describe('Integration | errorSampleRate', () => { it('does not stop replay based on earliest event in buffer', async () => { jest.setSystemTime(BASE_TIMESTAMP); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP - 60000, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP - 60000 }); mockRecord._emitter(TEST_EVENT); expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled(); @@ -955,7 +953,7 @@ it('handles buffer sessions that previously had an error', async () => { jest.runAllTimers(); await new Promise(process.nextTick); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); expect(replay).not.toHaveLastSentReplay(); @@ -992,7 +990,7 @@ it('handles buffer sessions that never had an error', async () => { jest.runAllTimers(); await new Promise(process.nextTick); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); expect(replay).not.toHaveLastSentReplay(); @@ -1037,7 +1035,7 @@ it('sends a replay after loading the session from storage', async () => { jest.runAllTimers(); await new Promise(process.nextTick); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); expect(replay).not.toHaveLastSentReplay(); diff --git a/packages/replay/test/integration/eventProcessors.test.ts b/packages/replay/test/integration/eventProcessors.test.ts index 363c5f2d5a74..b9c86a5c5966 100644 --- a/packages/replay/test/integration/eventProcessors.test.ts +++ b/packages/replay/test/integration/eventProcessors.test.ts @@ -3,6 +3,7 @@ import type { Event, Hub, Scope } from '@sentry/types'; import { BASE_TIMESTAMP } from '..'; import { resetSdkMock } from '../mocks/resetSdkMock'; +import { getTestEventIncremental } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -48,7 +49,7 @@ describe('Integration | eventProcessors', () => { scope.addEventProcessor(handler1); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); jest.runAllTimers(); @@ -59,7 +60,7 @@ describe('Integration | eventProcessors', () => { scope.addEventProcessor(handler2); - const TEST_EVENT2 = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT2 = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT2); jest.runAllTimers(); diff --git a/packages/replay/test/integration/events.test.ts b/packages/replay/test/integration/events.test.ts index c90f8ceed125..ab71f57c9c52 100644 --- a/packages/replay/test/integration/events.test.ts +++ b/packages/replay/test/integration/events.test.ts @@ -8,6 +8,7 @@ import { PerformanceEntryResource } from '../fixtures/performanceEntry/resource' import type { RecordMock } from '../index'; import { BASE_TIMESTAMP } from '../index'; import { resetSdkMock } from '../mocks/resetSdkMock'; +import { getTestEventCheckout } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -74,11 +75,9 @@ describe('Integration | events', () => { const ELAPSED = 5000; await advanceTimers(ELAPSED); - const TEST_EVENT = { - data: {}, + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP + ELAPSED, - type: 2, - }; + }); addEvent(replay, TEST_EVENT); WINDOW.dispatchEvent(new Event('blur')); @@ -112,11 +111,9 @@ describe('Integration | events', () => { const ELAPSED = 5000; await advanceTimers(ELAPSED); - const TEST_EVENT = { - data: {}, + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP + ELAPSED, - type: 2, - }; + }); addEvent(replay, TEST_EVENT); @@ -156,11 +153,9 @@ describe('Integration | events', () => { expect(mockTransportSend).toHaveBeenCalledTimes(0); // A new checkout occurs (i.e. a new session was started) - const TEST_EVENT = { - data: {}, + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP, - type: 2, - }; + }); addEvent(replay, TEST_EVENT); // This event will trigger a flush diff --git a/packages/replay/test/integration/flush.test.ts b/packages/replay/test/integration/flush.test.ts index 6f2d3b7d8ccd..e78032daaf8f 100644 --- a/packages/replay/test/integration/flush.test.ts +++ b/packages/replay/test/integration/flush.test.ts @@ -9,6 +9,7 @@ import { createPerformanceEntries } from '../../src/util/createPerformanceEntrie import { createPerformanceSpans } from '../../src/util/createPerformanceSpans'; import * as SendReplay from '../../src/util/sendReplay'; import { BASE_TIMESTAMP, mockRrweb, mockSdk } from '../index'; +import { getTestEventCheckout } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -261,7 +262,7 @@ describe('Integration | flush', () => { }); // checkout - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); await advanceTimers(DEFAULT_FLUSH_MIN_DELAY); @@ -286,7 +287,7 @@ describe('Integration | flush', () => { }); // checkout - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); await advanceTimers(DEFAULT_FLUSH_MIN_DELAY); @@ -326,7 +327,7 @@ describe('Integration | flush', () => { }); // checkout - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); await advanceTimers(DEFAULT_FLUSH_MIN_DELAY); @@ -415,7 +416,7 @@ describe('Integration | flush', () => { replay.eventBuffer!.hasCheckout = true; // Add event that is too long after session start - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP + MAX_SESSION_LIFE + 100, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP + MAX_SESSION_LIFE + 100 }); mockRecord._emitter(TEST_EVENT); // no checkout! @@ -476,7 +477,7 @@ describe('Integration | flush', () => { }; // Add event inside of session life timespan - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP + 100, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP + 100 }); mockRecord._emitter(TEST_EVENT); await advanceTimers(160_000); diff --git a/packages/replay/test/integration/rateLimiting.test.ts b/packages/replay/test/integration/rateLimiting.test.ts index 291a95c4f94e..1bbaf9e66adf 100644 --- a/packages/replay/test/integration/rateLimiting.test.ts +++ b/packages/replay/test/integration/rateLimiting.test.ts @@ -7,6 +7,7 @@ import { clearSession } from '../../src/session/clearSession'; import * as SendReplayRequest from '../../src/util/sendReplayRequest'; import { BASE_TIMESTAMP, mockSdk } from '../index'; import { mockRrweb } from '../mocks/mockRrweb'; +import { getTestEventCheckout, getTestEventIncremental } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -68,7 +69,7 @@ describe('Integration | rate-limiting behaviour', () => { expect(replay.session?.segmentId).toBe(0); jest.spyOn(replay, 'stop'); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); mockTransportSend.mockImplementationOnce(() => { return Promise.resolve({ statusCode: 429 }); @@ -99,11 +100,10 @@ describe('Integration | rate-limiting behaviour', () => { expect(mockTransportSend).toHaveBeenCalledTimes(1); // and let's also emit a new event and check that it is not recorded - const TEST_EVENT3 = { + const TEST_EVENT3 = getTestEventIncremental({ data: {}, timestamp: BASE_TIMESTAMP + 7 * DEFAULT_FLUSH_MIN_DELAY, - type: 3, - }; + }); mockRecord._emitter(TEST_EVENT3); // T = base + 80 diff --git a/packages/replay/test/integration/sendReplayEvent.test.ts b/packages/replay/test/integration/sendReplayEvent.test.ts index d6f26db6653c..4aef1ee94776 100644 --- a/packages/replay/test/integration/sendReplayEvent.test.ts +++ b/packages/replay/test/integration/sendReplayEvent.test.ts @@ -8,6 +8,7 @@ import { clearSession } from '../../src/session/clearSession'; import { addEvent } from '../../src/util/addEvent'; import * as SendReplayRequest from '../../src/util/sendReplayRequest'; import { BASE_TIMESTAMP, mockRrweb, mockSdk } from '../index'; +import { getTestEventCheckout, getTestEventIncremental } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -89,7 +90,7 @@ describe('Integration | sendReplayEvent', () => { const ELAPSED = 5000; jest.advanceTimersByTime(ELAPSED); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); addEvent(replay, TEST_EVENT); document.dispatchEvent(new Event('visibilitychange')); @@ -150,7 +151,7 @@ describe('Integration | sendReplayEvent', () => { }); it('uploads a replay event if 5 seconds have elapsed since the last replay event occurred', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); mockRecord._emitter(TEST_EVENT); // Pretend 5 seconds have passed const ELAPSED = 5000; @@ -169,7 +170,7 @@ describe('Integration | sendReplayEvent', () => { }); it('uploads a replay event if maxFlushDelay is set 15 seconds have elapsed since the last replay upload', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); // Fire a new event every 4 seconds, 4 times for (let i = 0; i < 4; i++) { mockRecord._emitter(TEST_EVENT); @@ -214,7 +215,7 @@ describe('Integration | sendReplayEvent', () => { const ELAPSED = 5000; jest.advanceTimersByTime(ELAPSED); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); const hiddenBreadcrumb = { type: 5, timestamp: +new Date(BASE_TIMESTAMP + ELAPSED) / 1000, @@ -252,7 +253,7 @@ describe('Integration | sendReplayEvent', () => { const ELAPSED = 5000; jest.advanceTimersByTime(ELAPSED); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); addEvent(replay, TEST_EVENT); document.dispatchEvent(new Event('visibilitychange')); @@ -302,7 +303,7 @@ describe('Integration | sendReplayEvent', () => { it('fails to upload data on first two calls and succeeds on the third', async () => { expect(replay.session?.segmentId).toBe(0); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); // Suppress console.errors const mockConsole = jest.spyOn(console, 'error').mockImplementation(jest.fn()); @@ -351,7 +352,7 @@ describe('Integration | sendReplayEvent', () => { }); it('fails to upload data and hits retry max and stops', async () => { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); const spyHandleException = jest.spyOn(SentryCore, 'captureException'); diff --git a/packages/replay/test/integration/session.test.ts b/packages/replay/test/integration/session.test.ts index 6e62b71ca09c..b0ea37e4e0f2 100644 --- a/packages/replay/test/integration/session.test.ts +++ b/packages/replay/test/integration/session.test.ts @@ -18,6 +18,7 @@ import { createOptionsEvent } from '../../src/util/handleRecordingEmit'; import { BASE_TIMESTAMP } from '../index'; import type { RecordMock } from '../mocks/mockRrweb'; import { resetSdkMock } from '../mocks/resetSdkMock'; +import { getTestEventCheckout, getTestEventIncremental } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -140,11 +141,10 @@ describe('Integration | session', () => { // Session has become in an idle state // // This event will put the Replay SDK into a paused state - const TEST_EVENT = { + const TEST_EVENT = getTestEventIncremental({ data: { name: 'lost event' }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); mockRecord._emitter(TEST_EVENT); // performance events can still be collected while recording is stopped @@ -260,11 +260,10 @@ describe('Integration | session', () => { // Session has become in an idle state // // This event will put the Replay SDK into a paused state - const TEST_EVENT = { + const TEST_EVENT = getTestEventIncremental({ data: { name: 'lost event' }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); mockRecord._emitter(TEST_EVENT); // performance events can still be collected while recording is stopped @@ -359,11 +358,10 @@ describe('Integration | session', () => { replay['_updateSessionActivity'](); // This should trigger a new session - const TEST_EVENT = { + const TEST_EVENT = getTestEventIncremental({ data: { name: 'lost event' }, timestamp: ELAPSED, - type: 3, - }; + }); mockRecord._emitter(TEST_EVENT); expect(replay).not.toHaveSameSession(initialSession); @@ -379,11 +377,10 @@ describe('Integration | session', () => { const newTimestamp = BASE_TIMESTAMP + ELAPSED; - const NEW_TEST_EVENT = { + const NEW_TEST_EVENT = getTestEventIncremental({ data: { name: 'test' }, timestamp: newTimestamp + DEFAULT_FLUSH_MIN_DELAY + 20, - type: 3, - }; + }); mockRecord._emitter(NEW_TEST_EVENT); const optionsEvent = createOptionsEvent(replay); @@ -438,7 +435,7 @@ describe('Integration | session', () => { const ELAPSED = 5000; await advanceTimers(ELAPSED); - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 }; + const TEST_EVENT = getTestEventCheckout({ timestamp: BASE_TIMESTAMP }); addEvent(replay, TEST_EVENT); WINDOW.dispatchEvent(new Event('blur')); diff --git a/packages/replay/test/integration/stop.test.ts b/packages/replay/test/integration/stop.test.ts index a88c5de6a839..cdc980ae5b62 100644 --- a/packages/replay/test/integration/stop.test.ts +++ b/packages/replay/test/integration/stop.test.ts @@ -8,6 +8,7 @@ import { addEvent } from '../../src/util/addEvent'; import { createOptionsEvent } from '../../src/util/handleRecordingEmit'; // mock functions need to be imported first import { BASE_TIMESTAMP, mockRrweb, mockSdk } from '../index'; +import { getTestEventIncremental } from '../utils/getTestEvent'; import { useFakeTimers } from '../utils/use-fake-timers'; useFakeTimers(); @@ -76,7 +77,7 @@ describe('Integration | stop', () => { const ELAPSED = 5000; // Not sure where the 20ms comes from tbh const EXTRA_TICKS = 20; - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); const previousSessionId = replay.session?.id; // stop replays @@ -144,7 +145,7 @@ describe('Integration | stop', () => { }); it('does not buffer new events after being stopped', async function () { - const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; + const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); addEvent(replay, TEST_EVENT); expect(replay.eventBuffer?.hasEvents).toBe(true); expect(mockRunFlush).toHaveBeenCalledTimes(0); diff --git a/packages/replay/test/mocks/mockRrweb.ts b/packages/replay/test/mocks/mockRrweb.ts index 0c7ef971483d..c6fbd2be6e55 100644 --- a/packages/replay/test/mocks/mockRrweb.ts +++ b/packages/replay/test/mocks/mockRrweb.ts @@ -1,6 +1,7 @@ import type { record as rrwebRecord } from '@sentry-internal/rrweb'; -import type { RecordingEvent } from '../../src/types'; +import type { RecordingEvent, ReplayEventWithTime } from '../../src/types'; +import { ReplayEventTypeFullSnapshot, ReplayEventTypeIncrementalSnapshot } from '../../src/types'; type RecordAdditionalProperties = { takeFullSnapshot: jest.Mock; @@ -16,11 +17,11 @@ type RecordAdditionalProperties = { export type RecordMock = jest.MockedFunction & RecordAdditionalProperties; -function createCheckoutPayload(isCheckout: boolean = true) { +function createCheckoutPayload(isCheckout: boolean = true): ReplayEventWithTime { return { data: { isCheckout }, timestamp: Date.now(), - type: isCheckout ? 2 : 3, + type: isCheckout ? ReplayEventTypeFullSnapshot : ReplayEventTypeIncrementalSnapshot, }; } diff --git a/packages/replay/test/unit/eventBuffer/EventBufferArray.test.ts b/packages/replay/test/unit/eventBuffer/EventBufferArray.test.ts index 494d03e9572f..8c8d9a7e99e5 100644 --- a/packages/replay/test/unit/eventBuffer/EventBufferArray.test.ts +++ b/packages/replay/test/unit/eventBuffer/EventBufferArray.test.ts @@ -2,8 +2,9 @@ import { REPLAY_MAX_EVENT_BUFFER_SIZE } from '../../../src/constants'; import { createEventBuffer } from '../../../src/eventBuffer'; import { EventBufferSizeExceededError } from '../../../src/eventBuffer/error'; import { BASE_TIMESTAMP } from '../../index'; +import { getTestEventIncremental } from '../../utils/getTestEvent'; -const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; +const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); describe('Unit | eventBuffer | EventBufferArray', () => { it('adds events to normal event buffer', async function () { @@ -51,11 +52,10 @@ describe('Unit | eventBuffer | EventBufferArray', () => { it('rejects if size exceeds limit', async function () { const buffer = createEventBuffer({ useCompression: false }); - const largeEvent = { + const largeEvent = getTestEventIncremental({ data: { a: 'a'.repeat(REPLAY_MAX_EVENT_BUFFER_SIZE / 3) }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); await buffer.addEvent(largeEvent); await buffer.addEvent(largeEvent); @@ -67,11 +67,10 @@ describe('Unit | eventBuffer | EventBufferArray', () => { it('resets size limit on clear', async function () { const buffer = createEventBuffer({ useCompression: false }); - const largeEvent = { + const largeEvent = getTestEventIncremental({ data: { a: 'a'.repeat(REPLAY_MAX_EVENT_BUFFER_SIZE / 3) }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); await buffer.addEvent(largeEvent); await buffer.addEvent(largeEvent); @@ -84,11 +83,10 @@ describe('Unit | eventBuffer | EventBufferArray', () => { it('resets size limit on finish', async function () { const buffer = createEventBuffer({ useCompression: false }); - const largeEvent = { + const largeEvent = getTestEventIncremental({ data: { a: 'a'.repeat(REPLAY_MAX_EVENT_BUFFER_SIZE / 3) }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); await buffer.addEvent(largeEvent); await buffer.addEvent(largeEvent); diff --git a/packages/replay/test/unit/eventBuffer/EventBufferCompressionWorker.test.ts b/packages/replay/test/unit/eventBuffer/EventBufferCompressionWorker.test.ts index cab6855e411d..297744389cf6 100644 --- a/packages/replay/test/unit/eventBuffer/EventBufferCompressionWorker.test.ts +++ b/packages/replay/test/unit/eventBuffer/EventBufferCompressionWorker.test.ts @@ -7,8 +7,9 @@ import { REPLAY_MAX_EVENT_BUFFER_SIZE } from '../../../src/constants'; import { createEventBuffer } from '../../../src/eventBuffer'; import { EventBufferSizeExceededError } from '../../../src/eventBuffer/error'; import { EventBufferProxy } from '../../../src/eventBuffer/EventBufferProxy'; +import { getTestEventIncremental } from '../../utils/getTestEvent'; -const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; +const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); describe('Unit | eventBuffer | EventBufferCompressionWorker', () => { it('adds events to event buffer with compression worker', async function () { @@ -158,11 +159,10 @@ describe('Unit | eventBuffer | EventBufferCompressionWorker', () => { expect(buffer).toBeInstanceOf(EventBufferProxy); await buffer.ensureWorkerIsLoaded(); - const largeEvent = { + const largeEvent = getTestEventIncremental({ data: { a: 'a'.repeat(REPLAY_MAX_EVENT_BUFFER_SIZE / 3) }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); await buffer.addEvent(largeEvent); await buffer.addEvent(largeEvent); @@ -179,11 +179,10 @@ describe('Unit | eventBuffer | EventBufferCompressionWorker', () => { expect(buffer).toBeInstanceOf(EventBufferProxy); await buffer.ensureWorkerIsLoaded(); - const largeEvent = { + const largeEvent = getTestEventIncremental({ data: { a: 'a'.repeat(REPLAY_MAX_EVENT_BUFFER_SIZE / 3) }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); await buffer.addEvent(largeEvent); await buffer.addEvent(largeEvent); @@ -201,11 +200,10 @@ describe('Unit | eventBuffer | EventBufferCompressionWorker', () => { expect(buffer).toBeInstanceOf(EventBufferProxy); await buffer.ensureWorkerIsLoaded(); - const largeEvent = { + const largeEvent = getTestEventIncremental({ data: { a: 'a'.repeat(REPLAY_MAX_EVENT_BUFFER_SIZE / 3) }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); await buffer.addEvent(largeEvent); await buffer.addEvent(largeEvent); diff --git a/packages/replay/test/unit/eventBuffer/EventBufferProxy.test.ts b/packages/replay/test/unit/eventBuffer/EventBufferProxy.test.ts index c4a98f3c446e..6e51d11c2dab 100644 --- a/packages/replay/test/unit/eventBuffer/EventBufferProxy.test.ts +++ b/packages/replay/test/unit/eventBuffer/EventBufferProxy.test.ts @@ -4,9 +4,10 @@ import pako from 'pako'; import { BASE_TIMESTAMP } from '../..'; import { EventBufferProxy } from '../../../src/eventBuffer/EventBufferProxy'; +import { getTestEventIncremental } from '../../utils/getTestEvent'; import { createEventBuffer } from './../../../src/eventBuffer'; -const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; +const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP }); describe('Unit | eventBuffer | EventBufferProxy', () => { let consoleErrorSpy: jest.SpyInstance; diff --git a/packages/replay/test/unit/util/addEvent.test.ts b/packages/replay/test/unit/util/addEvent.test.ts index f00dc82d338f..6230bd40c21c 100644 --- a/packages/replay/test/unit/util/addEvent.test.ts +++ b/packages/replay/test/unit/util/addEvent.test.ts @@ -4,6 +4,7 @@ import { BASE_TIMESTAMP } from '../..'; import { REPLAY_MAX_EVENT_BUFFER_SIZE } from '../../../src/constants'; import type { EventBufferProxy } from '../../../src/eventBuffer/EventBufferProxy'; import { addEvent } from '../../../src/util/addEvent'; +import { getTestEventIncremental } from '../../utils/getTestEvent'; import { setupReplayContainer } from '../../utils/setupReplayContainer'; import { useFakeTimers } from '../../utils/use-fake-timers'; @@ -40,11 +41,10 @@ describe('Unit | util | addEvent', () => { }, }); - const largeEvent = { + const largeEvent = getTestEventIncremental({ data: { a: 'a'.repeat(REPLAY_MAX_EVENT_BUFFER_SIZE / 3) }, timestamp: BASE_TIMESTAMP, - type: 3, - }; + }); await (replay.eventBuffer as EventBufferProxy).ensureWorkerIsLoaded(); diff --git a/packages/replay/test/unit/util/handleRecordingEmit.test.ts b/packages/replay/test/unit/util/handleRecordingEmit.test.ts index 7978939291bd..73cab05a1535 100644 --- a/packages/replay/test/unit/util/handleRecordingEmit.test.ts +++ b/packages/replay/test/unit/util/handleRecordingEmit.test.ts @@ -1,7 +1,7 @@ import { EventType } from '@sentry-internal/rrweb'; import { BASE_TIMESTAMP } from '../..'; -import type { OptionFrameEvent } from '../../../src/types'; +import type { ReplayOptionFrameEvent } from '../../../src/types'; import * as SentryAddEvent from '../../../src/util/addEvent'; import { createOptionsEvent, getHandleRecordingEmit } from '../../../src/util/handleRecordingEmit'; import { setupReplayContainer } from '../../utils/setupReplayContainer'; @@ -9,7 +9,7 @@ import { useFakeTimers } from '../../utils/use-fake-timers'; useFakeTimers(); -let optionsEvent: OptionFrameEvent; +let optionsEvent: ReplayOptionFrameEvent; describe('Unit | util | handleRecordingEmit', () => { let addEventMock: jest.SpyInstance; diff --git a/packages/replay/test/utils/getTestEvent.ts b/packages/replay/test/utils/getTestEvent.ts new file mode 100644 index 000000000000..c62983b4c60d --- /dev/null +++ b/packages/replay/test/utils/getTestEvent.ts @@ -0,0 +1,26 @@ +import type { ReplayEventType, ReplayEventWithTime } from '../../src'; +import { ReplayEventTypeFullSnapshot, ReplayEventTypeIncrementalSnapshot } from '../../src/types'; + +export function getTestEvent({ + timestamp, + type, + data, +}: { + timestamp: number; + data?: any; + type: ReplayEventType; +}): ReplayEventWithTime { + return { + data: data || {}, + timestamp, + type, + }; +} + +export function getTestEventCheckout({ timestamp, data }: { timestamp: number; data?: any }): ReplayEventWithTime { + return getTestEvent({ timestamp, data, type: ReplayEventTypeFullSnapshot }); +} + +export function getTestEventIncremental({ timestamp, data }: { timestamp: number; data?: any }): ReplayEventWithTime { + return getTestEvent({ timestamp, data, type: ReplayEventTypeIncrementalSnapshot }); +}