diff --git a/packages/rum-core/src/domain/contexts/featureFlagContext.spec.ts b/packages/rum-core/src/domain/contexts/featureFlagContext.spec.ts
index d26f31f0b3..21588e1866 100644
--- a/packages/rum-core/src/domain/contexts/featureFlagContext.spec.ts
+++ b/packages/rum-core/src/domain/contexts/featureFlagContext.spec.ts
@@ -1,38 +1,35 @@
import type { CustomerDataTracker, RelativeTime } from '@datadog/browser-core'
import { relativeToClocks, createCustomerDataTracker, noop } from '@datadog/browser-core'
-import type { TestSetupBuilder } from '../../../test'
-import { setup } from '../../../test'
-import { LifeCycleEventType } from '../lifeCycle'
+import type { Clock } from '@datadog/browser-core/test'
+import { mockClock, registerCleanupTask } from '@datadog/browser-core/test'
+import { LifeCycle, LifeCycleEventType } from '../lifeCycle'
import type { ViewCreatedEvent, ViewEndedEvent } from '../view/trackViews'
import type { FeatureFlagContexts } from './featureFlagContext'
import { startFeatureFlagContexts } from './featureFlagContext'
describe('featureFlagContexts', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
+ let clock: Clock
let customerDataTracker: CustomerDataTracker
let featureFlagContexts: FeatureFlagContexts
beforeEach(() => {
- setupBuilder = setup().beforeBuild(({ lifeCycle }) => {
- customerDataTracker = createCustomerDataTracker(noop)
- featureFlagContexts = startFeatureFlagContexts(lifeCycle, customerDataTracker)
- })
- })
+ clock = mockClock()
+ customerDataTracker = createCustomerDataTracker(noop)
+ featureFlagContexts = startFeatureFlagContexts(lifeCycle, customerDataTracker)
- afterEach(() => {
- featureFlagContexts.stop()
+ registerCleanupTask(() => {
+ clock.cleanup()
+ featureFlagContexts.stop()
+ })
})
it('should return undefined before the initial view', () => {
- setupBuilder.build()
-
expect(featureFlagContexts.findFeatureFlagEvaluations()).toBeUndefined()
})
describe('addFeatureFlagEvaluation', () => {
it('should add feature flag evaluations of any type', () => {
- const { lifeCycle } = setupBuilder.build()
-
lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {
startClocks: relativeToClocks(0 as RelativeTime),
} as ViewCreatedEvent)
@@ -53,8 +50,6 @@ describe('featureFlagContexts', () => {
})
it('should replace existing feature flag evaluation to the current context', () => {
- const { lifeCycle } = setupBuilder.build()
-
lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {
startClocks: relativeToClocks(0 as RelativeTime),
} as ViewCreatedEvent)
@@ -69,8 +64,6 @@ describe('featureFlagContexts', () => {
})
it('should notify the customer data tracker on feature flag evaluation', () => {
- const { lifeCycle } = setupBuilder.build()
-
const updateCustomerDataSpy = spyOn(customerDataTracker, 'updateCustomerData')
lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {
@@ -89,14 +82,10 @@ describe('featureFlagContexts', () => {
* (which seems unlikely) and this event would anyway be rejected by lack of view id
*/
it('should return undefined when no current view', () => {
- setupBuilder.build()
-
expect(featureFlagContexts.findFeatureFlagEvaluations()).toBeUndefined()
})
it('should clear feature flag context on new view', () => {
- const { lifeCycle } = setupBuilder.build()
-
lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {
startClocks: relativeToClocks(0 as RelativeTime),
} as ViewCreatedEvent)
@@ -113,8 +102,6 @@ describe('featureFlagContexts', () => {
})
it('should return the feature flag context corresponding to the start time', () => {
- const { lifeCycle, clock } = setupBuilder.withFakeClock().build()
-
lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {
startClocks: relativeToClocks(0 as RelativeTime),
} as ViewCreatedEvent)
diff --git a/packages/rum-core/src/domain/view/trackViewEventCounts.spec.ts b/packages/rum-core/src/domain/view/trackViewEventCounts.spec.ts
index 3d952ca944..17743a460b 100644
--- a/packages/rum-core/src/domain/view/trackViewEventCounts.spec.ts
+++ b/packages/rum-core/src/domain/view/trackViewEventCounts.spec.ts
@@ -1,24 +1,22 @@
import type { Context } from '@datadog/browser-core'
+import { registerCleanupTask } from '@datadog/browser-core/test'
import type { RumEvent } from '../../rumEvent.types'
-import { LifeCycleEventType } from '../lifeCycle'
-import type { TestSetupBuilder } from '../../../test'
-import { setup } from '../../../test'
+import { LifeCycle, LifeCycleEventType } from '../lifeCycle'
import { RumEventType } from '../../rawRumEvent.types'
import { trackViewEventCounts } from './trackViewEventCounts'
describe('trackViewEventCounts', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
let onChange: () => void
beforeEach(() => {
onChange = jasmine.createSpy('onChange')
- setupBuilder = setup().beforeBuild(({ lifeCycle }) => trackViewEventCounts(lifeCycle, 'view-id', onChange))
+ const viewEventCountsTracking = trackViewEventCounts(lifeCycle, 'view-id', onChange)
+ registerCleanupTask(viewEventCountsTracking.stop)
})
it('should track events count', () => {
- const { lifeCycle } = setupBuilder.build()
-
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {
type: RumEventType.ERROR,
view: { id: 'view-id' },
@@ -28,8 +26,6 @@ describe('trackViewEventCounts', () => {
})
it('should not count child events unrelated to the view', () => {
- const { lifeCycle } = setupBuilder.build()
-
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {
type: RumEventType.ERROR,
view: { id: 'unrelated-view-id' },
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackCumulativeLayoutShift.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackCumulativeLayoutShift.spec.ts
index 4e09d78d04..d5c68ef812 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackCumulativeLayoutShift.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackCumulativeLayoutShift.spec.ts
@@ -1,63 +1,68 @@
import type { RelativeTime } from '@datadog/browser-core'
+import { registerCleanupTask } from '@datadog/browser-core/test'
import { resetExperimentalFeatures, elapsed, ONE_SECOND } from '@datadog/browser-core'
-import type { TestSetupBuilder } from '../../../../test'
-import { appendElement, appendText, createPerformanceEntry, setup } from '../../../../test'
-import { LifeCycleEventType } from '../../lifeCycle'
+import { appendElement, appendText, createPerformanceEntry } from '../../../../test'
+import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
+import type { RumConfiguration } from '../../configuration'
import type { CumulativeLayoutShift } from './trackCumulativeLayoutShift'
import { MAX_WINDOW_DURATION, trackCumulativeLayoutShift } from './trackCumulativeLayoutShift'
+interface StartCLSTrackingArgs {
+ viewStart: RelativeTime
+ isLayoutShiftSupported: boolean
+}
+
describe('trackCumulativeLayoutShift', () => {
- let setupBuilder: TestSetupBuilder
- let isLayoutShiftSupported: boolean
+ const lifeCycle = new LifeCycle()
let originalSupportedEntryTypes: PropertyDescriptor | undefined
let clsCallback: jasmine.Spy<(csl: CumulativeLayoutShift) => void>
- let viewStart: RelativeTime
- beforeEach(() => {
- if (
- !window.PerformanceObserver ||
- !PerformanceObserver.supportedEntryTypes ||
- !PerformanceObserver.supportedEntryTypes.includes('layout-shift')
- ) {
- pending('No LayoutShift API support')
+ function startCLSTracking(
+ { viewStart, isLayoutShiftSupported }: StartCLSTrackingArgs = {
+ viewStart: 0 as RelativeTime,
+ isLayoutShiftSupported: true,
}
-
+ ) {
clsCallback = jasmine.createSpy()
- viewStart = 0 as RelativeTime
- setupBuilder = setup().beforeBuild(({ lifeCycle, configuration }) =>
- trackCumulativeLayoutShift(configuration, lifeCycle, viewStart, clsCallback)
- )
-
originalSupportedEntryTypes = Object.getOwnPropertyDescriptor(PerformanceObserver, 'supportedEntryTypes')
- isLayoutShiftSupported = true
Object.defineProperty(PerformanceObserver, 'supportedEntryTypes', {
get: () => (isLayoutShiftSupported ? ['layout-shift'] : []),
})
- })
- afterEach(() => {
- if (originalSupportedEntryTypes) {
- Object.defineProperty(PerformanceObserver, 'supportedEntryTypes', originalSupportedEntryTypes)
+ const clsTrackingesult = trackCumulativeLayoutShift({} as RumConfiguration, lifeCycle, viewStart, clsCallback)
+
+ registerCleanupTask(() => {
+ clsTrackingesult.stop()
+ if (originalSupportedEntryTypes) {
+ Object.defineProperty(PerformanceObserver, 'supportedEntryTypes', originalSupportedEntryTypes)
+ }
+ })
+ }
+
+ beforeEach(() => {
+ if (
+ !window.PerformanceObserver ||
+ !PerformanceObserver.supportedEntryTypes ||
+ !PerformanceObserver.supportedEntryTypes.includes('layout-shift')
+ ) {
+ pending('No LayoutShift API support')
}
})
it('should be initialized to 0', () => {
- setupBuilder.build()
-
+ startCLSTracking()
expect(clsCallback).toHaveBeenCalledOnceWith({ value: 0 })
})
it('should be initialized to undefined if layout-shift is not supported', () => {
- isLayoutShiftSupported = false
- setupBuilder.build()
+ startCLSTracking({ viewStart: 0 as RelativeTime, isLayoutShiftSupported: false })
expect(clsCallback).not.toHaveBeenCalled()
})
it('should accumulate layout shift values for the first session window', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startCLSTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 1 as RelativeTime }),
])
@@ -75,8 +80,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should round the cumulative layout shift value to 4 decimals', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startCLSTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 1.23456789 }),
])
@@ -90,8 +94,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should ignore entries with recent input', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startCLSTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {
value: 0.1,
@@ -106,7 +109,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should create a new session window if the gap is more than 1 second', () => {
- const { lifeCycle } = setupBuilder.build()
+ startCLSTracking()
// first session window
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 0 as RelativeTime }),
@@ -131,8 +134,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should create a new session window if the current session window is more than 5 second', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startCLSTracking()
for (let i = 1; i <= 7; i++) {
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {
@@ -151,8 +153,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should get the max value sessions', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startCLSTracking()
// first session window: { value: 0.3, time: 1 }
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 0 as RelativeTime }),
@@ -204,8 +205,9 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should get the time from the beginning of the view', () => {
- viewStart = 100 as RelativeTime
- const { lifeCycle } = setupBuilder.build()
+ const viewStart = 100 as RelativeTime
+ startCLSTracking({ viewStart, isLayoutShiftSupported: true })
+
const shiftStart = 110 as RelativeTime
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: shiftStart }),
@@ -220,8 +222,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should return the first target element selector amongst all the shifted nodes', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startCLSTracking()
const textNode = appendText('text')
const divElement = appendElement('
')
@@ -236,8 +237,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should not return the target element when the element is detached from the DOM before the performance entry event is triggered', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startCLSTracking()
// first session window
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {
@@ -247,7 +247,6 @@ describe('trackCumulativeLayoutShift', () => {
])
expect(clsCallback.calls.mostRecent().args[0].value).toEqual(0.2)
-
// second session window
// first shift with an element
const divElement = appendElement('')
@@ -266,7 +265,7 @@ describe('trackCumulativeLayoutShift', () => {
})
it('should get the target element and time of the largest layout shift', () => {
- const { lifeCycle } = setupBuilder.build()
+ startCLSTracking()
const divElement = appendElement('')
// first session window: { value: 0.5, time: 1, targetSelector: '#div-element' }
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackFirstContentfulPaint.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackFirstContentfulPaint.spec.ts
index 8fdb57bba8..1999a785bc 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackFirstContentfulPaint.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackFirstContentfulPaint.spec.ts
@@ -1,40 +1,30 @@
import type { RelativeTime } from '@datadog/browser-core'
-import { restorePageVisibility, setPageVisibility } from '@datadog/browser-core/test'
+import { registerCleanupTask, restorePageVisibility, setPageVisibility } from '@datadog/browser-core/test'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
-import type { TestSetupBuilder } from '../../../../test'
-import { createPerformanceEntry, setup } from '../../../../test'
-import { LifeCycleEventType } from '../../lifeCycle'
+import { createPerformanceEntry } from '../../../../test'
+import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
import type { RumConfiguration } from '../../configuration'
import { FCP_MAXIMUM_DELAY, trackFirstContentfulPaint } from './trackFirstContentfulPaint'
import { trackFirstHidden } from './trackFirstHidden'
describe('trackFirstContentfulPaint', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
let fcpCallback: jasmine.Spy<(value: RelativeTime) => void>
- let configuration: RumConfiguration
- beforeEach(() => {
- configuration = {} as RumConfiguration
+ function startTrackingFCP() {
fcpCallback = jasmine.createSpy()
- setupBuilder = setup().beforeBuild(({ lifeCycle }) => {
- const firstHidden = trackFirstHidden(configuration)
- const firstContentfulPaint = trackFirstContentfulPaint(lifeCycle, firstHidden, fcpCallback)
- return {
- stop() {
- firstHidden.stop()
- firstContentfulPaint.stop()
- },
- }
- })
- })
+ const firstHidden = trackFirstHidden({} as RumConfiguration)
+ const firstContentfulPaint = trackFirstContentfulPaint(lifeCycle, firstHidden, fcpCallback)
- afterEach(() => {
- restorePageVisibility()
- })
+ registerCleanupTask(() => {
+ firstHidden.stop()
+ firstContentfulPaint.stop()
+ restorePageVisibility()
+ })
+ }
it('should provide the first contentful paint timing', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startTrackingFCP()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.PAINT),
])
@@ -45,7 +35,8 @@ describe('trackFirstContentfulPaint', () => {
it('should be discarded if the page is hidden', () => {
setPageVisibility('hidden')
- const { lifeCycle } = setupBuilder.build()
+ startTrackingFCP()
+
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.PAINT),
])
@@ -53,8 +44,7 @@ describe('trackFirstContentfulPaint', () => {
})
it('should be discarded if it is reported after a long time', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startTrackingFCP()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.PAINT, { startTime: FCP_MAXIMUM_DELAY as RelativeTime }),
])
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackFirstInput.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackFirstInput.spec.ts
index ebc2f9f116..5a0571447d 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackFirstInput.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackFirstInput.spec.ts
@@ -1,8 +1,7 @@
-import { type Duration, type RelativeTime, resetExperimentalFeatures } from '@datadog/browser-core'
-import { restorePageVisibility, setPageVisibility } from '@datadog/browser-core/test'
-import type { TestSetupBuilder } from '../../../../test'
-import { appendElement, appendText, createPerformanceEntry, setup } from '../../../../test'
-import { LifeCycleEventType } from '../../lifeCycle'
+import { type Duration, type RelativeTime } from '@datadog/browser-core'
+import { registerCleanupTask, restorePageVisibility, setPageVisibility } from '@datadog/browser-core/test'
+import { appendElement, appendText, createPerformanceEntry } from '../../../../test'
+import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
import type { RumConfiguration } from '../../configuration'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
import type { FirstInput } from './trackFirstInput'
@@ -10,35 +9,26 @@ import { trackFirstInput } from './trackFirstInput'
import { trackFirstHidden } from './trackFirstHidden'
describe('firstInputTimings', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
let fitCallback: jasmine.Spy<(firstInput: FirstInput) => void>
let configuration: RumConfiguration
- beforeEach(() => {
+ function startFirstInputTracking() {
configuration = {} as RumConfiguration
fitCallback = jasmine.createSpy()
- setupBuilder = setup().beforeBuild(({ lifeCycle }) => {
- const firstHidden = trackFirstHidden(configuration)
- const firstInputTimings = trackFirstInput(lifeCycle, configuration, firstHidden, fitCallback)
+ const firstHidden = trackFirstHidden(configuration)
+ const firstInputTimings = trackFirstInput(lifeCycle, configuration, firstHidden, fitCallback)
- return {
- stop() {
- firstHidden.stop()
- firstInputTimings.stop()
- },
- }
+ registerCleanupTask(() => {
+ firstHidden.stop()
+ firstInputTimings.stop()
+ restorePageVisibility()
})
- })
-
- afterEach(() => {
- restorePageVisibility()
- resetExperimentalFeatures()
- })
+ }
it('should provide the first input timings', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startFirstInputTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT),
])
@@ -51,8 +41,7 @@ describe('firstInputTimings', () => {
})
it('should provide the first input target selector', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startFirstInputTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT, {
target: appendElement(''),
@@ -67,8 +56,7 @@ describe('firstInputTimings', () => {
})
it("should not provide the first input target if it's not a DOM element", () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startFirstInputTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT, {
target: appendText('text'),
@@ -84,7 +72,7 @@ describe('firstInputTimings', () => {
it('should be discarded if the page is hidden', () => {
setPageVisibility('hidden')
- const { lifeCycle } = setupBuilder.build()
+ startFirstInputTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT),
@@ -94,8 +82,7 @@ describe('firstInputTimings', () => {
})
it('should be adjusted to 0 if the computed value would be negative due to browser timings imprecisions', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startFirstInputTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT, {
processingStart: 900 as RelativeTime,
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackInitialViewMetrics.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackInitialViewMetrics.spec.ts
index 841512899c..13ca9c31eb 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackInitialViewMetrics.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackInitialViewMetrics.spec.ts
@@ -1,36 +1,33 @@
import type { Duration, RelativeTime } from '@datadog/browser-core'
+import { registerCleanupTask } from '@datadog/browser-core/test'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
-import type { TestSetupBuilder } from '../../../../test'
-import { createPerformanceEntry, setup } from '../../../../test'
-import { LifeCycleEventType } from '../../lifeCycle'
+import { createPerformanceEntry } from '../../../../test'
+import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
import type { RumConfiguration } from '../../configuration'
import { trackInitialViewMetrics } from './trackInitialViewMetrics'
describe('trackInitialViewMetrics', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
let scheduleViewUpdateSpy: jasmine.Spy<() => void>
let trackInitialViewMetricsResult: ReturnType
let setLoadEventSpy: jasmine.Spy<(loadEvent: Duration) => void>
- let configuration: RumConfiguration
beforeEach(() => {
- configuration = {} as RumConfiguration
+ const configuration = {} as RumConfiguration
scheduleViewUpdateSpy = jasmine.createSpy()
setLoadEventSpy = jasmine.createSpy()
- setupBuilder = setup().beforeBuild(({ lifeCycle }) => {
- trackInitialViewMetricsResult = trackInitialViewMetrics(
- lifeCycle,
- configuration,
- setLoadEventSpy,
- scheduleViewUpdateSpy
- )
- return trackInitialViewMetricsResult
- })
+ trackInitialViewMetricsResult = trackInitialViewMetrics(
+ lifeCycle,
+ configuration,
+ setLoadEventSpy,
+ scheduleViewUpdateSpy
+ )
+
+ registerCleanupTask(trackInitialViewMetricsResult.stop)
})
it('should merge metrics from various sources', () => {
- const { lifeCycle } = setupBuilder.build()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.NAVIGATION),
createPerformanceEntry(RumPerformanceEntryType.PAINT),
@@ -56,8 +53,6 @@ describe('trackInitialViewMetrics', () => {
})
it('calls the `setLoadEvent` callback when the loadEvent timing is known', () => {
- const { lifeCycle } = setupBuilder.build()
-
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.NAVIGATION),
createPerformanceEntry(RumPerformanceEntryType.PAINT),
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts
index 4031950258..73e4c619f7 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts
@@ -1,8 +1,7 @@
import type { Duration, RelativeTime } from '@datadog/browser-core'
import { elapsed, resetExperimentalFeatures } from '@datadog/browser-core'
import { registerCleanupTask } from '@datadog/browser-core/test'
-import type { TestSetupBuilder } from '../../../../test'
-import { appendElement, appendText, createPerformanceEntry, setup } from '../../../../test'
+import { appendElement, appendText, createPerformanceEntry } from '../../../../test'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
import type {
BrowserWindow,
@@ -10,8 +9,8 @@ import type {
RumPerformanceEventTiming,
} from '../../../browser/performanceObservable'
import { ViewLoadingType } from '../../../rawRumEvent.types'
-import type { LifeCycle } from '../../lifeCycle'
-import { LifeCycleEventType } from '../../lifeCycle'
+import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
+import type { RumConfiguration } from '../../configuration'
import {
trackInteractionToNextPaint,
trackViewInteractionCount,
@@ -20,11 +19,10 @@ import {
} from './trackInteractionToNextPaint'
describe('trackInteractionToNextPaint', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
let interactionCountMock: ReturnType
let getInteractionToNextPaint: ReturnType['getInteractionToNextPaint']
let setViewEnd: ReturnType['setViewEnd']
- let viewStart: RelativeTime
function newInteraction(lifeCycle: LifeCycle, overrides: Partial) {
if (overrides.interactionId) {
@@ -34,39 +32,38 @@ describe('trackInteractionToNextPaint', () => {
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [entry])
}
- beforeEach(() => {
- if (!isInteractionToNextPaintSupported()) {
- pending('No INP support')
- }
+ function startINPTracking(viewStart = 0 as RelativeTime) {
interactionCountMock = mockInteractionCount()
- viewStart = 0 as RelativeTime
- setupBuilder = setup().beforeBuild(({ lifeCycle, configuration }) => {
- const interactionToNextPaintTracking = trackInteractionToNextPaint(
- configuration,
- viewStart,
- ViewLoadingType.INITIAL_LOAD,
- lifeCycle
- )
- getInteractionToNextPaint = interactionToNextPaintTracking.getInteractionToNextPaint
- setViewEnd = interactionToNextPaintTracking.setViewEnd
-
- return interactionToNextPaintTracking
- })
+ const interactionToNextPaintTracking = trackInteractionToNextPaint(
+ {} as RumConfiguration,
+ viewStart,
+ ViewLoadingType.INITIAL_LOAD,
+ lifeCycle
+ )
+ getInteractionToNextPaint = interactionToNextPaintTracking.getInteractionToNextPaint
+ setViewEnd = interactionToNextPaintTracking.setViewEnd
registerCleanupTask(() => {
+ interactionToNextPaintTracking.stop
resetExperimentalFeatures()
interactionCountMock.clear()
})
+ }
+
+ beforeEach(() => {
+ if (!isInteractionToNextPaintSupported()) {
+ pending('No INP support')
+ }
})
it('should return undefined when there are no interactions', () => {
- setupBuilder.build()
+ startINPTracking()
expect(getInteractionToNextPaint()).toEqual(undefined)
})
it('should ignore entries without interactionId', () => {
- const { lifeCycle } = setupBuilder.build()
+ startINPTracking()
newInteraction(lifeCycle, {
interactionId: undefined,
})
@@ -74,8 +71,7 @@ describe('trackInteractionToNextPaint', () => {
})
it('should ignore entries that starts out of the view time bounds', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startINPTracking()
setViewEnd(10 as RelativeTime)
newInteraction(lifeCycle, {
@@ -92,8 +88,7 @@ describe('trackInteractionToNextPaint', () => {
})
it('should take into account entries that starts in view time bounds but finish after view end', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startINPTracking()
setViewEnd(10 as RelativeTime)
newInteraction(lifeCycle, {
@@ -109,7 +104,7 @@ describe('trackInteractionToNextPaint', () => {
})
it('should cap INP value', () => {
- const { lifeCycle } = setupBuilder.build()
+ startINPTracking()
newInteraction(lifeCycle, {
interactionId: 1,
duration: (MAX_INP_VALUE + 1) as Duration,
@@ -124,7 +119,7 @@ describe('trackInteractionToNextPaint', () => {
})
it('should return the p98 worst interaction', () => {
- const { lifeCycle } = setupBuilder.build()
+ startINPTracking()
for (let index = 1; index <= 100; index++) {
newInteraction(lifeCycle, {
duration: index as Duration,
@@ -140,13 +135,13 @@ describe('trackInteractionToNextPaint', () => {
})
it('should return 0 when an interaction happened without generating a performance event (interaction duration below 40ms)', () => {
- setupBuilder.build()
+ startINPTracking()
interactionCountMock.setInteractionCount(1 as Duration) // assumes an interaction happened but no PERFORMANCE_ENTRIES_COLLECTED have been triggered
expect(getInteractionToNextPaint()).toEqual({ value: 0 as Duration })
})
it('should take first-input entry into account', () => {
- const { lifeCycle } = setupBuilder.build()
+ startINPTracking()
newInteraction(lifeCycle, {
interactionId: 1,
entryType: RumPerformanceEntryType.FIRST_INPUT,
@@ -160,8 +155,7 @@ describe('trackInteractionToNextPaint', () => {
})
it('should replace the entry in the list of worst interactions when an entry with the same interactionId exist', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startINPTracking()
for (let index = 1; index <= 100; index++) {
newInteraction(lifeCycle, {
duration: index as Duration,
@@ -178,8 +172,8 @@ describe('trackInteractionToNextPaint', () => {
})
it('should get the time from the beginning of the view', () => {
- viewStart = 100 as RelativeTime
- const { lifeCycle } = setupBuilder.build()
+ const viewStart = 100 as RelativeTime
+ startINPTracking(viewStart)
const interactionStart = 110 as RelativeTime
newInteraction(lifeCycle, {
@@ -192,8 +186,7 @@ describe('trackInteractionToNextPaint', () => {
describe('target selector', () => {
it('should be returned', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startINPTracking()
newInteraction(lifeCycle, {
interactionId: 2,
target: appendElement(''),
@@ -203,8 +196,7 @@ describe('trackInteractionToNextPaint', () => {
})
it("should not be returned if it's not a DOM element", () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startINPTracking()
newInteraction(lifeCycle, {
interactionId: 2,
target: appendText('text'),
@@ -214,8 +206,7 @@ describe('trackInteractionToNextPaint', () => {
})
it('should not be recomputed if the INP has not changed', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startINPTracking()
const element = appendElement('')
newInteraction(lifeCycle, {
interactionId: 1,
@@ -235,8 +226,7 @@ describe('trackInteractionToNextPaint', () => {
})
it('should be recomputed if the INP has changed', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startINPTracking()
newInteraction(lifeCycle, {
interactionId: 1,
duration: 10 as Duration,
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.spec.ts
index 43f9e3caa3..8d48db6e5f 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.spec.ts
@@ -1,51 +1,48 @@
import type { RelativeTime } from '@datadog/browser-core'
-import { DOM_EVENT, resetExperimentalFeatures } from '@datadog/browser-core'
-import { restorePageVisibility, setPageVisibility, createNewEvent } from '@datadog/browser-core/test'
+import { DOM_EVENT } from '@datadog/browser-core'
+import {
+ setPageVisibility,
+ createNewEvent,
+ restorePageVisibility,
+ registerCleanupTask,
+} from '@datadog/browser-core/test'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
-import type { TestSetupBuilder } from '../../../../test'
-import { appendElement, createPerformanceEntry, setup } from '../../../../test'
-import { LifeCycleEventType } from '../../lifeCycle'
+import { appendElement, createPerformanceEntry } from '../../../../test'
+import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
import type { RumConfiguration } from '../../configuration'
import type { LargestContentfulPaint } from './trackLargestContentfulPaint'
import { LCP_MAXIMUM_DELAY, trackLargestContentfulPaint } from './trackLargestContentfulPaint'
import { trackFirstHidden } from './trackFirstHidden'
describe('trackLargestContentfulPaint', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
let lcpCallback: jasmine.Spy<(lcp: LargestContentfulPaint) => void>
let eventTarget: Window
- let configuration: RumConfiguration
+
+ function startLCPTracking() {
+ const firstHidden = trackFirstHidden({} as RumConfiguration)
+ const largestContentfulPaint = trackLargestContentfulPaint(
+ lifeCycle,
+ {} as RumConfiguration,
+ firstHidden,
+ eventTarget,
+ lcpCallback
+ )
+
+ registerCleanupTask(() => {
+ firstHidden.stop()
+ largestContentfulPaint.stop()
+ restorePageVisibility()
+ })
+ }
beforeEach(() => {
- configuration = {} as RumConfiguration
lcpCallback = jasmine.createSpy()
eventTarget = document.createElement('div') as unknown as Window
- setupBuilder = setup().beforeBuild(({ lifeCycle }) => {
- const firstHidden = trackFirstHidden(configuration)
- const largestContentfulPaint = trackLargestContentfulPaint(
- lifeCycle,
- configuration,
- firstHidden,
- eventTarget,
- lcpCallback
- )
- return {
- stop() {
- firstHidden.stop()
- largestContentfulPaint.stop()
- },
- }
- })
- })
-
- afterEach(() => {
- restorePageVisibility()
- resetExperimentalFeatures()
})
it('should provide the largest contentful paint timing', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startLCPTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT),
])
@@ -54,8 +51,7 @@ describe('trackLargestContentfulPaint', () => {
})
it('should provide the largest contentful paint target selector', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startLCPTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {
element: appendElement(''),
@@ -66,8 +62,7 @@ describe('trackLargestContentfulPaint', () => {
})
it('should be discarded if it is reported after a user interaction', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startLCPTracking()
eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.KEY_DOWN, { timeStamp: 1 }))
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
@@ -79,7 +74,7 @@ describe('trackLargestContentfulPaint', () => {
it('should be discarded if the page is hidden', () => {
setPageVisibility('hidden')
- const { lifeCycle } = setupBuilder.build()
+ startLCPTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT),
@@ -89,8 +84,7 @@ describe('trackLargestContentfulPaint', () => {
})
it('should be discarded if it is reported after a long time', () => {
- const { lifeCycle } = setupBuilder.build()
-
+ startLCPTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {
startTime: LCP_MAXIMUM_DELAY as RelativeTime,
@@ -101,7 +95,7 @@ describe('trackLargestContentfulPaint', () => {
})
it('should be discarded if it has a size inferior to the previous LCP entry', () => {
- const { lifeCycle } = setupBuilder.build()
+ startLCPTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {
startTime: 1 as RelativeTime,
@@ -120,7 +114,7 @@ describe('trackLargestContentfulPaint', () => {
})
it('should notify multiple times when the size is bigger than the previous entry', () => {
- const { lifeCycle } = setupBuilder.build()
+ startLCPTracking()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {
startTime: 1 as RelativeTime,
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackNavigationTimings.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackNavigationTimings.spec.ts
index 3f56bf3975..722ac2cdc0 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackNavigationTimings.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackNavigationTimings.spec.ts
@@ -1,24 +1,23 @@
import type { Duration } from '@datadog/browser-core'
+import { registerCleanupTask } from '@datadog/browser-core/test'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
-import type { TestSetupBuilder } from '../../../../test'
-import { createPerformanceEntry, setup } from '../../../../test'
-import { LifeCycleEventType } from '../../lifeCycle'
+import { createPerformanceEntry } from '../../../../test'
+import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
import type { NavigationTimings } from './trackNavigationTimings'
import { trackNavigationTimings } from './trackNavigationTimings'
describe('trackNavigationTimings', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
let navigationTimingsCallback: jasmine.Spy<(timings: NavigationTimings) => void>
beforeEach(() => {
navigationTimingsCallback = jasmine.createSpy()
+ const trackNavigationTimingsResult = trackNavigationTimings(lifeCycle, navigationTimingsCallback)
- setupBuilder = setup().beforeBuild(({ lifeCycle }) => trackNavigationTimings(lifeCycle, navigationTimingsCallback))
+ registerCleanupTask(trackNavigationTimingsResult.stop)
})
it('should provide navigation timing', () => {
- const { lifeCycle } = setupBuilder.build()
-
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.NAVIGATION),
])
diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackScrollMetrics.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackScrollMetrics.spec.ts
index 8f6176a449..06755cee7b 100644
--- a/packages/rum-core/src/domain/view/viewMetrics/trackScrollMetrics.spec.ts
+++ b/packages/rum-core/src/domain/view/viewMetrics/trackScrollMetrics.spec.ts
@@ -1,8 +1,7 @@
import type { Duration, RelativeTime, Subscription, TimeStamp } from '@datadog/browser-core'
import { DOM_EVENT, Observable, isIE } from '@datadog/browser-core'
-import { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'
-import type { TestSetupBuilder } from '../../../../test'
-import { setup } from '../../../../test'
+import type { Clock } from '@datadog/browser-core/test'
+import { createNewEvent, mockClock, registerCleanupTask } from '@datadog/browser-core/test'
import type { RumConfiguration } from '../../configuration'
import type { ScrollMetrics, ScrollValues } from './trackScrollMetrics'
import { createScrollValuesObservable, trackScrollMetrics } from './trackScrollMetrics'
@@ -49,36 +48,33 @@ describe('createScrollValuesObserver', () => {
})
describe('trackScrollMetrics', () => {
- let setupBuilder: TestSetupBuilder
+ let clock: Clock
let scrollMetricsCallback: jasmine.Spy<(metrics: ScrollMetrics) => void>
const scrollObservable = new Observable()
beforeEach(() => {
scrollMetricsCallback = jasmine.createSpy()
- setupBuilder = setup()
- .withFakeClock()
- .beforeBuild(({ configuration }) =>
- trackScrollMetrics(
- configuration,
- { relative: 0 as RelativeTime, timeStamp: 0 as TimeStamp },
- scrollMetricsCallback,
- scrollObservable
- )
- )
+ clock = mockClock()
+ trackScrollMetrics(
+ {} as RumConfiguration,
+ { relative: 0 as RelativeTime, timeStamp: 0 as TimeStamp },
+ scrollMetricsCallback,
+ scrollObservable
+ )
})
afterEach(() => {
document.body.innerHTML = ''
+ clock.cleanup()
})
const updateScrollValues = (scrollValues: ScrollValues) => {
- setupBuilder.clock!.tick(100)
+ clock.tick(100)
scrollObservable.notify(scrollValues)
}
it('should update scroll height and scroll depth', () => {
- setupBuilder.build()
updateScrollValues({ scrollDepth: 700, scrollHeight: 2000, scrollTop: 100 })
expect(scrollMetricsCallback).toHaveBeenCalledOnceWith({
maxDepth: 700,
@@ -88,7 +84,6 @@ describe('trackScrollMetrics', () => {
})
})
it('should update time and scroll height only if it has increased', () => {
- setupBuilder.build()
updateScrollValues({ scrollDepth: 700, scrollHeight: 2000, scrollTop: 100 })
updateScrollValues({ scrollDepth: 700, scrollHeight: 1900, scrollTop: 100 })
expect(scrollMetricsCallback).toHaveBeenCalledOnceWith({
@@ -100,7 +95,6 @@ describe('trackScrollMetrics', () => {
})
it('should update max depth only if it has increased', () => {
- setupBuilder.build()
updateScrollValues({ scrollDepth: 700, scrollHeight: 2000, scrollTop: 100 })
updateScrollValues({ scrollDepth: 600, scrollHeight: 2000, scrollTop: 0 })
expect(scrollMetricsCallback).toHaveBeenCalledOnceWith({
diff --git a/packages/rum-core/src/domain/vital/vitalCollection.spec.ts b/packages/rum-core/src/domain/vital/vitalCollection.spec.ts
index a9b4c68e59..9b0fbd5800 100644
--- a/packages/rum-core/src/domain/vital/vitalCollection.spec.ts
+++ b/packages/rum-core/src/domain/vital/vitalCollection.spec.ts
@@ -1,30 +1,48 @@
import type { Duration } from '@datadog/browser-core'
+import { mockClock, registerCleanupTask, type Clock } from '@datadog/browser-core/test'
import { clocksNow } from '@datadog/browser-core'
-import type { TestSetupBuilder } from '../../../test'
-import { setup } from '../../../test'
-import type { RawRumVitalEvent } from '../../rawRumEvent.types'
+import { validateRumEventFormat } from '../../../test'
+import type { RawRumEvent, RawRumVitalEvent } from '../../rawRumEvent.types'
import { VitalType, RumEventType } from '../../rawRumEvent.types'
+import type { RawRumEventCollectedData } from '../lifeCycle'
+import { LifeCycle, LifeCycleEventType } from '../lifeCycle'
+import type { PageStateHistory } from '../contexts/pageStateHistory'
import { createVitalInstance, startVitalCollection } from './vitalCollection'
+const pageStateHistory: PageStateHistory = {
+ findAll: () => undefined,
+ addPageState: () => {},
+ stop: () => {},
+ wasInPageStateAt: () => false,
+ wasInPageStateDuringPeriod: () => false,
+}
+
describe('vitalCollection', () => {
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
+ let rawRumEvents: Array> = []
+ let clock: Clock
let vitalCollection: ReturnType
let wasInPageStateDuringPeriodSpy: jasmine.Spy
beforeEach(() => {
- setupBuilder = setup()
- .withFakeClock()
- .beforeBuild(({ lifeCycle, pageStateHistory }) => {
- wasInPageStateDuringPeriodSpy = spyOn(pageStateHistory, 'wasInPageStateDuringPeriod')
- vitalCollection = startVitalCollection(lifeCycle, pageStateHistory)
- })
+ clock = mockClock()
+ wasInPageStateDuringPeriodSpy = spyOn(pageStateHistory, 'wasInPageStateDuringPeriod')
+ vitalCollection = startVitalCollection(lifeCycle, pageStateHistory)
+ const eventsSubscription = lifeCycle.subscribe(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, (data) => {
+ rawRumEvents.push(data)
+ validateRumEventFormat(data.rawRumEvent)
+ })
+
+ registerCleanupTask(() => {
+ eventsSubscription.unsubscribe()
+ rawRumEvents = []
+ clock.cleanup()
+ })
})
describe('custom duration', () => {
describe('createVitalInstance', () => {
it('should create duration vital from a vital instance', () => {
- const { clock } = setupBuilder.build()
-
const cbSpy = jasmine.createSpy()
const vital = createVitalInstance(cbSpy, { name: 'foo' })
@@ -53,8 +71,6 @@ describe('vitalCollection', () => {
})
it('should create multiple duration vitals from createVitalInstance', () => {
- const { clock } = setupBuilder.build()
-
const cbSpy = jasmine.createSpy()
const vital1 = createVitalInstance(cbSpy, { name: 'foo', details: 'component 1' })
@@ -108,8 +124,6 @@ describe('vitalCollection', () => {
})
it('should create a vital from start API', () => {
- const { rawRumEvents, clock } = setupBuilder.build()
-
const vital = vitalCollection.startDurationVital({
name: 'foo',
context: { foo: 'bar' },
@@ -127,8 +141,6 @@ describe('vitalCollection', () => {
})
it('should create a vital from add API', () => {
- const { rawRumEvents } = setupBuilder.build()
-
vitalCollection.addDurationVital({
name: 'foo',
type: VitalType.DURATION,
@@ -145,7 +157,6 @@ describe('vitalCollection', () => {
})
it('should discard a vital for which a frozen state happened', () => {
- const { rawRumEvents } = setupBuilder.build()
wasInPageStateDuringPeriodSpy.and.returnValue(true)
vitalCollection.addDurationVital({
@@ -160,8 +171,6 @@ describe('vitalCollection', () => {
})
it('should collect raw rum event from duration vital', () => {
- const { rawRumEvents } = setupBuilder.build()
-
const vital = createVitalInstance(vitalCollection.addDurationVital, { name: 'foo' })
vital.stop()
diff --git a/packages/rum-core/src/domain/waitPageActivityEnd.spec.ts b/packages/rum-core/src/domain/waitPageActivityEnd.spec.ts
index 6cdaf333aa..cb1db9332b 100644
--- a/packages/rum-core/src/domain/waitPageActivityEnd.spec.ts
+++ b/packages/rum-core/src/domain/waitPageActivityEnd.spec.ts
@@ -1,12 +1,11 @@
import type { RelativeTime, Subscription } from '@datadog/browser-core'
import { Observable, ONE_SECOND, getTimeStamp } from '@datadog/browser-core'
import type { Clock } from '@datadog/browser-core/test'
-import { mockClock } from '@datadog/browser-core/test'
-import type { TestSetupBuilder } from '../../test'
-import { createPerformanceEntry, mockPerformanceObserver, setup } from '../../test'
+import { mockClock, SPEC_ENDPOINTS } from '@datadog/browser-core/test'
+import { createPerformanceEntry, mockPerformanceObserver } from '../../test'
import type { RumPerformanceEntry } from '../browser/performanceObservable'
import { RumPerformanceEntryType } from '../browser/performanceObservable'
-import { LifeCycleEventType } from './lifeCycle'
+import { LifeCycle, LifeCycleEventType } from './lifeCycle'
import type { RequestCompleteEvent, RequestStartEvent } from './requestCollection'
import type { PageActivityEvent, PageActivityEndEvent } from './waitPageActivityEnd'
import {
@@ -15,6 +14,8 @@ import {
doWaitPageActivityEnd,
createPageActivityObservable,
} from './waitPageActivityEnd'
+import type { RumConfiguration } from './configuration'
+import { validateAndBuildRumConfiguration } from './configuration'
// Used to wait some time after the creation of an action
const BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY = PAGE_ACTIVITY_VALIDATION_DELAY * 0.8
@@ -41,38 +42,57 @@ function eventsCollector() {
}
}
+const RUM_CONFIGURATION: RumConfiguration = {
+ ...validateAndBuildRumConfiguration({
+ clientToken: 'xxx',
+ applicationId: 'AppId',
+ trackResources: true,
+ trackLongTasks: true,
+ })!,
+ ...SPEC_ENDPOINTS,
+}
+
describe('createPageActivityObservable', () => {
const { events, pushEvent } = eventsCollector()
- let setupBuilder: TestSetupBuilder
+ const lifeCycle = new LifeCycle()
+ const domMutationObservable = new Observable()
let pageActivitySubscription: Subscription
let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void
+ function startListeningToPageActivities(
+ extraConfiguration: Partial = { excludedActivityUrls: [EXCLUDED_FAKE_URL] }
+ ) {
+ const pageActivityObservable = createPageActivityObservable(lifeCycle, domMutationObservable, {
+ ...RUM_CONFIGURATION,
+ ...extraConfiguration,
+ })
+ pageActivitySubscription = pageActivityObservable.subscribe(pushEvent)
+ }
+
beforeEach(() => {
;({ notifyPerformanceEntries } = mockPerformanceObserver())
- setupBuilder = setup()
- .withConfiguration({ excludedActivityUrls: [EXCLUDED_FAKE_URL] })
- .beforeBuild(({ lifeCycle, domMutationObservable, configuration }) => {
- const pageActivityObservable = createPageActivityObservable(lifeCycle, domMutationObservable, configuration)
- pageActivitySubscription = pageActivityObservable.subscribe(pushEvent)
- })
+ })
+
+ afterEach(() => {
+ pageActivitySubscription.unsubscribe()
})
it('emits an activity event on dom mutation', () => {
- const { domMutationObservable } = setupBuilder.build()
+ startListeningToPageActivities()
domMutationObservable.notify()
expect(events).toEqual([{ isBusy: false }])
})
it('emits an activity event on resource collected', () => {
- setupBuilder.build()
+ startListeningToPageActivities()
notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE)])
expect(events).toEqual([{ isBusy: false }])
})
it('does not emit an activity event when a navigation occurs', () => {
- const { lifeCycle } = setupBuilder.build()
+ startListeningToPageActivities()
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, [
createPerformanceEntry(RumPerformanceEntryType.NAVIGATION),
])
@@ -81,13 +101,13 @@ describe('createPageActivityObservable', () => {
it('emits an activity event when `window.open` is used', () => {
spyOn(window, 'open')
- setupBuilder.build()
+ startListeningToPageActivities()
window.open('toto')
expect(events).toEqual([{ isBusy: false }])
})
it('stops emitting activities after calling stop()', () => {
- const { domMutationObservable } = setupBuilder.build()
+ startListeningToPageActivities()
domMutationObservable.notify()
expect(events).toEqual([{ isBusy: false }])
@@ -101,26 +121,26 @@ describe('createPageActivityObservable', () => {
describe('programmatic requests', () => {
it('emits an activity event when a request starts', () => {
- const { lifeCycle } = setupBuilder.build()
+ startListeningToPageActivities()
lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10))
expect(events).toEqual([{ isBusy: true }])
})
it('emits an activity event when a request completes', () => {
- const { lifeCycle } = setupBuilder.build()
+ startListeningToPageActivities()
lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10))
lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10))
expect(events).toEqual([{ isBusy: true }, { isBusy: false }])
})
it('ignores requests that has started before', () => {
- const { lifeCycle } = setupBuilder.build()
+ startListeningToPageActivities()
lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10))
expect(events).toEqual([])
})
it('keeps emitting busy events while all requests are not completed', () => {
- const { lifeCycle } = setupBuilder.build()
+ startListeningToPageActivities()
lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10))
lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(11))
lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(9))
@@ -131,15 +151,13 @@ describe('createPageActivityObservable', () => {
describe('excludedActivityUrls', () => {
it('ignores resources that should be excluded by configuration', () => {
- setupBuilder
- .withConfiguration({
- excludedActivityUrls: [
- /^https?:\/\/qux\.com.*/,
- 'http://bar.com',
- (url: string) => url === 'http://dynamic.com',
- ],
- })
- .build()
+ startListeningToPageActivities({
+ excludedActivityUrls: [
+ /^https?:\/\/qux\.com.*/,
+ 'http://bar.com',
+ (url: string) => url === 'http://dynamic.com',
+ ],
+ })
notifyPerformanceEntries([
createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: 'http://qux.com' }),
@@ -151,14 +169,14 @@ describe('createPageActivityObservable', () => {
})
it('ignores requests that should be excluded by configuration', () => {
- const { lifeCycle } = setupBuilder.build()
+ startListeningToPageActivities()
lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10, EXCLUDED_FAKE_URL))
lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10, EXCLUDED_FAKE_URL))
expect(events).toEqual([])
})
it("ignored requests don't interfere with pending requests count", () => {
- const { lifeCycle } = setupBuilder.build()
+ startListeningToPageActivities()
lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(9))
lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10, EXCLUDED_FAKE_URL))
lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10, EXCLUDED_FAKE_URL))
diff --git a/packages/rum-core/test/testSetupBuilder.ts b/packages/rum-core/test/testSetupBuilder.ts
index d1d5d41444..59e6b72e5d 100644
--- a/packages/rum-core/test/testSetupBuilder.ts
+++ b/packages/rum-core/test/testSetupBuilder.ts
@@ -230,7 +230,7 @@ export function setup(): TestSetupBuilder {
return setupBuilder
}
-function validateRumEventFormat(rawRumEvent: RawRumEvent) {
+export function validateRumEventFormat(rawRumEvent: RawRumEvent) {
const fakeId = '00000000-aaaa-0000-aaaa-000000000000'
const fakeContext: RumContext = {
_dd: {