Skip to content

Commit

Permalink
Merge 0f8b4bf into aad7433
Browse files Browse the repository at this point in the history
  • Loading branch information
vlkerag authored Jan 22, 2024
2 parents aad7433 + 0f8b4bf commit 3e4f7fb
Show file tree
Hide file tree
Showing 9 changed files with 774 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-radios-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@guardian/consent-management-platform': patch
---

testing consent wrappers
113 changes: 113 additions & 0 deletions src/cmpCookies.tests.ts
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);
});
});
99 changes: 99 additions & 0 deletions src/cmpCookies.ts
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}`)
}
};
175 changes: 175 additions & 0 deletions src/cmpStorage.test.ts
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);
});
});
Loading

0 comments on commit 3e4f7fb

Please sign in to comment.