Skip to content

✨ [RUM-10144] apply context defined just after init to View event generated during init #3597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
5 changes: 5 additions & 0 deletions packages/core/src/tools/utils/functionUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { monitorError } from '../monitor'
import type { TimeoutId } from '../timer'
import { setTimeout, clearTimeout } from '../timer'

Expand Down Expand Up @@ -43,3 +44,7 @@ export function throttle<T extends (...args: any[]) => void>(

// eslint-disable-next-line @typescript-eslint/no-empty-function
export function noop() {}

export function enqueueMicroTask(callback: () => void) {
Promise.resolve().then(callback).catch(monitorError)
}
18 changes: 17 additions & 1 deletion packages/core/test/emulate/mockClock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ export function mockClock() {

registerCleanupTask(() => jasmine.clock().uninstall())

const pendingMicroTasks: Array<() => void> = []

const originalPromiseResolve = Promise.resolve.bind(Promise)
spyOn(Promise, 'resolve').and.callFake(
() =>
({
then: (callback: () => void) => {
pendingMicroTasks.push(callback)
return originalPromiseResolve()
},
}) as Promise<void>
)

return {
/**
* Returns a RelativeTime representing the time it was X milliseconds after the `mockClock()`
Expand All @@ -26,7 +39,10 @@ export function mockClock() {
* invokation (the start of the test).
*/
timeStamp: (duration: number) => (timeStampStart + duration) as TimeStamp,
tick: (ms: number) => jasmine.clock().tick(ms),
tick: (ms: number) => {
pendingMicroTasks.splice(0).forEach((task) => task())
jasmine.clock().tick(ms)
},
setDate: (date: Date) => jasmine.clock().mockDate(date),
}
}
12 changes: 9 additions & 3 deletions packages/rum-core/src/boot/startRum.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,13 @@ function startRumStub(

describe('rum session', () => {
let serverRumEvents: RumEvent[]
let clock: Clock
let lifeCycle: LifeCycle
let sessionManager: RumSessionManagerMock

beforeEach(() => {
lifeCycle = new LifeCycle()
clock = mockClock()
sessionManager = createRumSessionManagerMock().setId('42')
const domMutationObservable = new Observable<RumMutationRecord[]>()
const windowOpenObservable = new Observable<void>()
Expand All @@ -135,6 +137,7 @@ describe('rum session', () => {
})

it('when the session is renewed, a new view event should be sent', () => {
clock.tick(0)
expect(serverRumEvents.length).toEqual(1)
expect(serverRumEvents[0].type).toEqual('view')
expect(serverRumEvents[0].session.id).toEqual('42')
Expand All @@ -144,6 +147,7 @@ describe('rum session', () => {

sessionManager.setId('43')
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
clock.tick(0)

expect(serverRumEvents.length).toEqual(3)

Expand Down Expand Up @@ -223,7 +227,6 @@ describe('rum events url', () => {

let changeLocation: (to: string) => void
let lifeCycle: LifeCycle
let clock: Clock
let serverRumEvents: RumEvent[]
let stop: () => void

Expand Down Expand Up @@ -259,18 +262,20 @@ describe('rum events url', () => {
})

it('should keep the same URL when updating a view ended by a URL change', () => {
const clock = mockClock()
setupViewUrlTest()
serverRumEvents.length = 0

changeLocation('/bar')
clock.tick(0)

expect(serverRumEvents.length).toEqual(2)
expect(serverRumEvents[0].view.url).toEqual('http://foo.com/')
expect(serverRumEvents[1].view.url).toEqual('http://foo.com/bar')
})

it('should attach the url corresponding to the start of the event', () => {
clock = mockClock()
const clock = mockClock()
const { notifyPerformanceEntries } = mockPerformanceObserver()

setupViewUrlTest()
Expand All @@ -297,13 +302,14 @@ describe('rum events url', () => {
})

it('should keep the same URL when updating an ended view', () => {
clock = mockClock()
const clock = mockClock()
const { triggerOnLoad } = mockDocumentReadyState()
setupViewUrlTest()

clock.tick(VIEW_DURATION)

changeLocation('/bar')
clock.tick(0)

serverRumEvents.length = 0

Expand Down
22 changes: 10 additions & 12 deletions packages/rum-core/src/domain/view/setupViewTest.specHelper.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import { Observable, deepClone } from '@datadog/browser-core'
import { registerCleanupTask } from '../../../../core/test'
import { mockRumConfiguration, setupLocationObserver } from '../../../test'
import type { LifeCycle } from '../lifeCycle'
import { LifeCycleEventType } from '../lifeCycle'
import { LifeCycle, LifeCycleEventType } from '../lifeCycle'
import type { RumConfiguration } from '../configuration'
import type { RumMutationRecord } from '../../browser/domMutationObservable'
import type { ViewCreatedEvent, ViewEvent, ViewOptions, ViewEndedEvent } from './trackViews'
import { trackViews } from './trackViews'

export type ViewTest = ReturnType<typeof setupViewTest>

interface ViewTrackingContext {
lifeCycle: LifeCycle
interface ViewTestOptions {
initialLocation?: string
partialConfig?: Partial<RumConfiguration>
initialViewOptions?: ViewOptions
}

export function setupViewTest(
{ lifeCycle, initialLocation, partialConfig }: ViewTrackingContext,
initialViewOptions?: ViewOptions
) {
export function setupViewTest({ initialLocation, partialConfig, initialViewOptions }: ViewTestOptions = {}) {
const lifeCycle = new LifeCycle()
const domMutationObservable = new Observable<RumMutationRecord[]>()
const windowOpenObservable = new Observable<void>()
const configuration = mockRumConfiguration(partialConfig)
Expand Down Expand Up @@ -56,8 +54,11 @@ export function setupViewTest(
!configuration.trackViewsManually,
initialViewOptions
)

registerCleanupTask(stop)

return {
stop,
lifeCycle,
startView,
setViewContext,
setViewContextProperty,
Expand All @@ -71,9 +72,6 @@ export function setupViewTest(
getViewCreateCount,
getViewEnd,
getViewEndCount,
getLatestViewContext: () => ({
id: getViewCreate(getViewCreateCount() - 1).id,
}),
}
}

Expand Down
Loading