Skip to content

Commit

Permalink
Add onetrust-wrapper unit tests (#903)
Browse files Browse the repository at this point in the history
  • Loading branch information
silesky authored Jul 18, 2023
1 parent f2380bb commit 890ce47
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 1 deletion.
4 changes: 4 additions & 0 deletions packages/consent/consent-wrapper-onetrust/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"!*.tsbuildinfo"
],
"scripts": {
"test": "yarn jest",
"lint": "yarn concurrently 'yarn:eslint .' 'yarn:tsc --noEmit'",
"build": "rm -rf dist && yarn concurrently 'yarn:build:*'",
"build...": "yarn run -T turbo run build --filter=@segment/analytics-consent-wrapper-onetrust",
Expand All @@ -33,5 +34,8 @@
"directory": "packages/consent/consent-wrapper-onetrust",
"type": "git",
"url": "https://github.com/segmentio/analytics-next"
},
"devDependencies": {
"@internal/test-helpers": "workspace:^"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import * as ConsentTools from '@segment/analytics-consent-tools'
import * as OneTrustAPI from '../../lib/onetrust-api'
import { sleep } from '@internal/test-helpers'

const throwNotImplemented = (): never => {
throw new Error('not implemented')
}

const grpFixture = {
StrictlyNeccessary: {
CustomGroupId: 'C0001',
GroupName: 'Strictly Neccessary Cookies',
},
Targeting: {
CustomGroupId: 'C0004',
GroupName: 'Targeting Cookies',
},
Performance: {
CustomGroupId: 'C0005',
GroupName: 'Performance Cookies',
},
}

/**
* This can be used to mock the OneTrust global object in individual tests
*/
const OneTrustMockGlobal: jest.Mocked<OneTrustAPI.OneTrustGlobal> = {
GetDomainData: jest.fn().mockImplementationOnce(throwNotImplemented),
IsAlertBoxClosed: jest.fn().mockImplementationOnce(() => false),
onConsentChanged: jest.fn(), // not implemented atm
}

const getConsentedGroupIdsSpy = jest
.spyOn(OneTrustAPI, 'getConsentedGroupIds')
.mockImplementationOnce(throwNotImplemented)

const helpers = {
_createWrapperSpy: jest.spyOn(ConsentTools, 'createWrapper'),
get shouldLoad() {
return helpers._createWrapperSpy.mock.lastCall[0].shouldLoad!
},
get getCategories() {
return helpers._createWrapperSpy.mock.lastCall[0].getCategories!
},
}

import { oneTrust } from '../wrapper'

/**
* These tests are not meant to be comprehensive, but they should cover the most important cases.
* We should prefer unit tests for most functionality (see lib/__tests__)
*/
describe('High level "integration" tests', () => {
beforeEach(() => {
oneTrust({} as any)
getConsentedGroupIdsSpy.mockReset()
Object.values(OneTrustMockGlobal).forEach((fn) => fn.mockReset())
jest
.spyOn(OneTrustAPI, 'getOneTrustGlobal')
.mockImplementation(() => OneTrustMockGlobal)
})

describe('shouldLoad', () => {
/**
* Typically, resolveWhen triggers when a predicate is true. We can manually 'check' so we don't have to use timeouts.
*/
let resolveResolveWhen = () => {}
jest.spyOn(ConsentTools, 'resolveWhen').mockImplementation(async (fn) => {
return new Promise((_resolve) => {
resolveResolveWhen = () => {
if (fn()) {
_resolve()
} else {
throw new Error('Refuse to resolve, resolveWhen condition is false')
}
}
})
})

it('should be resolved successfully', async () => {
OneTrustMockGlobal.GetDomainData.mockReturnValueOnce({
Groups: [grpFixture.StrictlyNeccessary, grpFixture.Performance],
})
getConsentedGroupIdsSpy.mockImplementation(() => [
grpFixture.StrictlyNeccessary.CustomGroupId,
])
const shouldLoadP = Promise.resolve(helpers.shouldLoad({} as any))
let shouldLoadResolved = false
void shouldLoadP.then(() => (shouldLoadResolved = true))
await sleep(0)
expect(shouldLoadResolved).toBe(false)
OneTrustMockGlobal.IsAlertBoxClosed.mockReturnValueOnce(true)
resolveResolveWhen()
const result = await shouldLoadP
expect(result).toBe(undefined)
})
})

describe('getCategories', () => {
it('should get categories successfully', async () => {
OneTrustMockGlobal.GetDomainData.mockReturnValue({
Groups: [
grpFixture.StrictlyNeccessary,
grpFixture.Performance,
grpFixture.Targeting,
],
})
getConsentedGroupIdsSpy.mockImplementation(() => [
grpFixture.StrictlyNeccessary.CustomGroupId,
])
const categories = helpers.getCategories()
// contain both consented and denied category
expect(categories).toEqual({
C0001: true,
'Strictly Neccessary Cookies': true,
C0004: false,
'Targeting Cookies': false,
C0005: false,
'Performance Cookies': false,
})
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import './onetrust-globals.d.ts'

import { getConsentedGroupIds, getGroupData } from '../onetrust-api'

beforeEach(() => {
// @ts-ignore
delete window.OneTrustActiveGroups
// @ts-ignore
delete window.OneTrust
})

describe(getConsentedGroupIds, () => {
it('should return an empty array if no groups are consented', () => {
window.OnetrustActiveGroups = ',C0001,C0004,C0003,STACK42,'
expect(getConsentedGroupIds()).toEqual([
'C0001',
'C0004',
'C0003',
'STACK42',
])
})
it('should work even without the strange leading/trailing commas that onetrust adds', () => {
window.OnetrustActiveGroups = 'C0001,C0004'
expect(getConsentedGroupIds()).toEqual(['C0001', 'C0004'])
})

it('should return an array with only 1 active group if that is the only one consented', () => {
window.OnetrustActiveGroups = ',C0001,'
expect(getConsentedGroupIds()).toEqual(['C0001'])
})

it('should return an empty array if no groups are defined', () => {
window.OnetrustActiveGroups = ',,'
expect(getConsentedGroupIds()).toEqual([])
window.OnetrustActiveGroups = ','
expect(getConsentedGroupIds()).toEqual([])
// @ts-ignore
window.OnetrustActiveGroups = undefined
expect(getConsentedGroupIds()).toEqual([])
})
})

describe(getGroupData, () => {
it('should partition groups into consent/deny', () => {
window.OnetrustActiveGroups = ',C0001,C0004'
window.OneTrust = {
...window.OneTrust,
GetDomainData: () => ({
Groups: [
{
CustomGroupId: 'C0001',
GroupName: 'Strictly Neccessary Cookies',
},
{
CustomGroupId: 'C0004',
GroupName: 'Targeting Cookies',
},
{
CustomGroupId: 'SOME_OTHER_GROUP',
GroupName: 'Some other group',
},
],
}),
}
const data = getGroupData()

expect(data.userSetConsentGroups).toMatchInlineSnapshot(`
Array [
Object {
"customGroupId": "C0001",
"groupName": "Strictly Neccessary Cookies",
},
Object {
"customGroupId": "C0004",
"groupName": "Targeting Cookies",
},
]
`)
expect(data.userDeniedConsentGroups).toMatchInlineSnapshot(`
Array [
Object {
"customGroupId": "SOME_OTHER_GROUP",
"groupName": "Some other group",
},
]
`)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { OneTrustGlobal } from '../onetrust-api'
/**
* ALERT: It's OK to declare ambient globals in test code, but __not__ in library code
* This file should not be included in the final package
*/
export declare global {
interface Window {
OneTrust: OneTrustGlobal
OnetrustActiveGroups: string
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type GroupInfoDto = {
/**
* The data model used by the OneTrust lib
*/
interface OneTrustGlobal {
export interface OneTrustGlobal {
GetDomainData: () => {
Groups: GroupInfoDto[]
}
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@segment/analytics-consent-wrapper-onetrust@workspace:packages/consent/consent-wrapper-onetrust"
dependencies:
"@internal/test-helpers": "workspace:^"
"@segment/analytics-consent-tools": 0.0.3
languageName: unknown
linkType: soft
Expand Down

0 comments on commit 890ce47

Please sign in to comment.