-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
774 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@guardian/consent-management-platform': patch | ||
--- | ||
|
||
testing consent wrappers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { onConsentChange } from './onConsentChange'; | ||
import type { Callback, ConsentState } from './types'; | ||
import type { TCFv2ConsentState } from './types/tcfv2'; | ||
import {cmpGetCookie, cmpSetCookie } from './cmpCookies'; | ||
import { getCookie as getCookie_, setCookie as setCookie_} from '@guardian/libs'; | ||
|
||
jest.mock('./onConsentChange'); | ||
jest.mock('@guardian/libs', () => ({ | ||
getCookie: jest.fn(), | ||
setCookie: jest.fn(), | ||
storage: { | ||
local: { | ||
get: jest.fn(), | ||
set: jest.fn(), | ||
}, | ||
session: { | ||
get: jest.fn(), | ||
set: jest.fn(), | ||
}, | ||
} | ||
})); | ||
|
||
const tcfv2ConsentState: TCFv2ConsentState = { | ||
consents: { 1: true }, | ||
eventStatus: 'tcloaded', | ||
vendorConsents: { | ||
['5efefe25b8e05c06542b2a77']: true, | ||
}, | ||
addtlConsent: 'xyz', | ||
gdprApplies: true, | ||
tcString: 'YAAA', | ||
}; | ||
|
||
const tcfv2ConsentStateNoConsent: TCFv2ConsentState = { | ||
consents: { 1: false }, | ||
eventStatus: 'tcloaded', | ||
vendorConsents: {}, | ||
addtlConsent: 'xyz', | ||
gdprApplies: true, | ||
tcString: 'YAAA', | ||
}; | ||
|
||
const mockOnConsentChange = (consentState: ConsentState) => | ||
(onConsentChange as jest.Mock).mockImplementation((cb: Callback) => cb(consentState)); | ||
|
||
describe('cookies return the expected consent', () => { | ||
let mockContains:any; | ||
|
||
beforeEach(() => { | ||
mockContains = 'someTestData'; | ||
|
||
(getCookie_ as jest.Mock).mockImplementation(({name }: { | ||
name: string; | ||
}) => { | ||
if (name === 'gu.mock') {return mockContains} | ||
else {return(null)} | ||
}); | ||
|
||
(setCookie_ as jest.Mock).mockImplementation(({ name, value }: { | ||
name: string; | ||
value: string; | ||
}) => { | ||
if (name === 'gu.mock') {mockContains = value;} | ||
}); | ||
}); | ||
|
||
test('Targeted advertising get cookie returns null when canTarget is false', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentState, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const cookieValue = await cmpGetCookie({useCase: 'Targeted advertising', name: 'gu.mock'}); | ||
expect(cookieValue).toEqual(null); | ||
}); | ||
test('Targeted advertising can set and get cookies when canTarget is true', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentState, | ||
canTarget: true, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const cookieValueDefault = await cmpGetCookie({useCase: 'Targeted advertising', name: 'gu.mock'}); | ||
expect(cookieValueDefault).toEqual('someTestData'); | ||
await cmpSetCookie({useCase: 'Essential', name: 'gu.mock', value: 'testdataAd'}); | ||
const cookieValue = await cmpGetCookie({useCase: 'Targeted advertising', name: 'gu.mock'}); | ||
expect(cookieValue).toEqual('testdataAd'); | ||
}); | ||
test('Essential can set and get cookies when no consents', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentStateNoConsent, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const cookieValueDefault = await cmpGetCookie({useCase: 'Essential', name:'gu.mock'}); | ||
expect(cookieValueDefault).toEqual('someTestData'); | ||
await cmpSetCookie({useCase: 'Essential', name: 'gu.mock', value: 'testdata'}); | ||
const cookieValue = await cmpGetCookie({useCase: 'Essential', name: 'gu.mock'}); | ||
expect(cookieValue).toEqual('testdata'); | ||
}); | ||
test('get null if cookie does not exist', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentStateNoConsent, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const cookieValue = await cmpGetCookie({useCase: 'Essential', name: 'gu.does_not_exist'}); | ||
expect(cookieValue).toEqual(null); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { getCookie, setCookie, setSessionCookie } from '@guardian/libs'; | ||
import { hasConsentForUseCaseWithConsentState } from './hasConsentForUseCase'; | ||
import { onConsent } from './onConsent'; | ||
import { ConsentState } from './types'; | ||
import type { ConsentUseCases } from './types/consentUseCases'; | ||
|
||
//TODO?: Write wrappers for the other cookie functions in @guardian/libs | ||
|
||
export const cmpGetCookie = async({ useCase, name, shouldMemoize, }: { | ||
useCase: ConsentUseCases, | ||
name: string; | ||
shouldMemoize?: boolean | undefined; | ||
}): Promise<string | null> => | ||
{ | ||
const consentState = await onConsent(); | ||
return(cmpGetCookieWithConsentState({useCase, consentState, name, shouldMemoize})) | ||
} | ||
|
||
export const cmpGetCookieWithConsentState = ({ useCase, consentState, name, shouldMemoize}: { | ||
useCase: ConsentUseCases, | ||
consentState: ConsentState, | ||
name: string; | ||
shouldMemoize?: boolean | undefined; | ||
}): string | null => | ||
{ | ||
console.log('in cmpGetCookie'); | ||
|
||
if(hasConsentForUseCaseWithConsentState(useCase, consentState)) | ||
{ | ||
return getCookie({name: name, shouldMemoize: shouldMemoize}) | ||
} | ||
else | ||
{ | ||
console.error('cmp', `Cannot get cookie ${name} due to missing consent for use-case ${useCase}`) | ||
return(null) | ||
} | ||
}; | ||
|
||
export const cmpSetCookie = async ({ useCase, name, value, daysToLive, isCrossSubdomain, }: { | ||
useCase: ConsentUseCases, | ||
name: string; | ||
value: string; | ||
daysToLive?: number | undefined; | ||
isCrossSubdomain?: boolean | undefined; | ||
}): Promise<void> => | ||
{ | ||
const consentState = await onConsent(); | ||
return(cmpSetCookieWithConsentState({useCase, consentState, name, value, daysToLive, isCrossSubdomain})) | ||
} | ||
|
||
export const cmpSetCookieWithConsentState = ({ useCase, consentState, name, value, daysToLive, isCrossSubdomain, }: { | ||
useCase: ConsentUseCases, | ||
consentState: ConsentState, | ||
name: string; | ||
value: string; | ||
daysToLive?: number | undefined; | ||
isCrossSubdomain?: boolean | undefined; | ||
}): void => | ||
{ | ||
console.log('in cmpSetCookie'); | ||
|
||
if(hasConsentForUseCaseWithConsentState(useCase, consentState)) | ||
{ | ||
setCookie({name:name, value:value, daysToLive:daysToLive, isCrossSubdomain:isCrossSubdomain}) | ||
} | ||
else | ||
{ | ||
console.error('cmp', `Cannot set cookie ${name} due to missing consent for use-case ${useCase}`) | ||
} | ||
}; | ||
|
||
export const cmpSetSessionCookie = async ({ useCase, name, value }: { | ||
useCase: ConsentUseCases, | ||
name: string; | ||
value: string; | ||
}): Promise<void> => | ||
{ | ||
const consentState = await onConsent(); | ||
return(cmpSetSessionCookieWithConsentState({useCase, consentState, name, value})) | ||
}; | ||
|
||
export const cmpSetSessionCookieWithConsentState= async ({ useCase, consentState, name, value }: { | ||
useCase: ConsentUseCases, | ||
consentState: ConsentState, | ||
name: string; | ||
value: string; | ||
}): Promise<void> => | ||
{ | ||
console.log('in cmpSetSessionCookie'); | ||
|
||
if(hasConsentForUseCaseWithConsentState(useCase, consentState)) | ||
{ | ||
setSessionCookie({name:name, value:value}) | ||
} | ||
else | ||
{ | ||
console.error('cmp', `Cannot set cookie ${name} due to missing consent for use-case ${useCase}`) | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
import { onConsentChange } from './onConsentChange'; | ||
import type { Callback, ConsentState } from './types'; | ||
import type { TCFv2ConsentState } from './types/tcfv2'; | ||
import {storage} from './cmpStorage'; | ||
import { storage as storageStub} from '@guardian/libs'; | ||
|
||
//TODO: add tests for all use-cases and all other storage functions | ||
|
||
jest.mock('./onConsentChange'); | ||
jest.mock('@guardian/libs', () => ({ | ||
getCookie: jest.fn(), | ||
setCookie: jest.fn(), | ||
storage: { | ||
local: { | ||
get: jest.fn(), | ||
set: jest.fn(), | ||
}, | ||
session: { | ||
get: jest.fn(), | ||
set: jest.fn(), | ||
}, | ||
} | ||
})); | ||
|
||
const tcfv2ConsentState: TCFv2ConsentState = { | ||
consents: { 1: true }, | ||
eventStatus: 'tcloaded', | ||
vendorConsents: { | ||
['5efefe25b8e05c06542b2a77']: true, | ||
}, | ||
addtlConsent: 'xyz', | ||
gdprApplies: true, | ||
tcString: 'YAAA', | ||
}; | ||
|
||
const tcfv2ConsentStateNoConsent: TCFv2ConsentState = { | ||
consents: { 1: false }, | ||
eventStatus: 'tcloaded', | ||
vendorConsents: {}, | ||
addtlConsent: 'xyz', | ||
gdprApplies: true, | ||
tcString: 'YAAA', | ||
}; | ||
|
||
const mockOnConsentChange = (consentState: ConsentState) => | ||
(onConsentChange as jest.Mock).mockImplementation((cb: Callback) => cb(consentState)); | ||
|
||
describe('local storage returns the expected consent', () => { | ||
let mockContains:any; | ||
|
||
beforeEach(() => { | ||
mockContains = 'someTestData'; | ||
|
||
(storageStub.local.get as jest.Mock).mockImplementation((key:string) => { | ||
if (key === 'gu.mock') {return mockContains} | ||
else {return(null)} | ||
}); | ||
|
||
(storageStub.local.set as jest.Mock).mockImplementation((key:string, data:unknown) => { | ||
if (key === 'gu.mock') {mockContains = data;} | ||
}); | ||
}); | ||
|
||
test('Targeted advertising get local storage returns null when canTarget is false', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentState, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const localStorageValue = await storage.local.get('Targeted advertising', 'gu.mock'); | ||
expect(localStorageValue).toEqual(null); | ||
}); | ||
test('Targeted advertising can set and get local storage value when canTarget is true', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentState, | ||
canTarget: true, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const localStorageValueDefault = await storage.local.get('Targeted advertising', 'gu.mock'); | ||
expect(localStorageValueDefault).toEqual('someTestData'); | ||
await storage.local.set('Essential', 'gu.mock', 'testdataAd'); | ||
const localStorageValue = await storage.local.get('Targeted advertising', 'gu.mock'); | ||
expect(localStorageValue).toEqual('testdataAd'); | ||
}); | ||
test('Essential can set and get local storage when no consents', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentStateNoConsent, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const localStorageValueDefault = await storage.local.get('Essential', 'gu.mock'); | ||
expect(localStorageValueDefault).toEqual('someTestData'); | ||
await storage.local.set('Essential', 'gu.mock', 'testdata'); | ||
const localStorageValue = await storage.local.get('Essential', 'gu.mock'); | ||
expect(localStorageValue).toEqual('testdata'); | ||
}); | ||
test('get null if local storage item does not exist', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentStateNoConsent, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const localStorageValue = await storage.local.get('Essential', 'gu.does_not_exist'); | ||
expect(localStorageValue).toEqual(null); | ||
}); | ||
}); | ||
|
||
|
||
describe('session storage returns the expected consent', () => { | ||
let mockContains:any; | ||
|
||
beforeEach(() => { | ||
mockContains = 'someTestData'; | ||
|
||
(storageStub.session.get as jest.Mock).mockImplementation((key:string) => { | ||
if (key === 'gu.mock') {return mockContains} | ||
else {return(null)} | ||
}); | ||
|
||
(storageStub.session.set as jest.Mock).mockImplementation((key:string, data:unknown) => { | ||
if (key === 'gu.mock') {mockContains = data;} | ||
}); | ||
}); | ||
|
||
test('Targeted advertising get session storage returns null when canTarget is false', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentState, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const sessionStorageValue = await storage.session.get('Targeted advertising', 'gu.mock'); | ||
expect(sessionStorageValue).toEqual(null); | ||
}); | ||
test('Targeted advertising can set and get session storage value when canTarget is true', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentState, | ||
canTarget: true, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const sessionStorageValueDefault = await storage.session.get('Targeted advertising', 'gu.mock'); | ||
expect(sessionStorageValueDefault).toEqual('someTestData'); | ||
await storage.session.set('Essential', 'gu.mock', 'testdataAd'); | ||
const sessionStorageValue = await storage.session.get('Targeted advertising', 'gu.mock'); | ||
expect(sessionStorageValue).toEqual('testdataAd'); | ||
}); | ||
test('Essential can set and get session storage when no consents', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentStateNoConsent, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const sessionStorageValueDefault = await storage.session.get('Essential', 'gu.mock'); | ||
expect(sessionStorageValueDefault).toEqual('someTestData'); | ||
await storage.session.set('Essential', 'gu.mock', 'testdata'); | ||
const sessionStorageValue = await storage.session.get('Essential', 'gu.mock'); | ||
expect(sessionStorageValue).toEqual('testdata'); | ||
}); | ||
test('get null if session storage item does not exist', async () => { | ||
const consentState: ConsentState = { | ||
tcfv2: tcfv2ConsentStateNoConsent, | ||
canTarget: false, | ||
framework: 'tcfv2', | ||
}; | ||
mockOnConsentChange(consentState); | ||
const sessionStorageValue = await storage.session.get('Essential', 'gu.does_not_exist'); | ||
expect(sessionStorageValue).toEqual(null); | ||
}); | ||
}); |
Oops, something went wrong.