Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
bcaudan committed May 31, 2023
1 parent 95bf2b0 commit 7d8c010
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 111 deletions.
5 changes: 5 additions & 0 deletions packages/rum-core/src/boot/rumPublicApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,11 @@ describe('rum public api', () => {
DefaultPrivacyLevel.MASK_USER_INPUT
)
})

// TODO missing configuration test
// recording started with default startSessionReplayRecordingManually
// recording started with configured startSessionReplayRecordingManually
// automatic start configuration is overridden by before init call (before init call executed after)
})

it('should provide sdk version', () => {
Expand Down
126 changes: 65 additions & 61 deletions packages/rum/src/boot/recorderApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ describe('makeRecorderApi', () => {
}

let rumInit: () => void
let startSessionReplayRecordingManually: boolean

beforeEach(() => {
if (isIE()) {
pending('IE not supported')
}
startSessionReplayRecordingManually = false
setupBuilder = setup().beforeBuild(({ lifeCycle, sessionManager }) => {
stopRecordingSpy = jasmine.createSpy('stopRecording')
startRecordingSpy = jasmine.createSpy('startRecording').and.callFake(() => ({
Expand All @@ -46,7 +48,12 @@ describe('makeRecorderApi', () => {
startDeflateWorkerWith(FAKE_WORKER)
recorderApi = makeRecorderApi(startRecordingSpy, startDeflateWorkerSpy)
rumInit = () => {
recorderApi.onRumStart(lifeCycle, {} as RumConfiguration, sessionManager, {} as ViewContexts)
recorderApi.onRumStart(
lifeCycle,
{ startSessionReplayRecordingManually } as RumConfiguration,
sessionManager,
{} as ViewContexts
)
}
})
})
Expand All @@ -55,26 +62,48 @@ describe('makeRecorderApi', () => {
setupBuilder.cleanup()
})

describe('boot', () => {
it('does not start recording when init() is called', () => {
setupBuilder.build()
expect(startRecordingSpy).not.toHaveBeenCalled()
rumInit()
expect(startRecordingSpy).not.toHaveBeenCalled()
describe('recorder boot', () => {
describe('with automatic start', () => {
it('starts recording when init() is called', () => {
setupBuilder.build()
expect(startRecordingSpy).not.toHaveBeenCalled()
rumInit()
expect(startRecordingSpy).toHaveBeenCalled()
})

it('does not start recording after the DOM is loaded', () => {
setupBuilder.build()
const { triggerOnDomLoaded } = mockDocumentReadyState()
rumInit()
expect(startRecordingSpy).not.toHaveBeenCalled()
triggerOnDomLoaded()
expect(startRecordingSpy).toHaveBeenCalled()
})
})

it('does not start recording after the DOM is loaded', () => {
setupBuilder.build()
const { triggerOnDomLoaded } = mockDocumentReadyState()
rumInit()
expect(startRecordingSpy).not.toHaveBeenCalled()
triggerOnDomLoaded()
expect(startRecordingSpy).not.toHaveBeenCalled()
describe('with manual start', () => {
it('does not start recording when init() is called', () => {
startSessionReplayRecordingManually = true
setupBuilder.build()
expect(startRecordingSpy).not.toHaveBeenCalled()
rumInit()
expect(startRecordingSpy).not.toHaveBeenCalled()
})

it('does not start recording after the DOM is loaded', () => {
startSessionReplayRecordingManually = true
setupBuilder.build()
const { triggerOnDomLoaded } = mockDocumentReadyState()
rumInit()
expect(startRecordingSpy).not.toHaveBeenCalled()
triggerOnDomLoaded()
expect(startRecordingSpy).not.toHaveBeenCalled()
})
})
})

describe('startSessionReplayRecording()', () => {
it('ignores calls while recording is already started', () => {
describe('recorder start', () => {
it('ignores additional start calls while recording is already started', () => {
setupBuilder.build()
rumInit()
recorderApi.start()
Expand All @@ -83,32 +112,24 @@ describe('makeRecorderApi', () => {
expect(startRecordingSpy).toHaveBeenCalledTimes(1)
})

it('starts recording if called before init()', () => {
setupBuilder.build()
recorderApi.start()
rumInit()
expect(startRecordingSpy).toHaveBeenCalled()
})

it('does not start recording multiple times if restarted before the DOM is loaded', () => {
it('ignores restart before the DOM is loaded', () => {
setupBuilder.build()
const { triggerOnDomLoaded } = mockDocumentReadyState()
rumInit()
recorderApi.start()
recorderApi.stop()
recorderApi.start()
triggerOnDomLoaded()
expect(startRecordingSpy).toHaveBeenCalledTimes(1)
})

it('ignores calls if the session is not tracked', () => {
it('ignores start calls if the session is not tracked', () => {
setupBuilder.withSessionManager(createRumSessionManagerMock().setNotTracked()).build()
rumInit()
recorderApi.start()
expect(startRecordingSpy).not.toHaveBeenCalled()
})

it('ignores calls if the session plan is WITHOUT_REPLAY', () => {
it('ignores start calls if the session plan is WITHOUT_REPLAY', () => {
setupBuilder.withSessionManager(createRumSessionManagerMock().setPlanWithoutSessionReplay()).build()
rumInit()
recorderApi.start()
Expand All @@ -117,17 +138,15 @@ describe('makeRecorderApi', () => {

it('do not start recording if worker fails to be instantiated', () => {
setupBuilder.build()
rumInit()
startDeflateWorkerWith(undefined)
recorderApi.start()
rumInit()
expect(startRecordingSpy).not.toHaveBeenCalled()
})

it('does not start recording multiple times if restarted before worker is initialized', () => {
setupBuilder.build()
rumInit()
stopDeflateWorker()
recorderApi.start()
rumInit()
recorderApi.stop()

callLastRegisteredInitialisationCallback()
Expand Down Expand Up @@ -174,30 +193,20 @@ describe('makeRecorderApi', () => {
})
})

describe('stopSessionReplayRecording()', () => {
describe('recorder stop', () => {
it('ignores calls while recording is already stopped', () => {
setupBuilder.build()
rumInit()
recorderApi.start()
recorderApi.stop()
recorderApi.stop()
recorderApi.stop()
expect(stopRecordingSpy).toHaveBeenCalledTimes(1)
})

it('does not start recording if called before init()', () => {
setupBuilder.build()
recorderApi.start()
recorderApi.stop()
rumInit()
expect(startRecordingSpy).not.toHaveBeenCalled()
})

it('prevents recording to start when the DOM is loaded', () => {
setupBuilder.build()
const { triggerOnDomLoaded } = mockDocumentReadyState()
rumInit()
recorderApi.start()
recorderApi.stop()
triggerOnDomLoaded()
expect(startRecordingSpy).not.toHaveBeenCalled()
Expand All @@ -211,7 +220,6 @@ describe('makeRecorderApi', () => {
sessionManager = createRumSessionManagerMock()
setupBuilder.withSessionManager(sessionManager)
;({ lifeCycle } = setupBuilder.build())
rumInit()
})

describe('from WITHOUT_REPLAY to WITH_REPLAY', () => {
Expand All @@ -220,7 +228,7 @@ describe('makeRecorderApi', () => {
})

it('starts recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
sessionManager.setPlanWithSessionReplay()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
expect(startRecordingSpy).not.toHaveBeenCalled()
Expand All @@ -230,7 +238,7 @@ describe('makeRecorderApi', () => {
})

it('does not starts recording if stopSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
recorderApi.stop()
sessionManager.setPlanWithSessionReplay()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
Expand All @@ -245,7 +253,7 @@ describe('makeRecorderApi', () => {
})

it('keeps not recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
sessionManager.setNotTracked()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
Expand All @@ -260,7 +268,7 @@ describe('makeRecorderApi', () => {
})

it('keeps not recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
expect(startRecordingSpy).not.toHaveBeenCalled()
Expand All @@ -274,7 +282,7 @@ describe('makeRecorderApi', () => {
})

it('stops recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
expect(startRecordingSpy).toHaveBeenCalledTimes(1)
sessionManager.setPlanWithoutSessionReplay()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
Expand All @@ -284,10 +292,8 @@ describe('makeRecorderApi', () => {
})

it('prevents session recording to start if the session is renewed before the DOM is loaded', () => {
setupBuilder.build()
const { triggerOnDomLoaded } = mockDocumentReadyState()
rumInit()
recorderApi.start()
sessionManager.setPlanWithoutSessionReplay()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
Expand All @@ -302,7 +308,7 @@ describe('makeRecorderApi', () => {
})

it('stops recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
expect(startRecordingSpy).toHaveBeenCalledTimes(1)
sessionManager.setNotTracked()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
Expand All @@ -318,7 +324,7 @@ describe('makeRecorderApi', () => {
})

it('keeps recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
expect(startRecordingSpy).toHaveBeenCalledTimes(1)
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
expect(stopRecordingSpy).toHaveBeenCalled()
Expand All @@ -327,7 +333,7 @@ describe('makeRecorderApi', () => {
})

it('does not starts recording if stopSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
expect(startRecordingSpy).toHaveBeenCalledTimes(1)
recorderApi.stop()
expect(stopRecordingSpy).toHaveBeenCalledTimes(1)
Expand All @@ -344,7 +350,7 @@ describe('makeRecorderApi', () => {
})

it('starts recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
sessionManager.setPlanWithSessionReplay()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
Expand All @@ -353,7 +359,7 @@ describe('makeRecorderApi', () => {
})

it('does not starts recording if stopSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
recorderApi.stop()
sessionManager.setPlanWithSessionReplay()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
Expand All @@ -369,7 +375,7 @@ describe('makeRecorderApi', () => {
})

it('keeps not recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
sessionManager.setPlanWithoutSessionReplay()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
Expand All @@ -384,7 +390,7 @@ describe('makeRecorderApi', () => {
})

it('keeps not recording if startSessionReplayRecording was called', () => {
recorderApi.start()
rumInit()
lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
expect(startRecordingSpy).not.toHaveBeenCalled()
Expand All @@ -397,20 +403,18 @@ describe('makeRecorderApi', () => {
it('is true only if recording', () => {
setupBuilder.build()
rumInit()
expect(recorderApi.isRecording()).toBeFalse()
recorderApi.start()
expect(recorderApi.isRecording()).toBeTrue()
recorderApi.stop()
expect(recorderApi.isRecording()).toBeFalse()
recorderApi.start()
expect(recorderApi.isRecording()).toBeTrue()
})

it('is false before the DOM is loaded', () => {
setupBuilder.build()
const { triggerOnDomLoaded } = mockDocumentReadyState()
rumInit()
expect(recorderApi.isRecording()).toBeFalse()
recorderApi.start()
expect(recorderApi.isRecording()).toBeFalse()
triggerOnDomLoaded()
expect(recorderApi.isRecording()).toBeTrue()
})
Expand Down
5 changes: 4 additions & 1 deletion packages/rum/src/boot/recorderApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function makeRecorderApi(
}

let state: RecorderState = {
status: RecorderStatus.Stopped,
status: RecorderStatus.IntentToStart,
}

let startStrategy = () => {
Expand All @@ -79,6 +79,9 @@ export function makeRecorderApi(
sessionManager: RumSessionManager,
viewContexts: ViewContexts
) => {
if (configuration.startSessionReplayRecordingManually) {
state = { status: RecorderStatus.Stopped }
}
lifeCycle.subscribe(LifeCycleEventType.SESSION_EXPIRED, () => {
if (state.status === RecorderStatus.Starting || state.status === RecorderStatus.Started) {
stopStrategy()
Expand Down
6 changes: 0 additions & 6 deletions test/e2e/lib/helpers/replay.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { RumInitConfiguration } from '@datadog/browser-rum-core'
import type { EventRegistry } from '../framework'

export function getFirstSegment(events: EventRegistry) {
Expand All @@ -8,8 +7,3 @@ export function getFirstSegment(events: EventRegistry) {
export function getLastSegment(events: EventRegistry) {
return events.sessionReplay[events.sessionReplay.length - 1].segment.data
}

export function initRumAndStartRecording(initConfiguration: RumInitConfiguration) {
window.DD_RUM!.init(initConfiguration)
window.DD_RUM!.startSessionReplayRecording()
}
Loading

0 comments on commit 7d8c010

Please sign in to comment.