1 import { addDays, endOfDay } from 'date-fns';
3 import * as cookiesModule from '@proton/shared/lib/helpers/cookies';
5 import { type FeatureFlagToggle } from '../interface';
6 import saveWhitelistedFlagInCookies, { UNLEASH_FLAG_COOKIE_NAME } from './UnleashCookiesProvider';
8 // ------------------------------
10 // ------------------------------
11 jest.mock('@proton/shared/lib/helpers/cookies', () => ({
14 deleteCookie: jest.fn(),
17 // ------------------------------
19 // ------------------------------
20 const getCookieSpys = () => {
22 getCookie: jest.spyOn(cookiesModule, 'getCookie'),
23 setCookie: jest.spyOn(cookiesModule, 'setCookie'),
24 deleteCookie: jest.spyOn(cookiesModule, 'deleteCookie'),
28 // ------------------------------
30 // ------------------------------
31 const generateFlag = (name: string, variantName: string, flagEnabled?: boolean, variantEnabled?: boolean) => {
33 enabled: flagEnabled ?? true,
37 enabled: variantEnabled ?? true,
39 } satisfies FeatureFlagToggle;
42 // ------------------------------
44 // ------------------------------
45 describe('UnleashCookiesProvider', () => {
47 Object.defineProperty(globalThis, 'window', {
48 value: { location: { hostname: 'www.example.com' } },
57 describe('Whitelisted flag with variant', () => {
59 const whitelistedFlags = ['ValidFlag'];
60 const unleashFlagsList = [generateFlag('ValidFlag', 'VariantA'), generateFlag('InvalidFlag', 'VariantB')];
61 saveWhitelistedFlagInCookies(unleashFlagsList, whitelistedFlags);
65 ['cookieName', UNLEASH_FLAG_COOKIE_NAME],
66 ['cookieValue', 'ValidFlag:VariantA'],
69 ['expirationDate', endOfDay(addDays(new Date(), 30)).toUTCString()],
70 ['domain', 'www.example.com'],
71 ])('%s key should be set to %j', (key, value) => {
72 const { setCookie } = getCookieSpys();
73 expect(setCookie).toHaveBeenCalledWith(
74 expect.objectContaining({
81 it('Should not save non whitelisted flag with variant', () => {
82 const { setCookie } = getCookieSpys();
83 const whitelistedFlags = ['ValidFlag'];
84 const unleashFlagsList = [generateFlag('ValidFlag', 'VariantA'), generateFlag('InvalidFlag', 'VariantB')];
86 saveWhitelistedFlagInCookies(unleashFlagsList, whitelistedFlags);
87 expect(setCookie).toHaveBeenCalledWith(
88 expect.objectContaining({
89 cookieValue: 'ValidFlag:VariantA',
94 it('Should not save disabled flags', () => {
95 const { setCookie } = getCookieSpys();
96 const whitelistedFlags = ['ValidFlag'];
97 const unleashFlagsList = [
98 generateFlag('ValidFlag', 'VariantA', false, true),
99 generateFlag('InvalidFlag', 'VariantB'),
102 saveWhitelistedFlagInCookies(unleashFlagsList, whitelistedFlags);
103 expect(setCookie).not.toHaveBeenCalled();
106 it('Should not save enabled flag with disabled variant', () => {
107 const { setCookie } = getCookieSpys();
108 const whitelistedFlags = ['ValidFlag'];
109 const unleashFlagsList = [
110 generateFlag('ValidFlag', 'VariantA', true, false),
111 generateFlag('InvalidFlag', 'VariantB'),
114 saveWhitelistedFlagInCookies(unleashFlagsList, whitelistedFlags);
115 expect(setCookie).not.toHaveBeenCalled();
118 describe('Should not save flag or variant with invalid characters', () => {
120 ['coma in flag name', 'Invalid,Flag', 'VariantA'],
121 ['colon in flag name', 'Invalid:Flag', 'VariantA'],
122 ['space in flag name', 'Invalid Flag', 'VariantA'],
123 ['coma in variantName', 'Flag', 'Invalid,Variant'],
124 ['colon in variantName', 'Flag', 'Invalid:Variant'],
125 ['space in variantName', 'Flag', 'Invalid Variant'],
128 it.each(cases)('%s should not be saved', async (_, flagName, variantName) => {
129 const { setCookie } = getCookieSpys();
130 const whitelistedFlags = [flagName];
131 const unleashFlagsList = [generateFlag(flagName, variantName)];
133 saveWhitelistedFlagInCookies(unleashFlagsList, whitelistedFlags);
134 expect(setCookie).not.toHaveBeenCalled();