Skip to content
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

⚗️✨ [RUM-2445] implement Tracking Consent management #2589

Merged
merged 13 commits into from Feb 12, 2024
Merged
35 changes: 28 additions & 7 deletions packages/core/src/domain/configuration/configuration.spec.ts
Expand Up @@ -5,12 +5,19 @@ import {
isExperimentalFeatureEnabled,
resetExperimentalFeatures,
} from '../../tools/experimentalFeatures'
import { TrackingConsent } from '../trackingConsent'
import type { InitConfiguration } from './configuration'
import { validateAndBuildConfiguration } from './configuration'

describe('validateAndBuildConfiguration', () => {
const clientToken = 'some_client_token'

let displaySpy: jasmine.Spy<typeof display.error>

beforeEach(() => {
displaySpy = spyOn(display, 'error')
})

afterEach(() => {
resetExperimentalFeatures()
})
Expand Down Expand Up @@ -44,12 +51,6 @@ describe('validateAndBuildConfiguration', () => {
})

describe('validate init configuration', () => {
let displaySpy: jasmine.Spy<typeof display.error>

beforeEach(() => {
displaySpy = spyOn(display, 'error')
})

it('requires the InitConfiguration to be defined', () => {
expect(validateAndBuildConfiguration(undefined as unknown as InitConfiguration)).toBeUndefined()
expect(displaySpy).toHaveBeenCalledOnceWith('Client Token is not configured, we will not send any data.')
Expand Down Expand Up @@ -160,7 +161,6 @@ describe('validateAndBuildConfiguration', () => {
throw myError
}
const configuration = validateAndBuildConfiguration({ clientToken, beforeSend })!
const displaySpy = spyOn(display, 'error')
expect(configuration.beforeSend!(null, {})).toBeUndefined()
expect(displaySpy).toHaveBeenCalledWith('beforeSend threw an error:', myError)
})
Expand All @@ -186,4 +186,25 @@ describe('validateAndBuildConfiguration', () => {
).toBeTrue()
})
})

describe('trackingConsent', () => {
it('defaults to "granted"', () => {
expect(validateAndBuildConfiguration({ clientToken: 'yes' })!.trackingConsent).toBe(TrackingConsent.GRANTED)
})

it('is set to provided value', () => {
expect(
validateAndBuildConfiguration({ clientToken: 'yes', trackingConsent: TrackingConsent.NOT_GRANTED })!
.trackingConsent
).toBe(TrackingConsent.NOT_GRANTED)
expect(
validateAndBuildConfiguration({ clientToken: 'yes', trackingConsent: TrackingConsent.GRANTED })!.trackingConsent
).toBe(TrackingConsent.GRANTED)
})

it('rejects invalid values', () => {
expect(validateAndBuildConfiguration({ clientToken: 'yes', trackingConsent: 'foo' as any })).toBeUndefined()
expect(displaySpy).toHaveBeenCalledOnceWith('Tracking Consent should be either "granted" or "not-granted"')
})
})
})
12 changes: 12 additions & 0 deletions packages/core/src/domain/configuration/configuration.ts
Expand Up @@ -10,6 +10,7 @@ import { objectHasValue } from '../../tools/utils/objectUtils'
import { assign } from '../../tools/utils/polyfills'
import { selectSessionStoreStrategyType } from '../session/sessionStore'
import type { SessionStoreStrategyType } from '../session/storeStrategies/sessionStoreStrategy'
import { TrackingConsent } from '../trackingConsent'
import type { TransportConfiguration } from './transportConfiguration'
import { computeTransportConfiguration } from './transportConfiguration'

Expand All @@ -30,6 +31,7 @@ export interface InitConfiguration {
allowFallbackToLocalStorage?: boolean | undefined
allowUntrustedEvents?: boolean | undefined
storeContextsAcrossPages?: boolean | undefined
trackingConsent?: TrackingConsent | undefined

// transport options
proxy?: string | ProxyFn | undefined
Expand Down Expand Up @@ -84,6 +86,7 @@ export interface Configuration extends TransportConfiguration {
service: string | undefined
silentMultipleInit: boolean
allowUntrustedEvents: boolean
trackingConsent: TrackingConsent

// Event limits
eventRateLimiterThreshold: number // Limit the maximum number of actions, errors and logs per minutes
Expand Down Expand Up @@ -120,6 +123,14 @@ export function validateAndBuildConfiguration(initConfiguration: InitConfigurati
return
}

if (
initConfiguration.trackingConsent !== undefined &&
!objectHasValue(TrackingConsent, initConfiguration.trackingConsent)
) {
display.error('Tracking Consent should be either "granted" or "not-granted"')
return
}

// Set the experimental feature flags as early as possible, so we can use them in most places
if (Array.isArray(initConfiguration.enableExperimentalFeatures)) {
addExperimentalFeatures(
Expand All @@ -140,6 +151,7 @@ export function validateAndBuildConfiguration(initConfiguration: InitConfigurati
service: initConfiguration.service,
silentMultipleInit: !!initConfiguration.silentMultipleInit,
allowUntrustedEvents: !!initConfiguration.allowUntrustedEvents,
trackingConsent: initConfiguration.trackingConsent ?? TrackingConsent.GRANTED,

/**
* beacon payload max queue size implementation is 64kb
Expand Down