From b015f4fdcfd912af690197bc0c025d9a9866b442 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Tue, 25 Mar 2025 15:27:06 +0000 Subject: [PATCH 01/29] Install playwright --- .../__tests__/{ => jest}/analytics/index.js | 4 +- .../__tests__/{ => jest}/banner/index.js | 194 ++++----- .../__tests__/{ => jest}/banner/showBanner.js | 128 +++--- .../__tests__/{ => jest}/consent.js | 2 +- .../__tests__/{ => jest}/cookies.js | 106 ++--- .../__tests__/{ => jest}/form/api.js | 88 ++-- .../__tests__/{ => jest}/form/interactions.js | 126 +++--- .../__tests__/{ => jest}/form/not-render.js | 50 +-- .../__tests__/{ => jest}/form/render.js | 106 ++--- .../{ => jest}/google-eu-consent/index.js | 128 +++--- .../google-eu-consent/no-eu-consent-config.js | 88 ++-- .../__tests__/{ => jest}/reject.js | 94 ++--- .../__tests__/{ => jest}/state.js | 282 ++++++------- .../__tests__/{ => jest}/store.js | 2 +- .../__tests__/{ => jest}/utils.js | 386 +++++++++--------- .../__tests__/playwright/playwright.spec.js | 19 + packages/cookie-banner/example/src/index.html | 126 ++++-- packages/cookie-banner/package.json | 6 +- packages/cookie-banner/playwright.config.js | 16 + .../tools/playwright.webpack.config.js | 8 + .../{example => tools}/webpack.config.js | 0 21 files changed, 1020 insertions(+), 939 deletions(-) rename packages/cookie-banner/__tests__/{ => jest}/analytics/index.js (96%) rename packages/cookie-banner/__tests__/{ => jest}/banner/index.js (95%) rename packages/cookie-banner/__tests__/{ => jest}/banner/showBanner.js (94%) rename packages/cookie-banner/__tests__/{ => jest}/consent.js (96%) rename packages/cookie-banner/__tests__/{ => jest}/cookies.js (93%) rename packages/cookie-banner/__tests__/{ => jest}/form/api.js (92%) rename packages/cookie-banner/__tests__/{ => jest}/form/interactions.js (94%) rename packages/cookie-banner/__tests__/{ => jest}/form/not-render.js (87%) rename packages/cookie-banner/__tests__/{ => jest}/form/render.js (93%) rename packages/cookie-banner/__tests__/{ => jest}/google-eu-consent/index.js (94%) rename packages/cookie-banner/__tests__/{ => jest}/google-eu-consent/no-eu-consent-config.js (92%) rename packages/cookie-banner/__tests__/{ => jest}/reject.js (93%) rename packages/cookie-banner/__tests__/{ => jest}/state.js (95%) rename packages/cookie-banner/__tests__/{ => jest}/store.js (96%) rename packages/cookie-banner/__tests__/{ => jest}/utils.js (95%) create mode 100644 packages/cookie-banner/__tests__/playwright/playwright.spec.js create mode 100644 packages/cookie-banner/playwright.config.js create mode 100644 packages/cookie-banner/tools/playwright.webpack.config.js rename packages/cookie-banner/{example => tools}/webpack.config.js (100%) diff --git a/packages/cookie-banner/__tests__/analytics/index.js b/packages/cookie-banner/__tests__/jest/analytics/index.js similarity index 96% rename from packages/cookie-banner/__tests__/analytics/index.js rename to packages/cookie-banner/__tests__/jest/analytics/index.js index 0ecfbab7..dfc70180 100644 --- a/packages/cookie-banner/__tests__/analytics/index.js +++ b/packages/cookie-banner/__tests__/jest/analytics/index.js @@ -1,5 +1,5 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; let instance; const init = () => { diff --git a/packages/cookie-banner/__tests__/banner/index.js b/packages/cookie-banner/__tests__/jest/banner/index.js similarity index 95% rename from packages/cookie-banner/__tests__/banner/index.js rename to packages/cookie-banner/__tests__/jest/banner/index.js index a173e9ee..e6db006a 100644 --- a/packages/cookie-banner/__tests__/banner/index.js +++ b/packages/cookie-banner/__tests__/jest/banner/index.js @@ -1,97 +1,97 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > DOM > render`, () => { - beforeAll(init); - - it('It should render the banner', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); - }); -}); - -describe(`Cookie banner > DOM > not render`, () => { - - it('It should not render the banner if hideBannerOnFormPage setting is true and on consent form page', async () => { - document.body.innerHTML = `
`; - cookieBanner({ - secure: false, - hideBannerOnFormPage: true, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); - }); -}); - - -describe(`Cookie banner > DOM > accessibility`, () => { - beforeAll(init); - it('The banner should be a region', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('role')).toEqual('region'); - }); - - it('The banner should be a polite aria live region', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-live')).toEqual('polite'); - }); - - it('The banner should have an aria label', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-label')).toBeDefined(); - }); - -}); - -describe(`Cookie banner > DOM > interactions`, () => { - beforeAll(init); - - it('Hides the banner', async () => { - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); - }); - -}); - +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +const init = () => { + // Set up our document body + document.body.innerHTML = `
`; + cookieBanner({ + secure: false, + hideBannerOnFormPage: false, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); +}; + + +describe(`Cookie banner > DOM > render`, () => { + beforeAll(init); + + it('It should render the banner', async () => { + expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); + }); +}); + +describe(`Cookie banner > DOM > not render`, () => { + + it('It should not render the banner if hideBannerOnFormPage setting is true and on consent form page', async () => { + document.body.innerHTML = `
`; + cookieBanner({ + secure: false, + hideBannerOnFormPage: true, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); + expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); + }); +}); + + +describe(`Cookie banner > DOM > accessibility`, () => { + beforeAll(init); + it('The banner should be a region', async () => { + expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('role')).toEqual('region'); + }); + + it('The banner should be a polite aria live region', async () => { + expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-live')).toEqual('polite'); + }); + + it('The banner should have an aria label', async () => { + expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-label')).toBeDefined(); + }); + +}); + +describe(`Cookie banner > DOM > interactions`, () => { + beforeAll(init); + + it('Hides the banner', async () => { + document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); + expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); + }); + +}); + diff --git a/packages/cookie-banner/__tests__/banner/showBanner.js b/packages/cookie-banner/__tests__/jest/banner/showBanner.js similarity index 94% rename from packages/cookie-banner/__tests__/banner/showBanner.js rename to packages/cookie-banner/__tests__/jest/banner/showBanner.js index 58a81acb..be8d6301 100644 --- a/packages/cookie-banner/__tests__/banner/showBanner.js +++ b/packages/cookie-banner/__tests__/jest/banner/showBanner.js @@ -1,65 +1,65 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -let instance; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - instance = cookieBanner({ - secure: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - -describe(`Cookie banner > showBanner > show banner`, () => { - beforeAll(init); - - it('It should not show the banner if is already showing', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); - expect(instance.getState().bannerOpen).toBe(true); - instance.showBanner(); - expect(document.querySelectorAll(`.${defaults.classNames.banner}`).length).toBe(1); - }); - - it('It should show the banner and invoke the callback function', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); - expect(instance.getState().bannerOpen).toBe(true); - //hide it - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(instance.getState().bannerOpen).toBe(false); - expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); - - //show it - const cb = jest.fn(); - instance.showBanner(cb); - expect(instance.getState().bannerOpen).toBe(true); - expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); - const nextState = instance.getState(); - expect(cb).toHaveBeenCalledWith(nextState); - }); - +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +let instance; + +const init = () => { + // Set up our document body + document.body.innerHTML = `
`; + instance = cookieBanner({ + secure: false, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); +}; + +describe(`Cookie banner > showBanner > show banner`, () => { + beforeAll(init); + + it('It should not show the banner if is already showing', async () => { + expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); + expect(instance.getState().bannerOpen).toBe(true); + instance.showBanner(); + expect(document.querySelectorAll(`.${defaults.classNames.banner}`).length).toBe(1); + }); + + it('It should show the banner and invoke the callback function', async () => { + expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); + expect(instance.getState().bannerOpen).toBe(true); + //hide it + document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); + expect(instance.getState().bannerOpen).toBe(false); + expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); + + //show it + const cb = jest.fn(); + instance.showBanner(cb); + expect(instance.getState().bannerOpen).toBe(true); + expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); + const nextState = instance.getState(); + expect(cb).toHaveBeenCalledWith(nextState); + }); + }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/consent.js b/packages/cookie-banner/__tests__/jest/consent.js similarity index 96% rename from packages/cookie-banner/__tests__/consent.js rename to packages/cookie-banner/__tests__/jest/consent.js index 4d971c43..764cada6 100644 --- a/packages/cookie-banner/__tests__/consent.js +++ b/packages/cookie-banner/__tests__/jest/consent.js @@ -1,4 +1,4 @@ -import { applyEffects } from '../src/lib/consent'; +import { applyEffects } from '../../src/lib/consent'; describe(`Cookie banner > consent > callback`, () => { document.body.innerHTML = `

`; diff --git a/packages/cookie-banner/__tests__/cookies.js b/packages/cookie-banner/__tests__/jest/cookies.js similarity index 93% rename from packages/cookie-banner/__tests__/cookies.js rename to packages/cookie-banner/__tests__/jest/cookies.js index 09e30f0d..de511637 100644 --- a/packages/cookie-banner/__tests__/cookies.js +++ b/packages/cookie-banner/__tests__/jest/cookies.js @@ -1,53 +1,53 @@ -import cookieBanner from '../src'; -import defaults from '../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > cookies > update`, () => { - beforeAll(init); - - it('Sets a cookie based on preferences form', async () => { - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); - - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - fields[1].checked = true; - fields[3].checked = true; - document.querySelector(`.${defaults.classNames.submitBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); - }); - -}); - +import cookieBanner from '../../src'; +import defaults from '../../src/lib/defaults'; + +const init = () => { + // Set up our document body + document.body.innerHTML = `
`; + window.__cb__ = cookieBanner({ + secure: false, + hideBannerOnFormPage: false, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); +}; + + +describe(`Cookie banner > cookies > update`, () => { + beforeAll(init); + + it('Sets a cookie based on preferences form', async () => { + document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); + expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); + + const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); + fields[1].checked = true; + fields[3].checked = true; + document.querySelector(`.${defaults.classNames.submitBtn}`).click(); + expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); + }); + +}); + diff --git a/packages/cookie-banner/__tests__/form/api.js b/packages/cookie-banner/__tests__/jest/form/api.js similarity index 92% rename from packages/cookie-banner/__tests__/form/api.js rename to packages/cookie-banner/__tests__/jest/form/api.js index e9a86f95..8b331ee5 100644 --- a/packages/cookie-banner/__tests__/form/api.js +++ b/packages/cookie-banner/__tests__/jest/form/api.js @@ -1,45 +1,45 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -describe(`Cookie banner > DOM > form > render by api`, () => { - - it('Should render the form via the API', async () => { - document.body.innerHTML = `
`; - const instance = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - suggested: true, - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Test yes label', - no: 'Test no label' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - expect(document.querySelector(`.${defaults.classNames.form}`)).toBeNull(); - - document.querySelector('main').innerHTML = `
`; - instance.renderForm(); - expect(document.querySelector(`.${defaults.classNames.form}`)).not.toBeNull(); - - }); - +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +describe(`Cookie banner > DOM > form > render by api`, () => { + + it('Should render the form via the API', async () => { + document.body.innerHTML = `
`; + const instance = cookieBanner({ + secure: false, + hideBannerOnFormPage: false, + types: { + test: { + suggested: true, + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Test yes label', + no: 'Test no label' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); + expect(document.querySelector(`.${defaults.classNames.form}`)).toBeNull(); + + document.querySelector('main').innerHTML = `
`; + instance.renderForm(); + expect(document.querySelector(`.${defaults.classNames.form}`)).not.toBeNull(); + + }); + }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/form/interactions.js b/packages/cookie-banner/__tests__/jest/form/interactions.js similarity index 94% rename from packages/cookie-banner/__tests__/form/interactions.js rename to packages/cookie-banner/__tests__/jest/form/interactions.js index 3db92465..63ea8109 100644 --- a/packages/cookie-banner/__tests__/form/interactions.js +++ b/packages/cookie-banner/__tests__/jest/form/interactions.js @@ -1,64 +1,64 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -const dispatchSyntheticEvent = (node, eventType) => { - let event = document.createEvent('Event'); - event.initEvent(eventType, true, true); - node.dispatchEvent(event); -}; - -describe(`Cookie banner > DOM > form interactions`, () => { - beforeAll(() => { - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Test yes label', - no: 'Test no label' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - }); - - it('Submit button should be disabled', async () => { - expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); - }); - - it('Submit button should be enabled if both field groups have values', async () => { - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - - fields[0].checked = true; - dispatchSyntheticEvent(fields[0], 'change');//for JSDOM - expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); - - fields[2].checked = true; - dispatchSyntheticEvent(fields[2], 'change');//for JSDOM - expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).toEqual(null); - }); - - it('Submit button should set the cookie and hide the banner', async () => { - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); - expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); - }); +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +const dispatchSyntheticEvent = (node, eventType) => { + let event = document.createEvent('Event'); + event.initEvent(eventType, true, true); + node.dispatchEvent(event); +}; + +describe(`Cookie banner > DOM > form interactions`, () => { + beforeAll(() => { + document.body.innerHTML = `
`; + window.__cb__ = cookieBanner({ + secure: false, + hideBannerOnFormPage: false, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Test yes label', + no: 'Test no label' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); + }); + + it('Submit button should be disabled', async () => { + expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); + }); + + it('Submit button should be enabled if both field groups have values', async () => { + const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); + + fields[0].checked = true; + dispatchSyntheticEvent(fields[0], 'change');//for JSDOM + expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); + + fields[2].checked = true; + dispatchSyntheticEvent(fields[2], 'change');//for JSDOM + expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).toEqual(null); + }); + + it('Submit button should set the cookie and hide the banner', async () => { + document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); + expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); + expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); + }); }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/form/not-render.js b/packages/cookie-banner/__tests__/jest/form/not-render.js similarity index 87% rename from packages/cookie-banner/__tests__/form/not-render.js rename to packages/cookie-banner/__tests__/jest/form/not-render.js index 2bd8532a..7cb4225f 100644 --- a/packages/cookie-banner/__tests__/form/not-render.js +++ b/packages/cookie-banner/__tests__/jest/form/not-render.js @@ -1,26 +1,26 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -describe(`Cookie banner > DOM > form > not render`, () => { - document.body.innerHTML = `
`; - cookieBanner({ - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - - it('Should return if there is no form container', async () => { - expect(document.querySelector(`.${defaults.classNames.form}`)).toBeNull(); - }); - +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +describe(`Cookie banner > DOM > form > not render`, () => { + document.body.innerHTML = `
`; + cookieBanner({ + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); + + it('Should return if there is no form container', async () => { + expect(document.querySelector(`.${defaults.classNames.form}`)).toBeNull(); + }); + }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/form/render.js b/packages/cookie-banner/__tests__/jest/form/render.js similarity index 93% rename from packages/cookie-banner/__tests__/form/render.js rename to packages/cookie-banner/__tests__/jest/form/render.js index 2d32f727..d29d0a65 100644 --- a/packages/cookie-banner/__tests__/form/render.js +++ b/packages/cookie-banner/__tests__/jest/form/render.js @@ -1,54 +1,54 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -describe(`Cookie banner > DOM > form > render`, () => { - beforeAll(() => { - document.body.innerHTML = `
`; - cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - suggested: true, - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Test yes label', - no: 'Test no label' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - }); - - it('Should render the form', async () => { - expect(document.querySelector(`.${defaults.classNames.form}`)).not.toBeNull(); - }); - - it('Should render a fieldset for each type', async () => { - const fieldset = Array.from(document.querySelectorAll(`.${defaults.classNames.fieldset}`)); - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - expect(fieldset.length).toEqual(2); - expect(fields.length).toEqual(4); - }); - - it('Should set the default values if any are set and no there is no user consent preferences', async () => { - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - expect(fields[0].checked).toEqual(true); - }); - +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +describe(`Cookie banner > DOM > form > render`, () => { + beforeAll(() => { + document.body.innerHTML = `
`; + cookieBanner({ + secure: false, + hideBannerOnFormPage: false, + types: { + test: { + suggested: true, + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Test yes label', + no: 'Test no label' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); + }); + + it('Should render the form', async () => { + expect(document.querySelector(`.${defaults.classNames.form}`)).not.toBeNull(); + }); + + it('Should render a fieldset for each type', async () => { + const fieldset = Array.from(document.querySelectorAll(`.${defaults.classNames.fieldset}`)); + const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); + expect(fieldset.length).toEqual(2); + expect(fields.length).toEqual(4); + }); + + it('Should set the default values if any are set and no there is no user consent preferences', async () => { + const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); + expect(fields[0].checked).toEqual(true); + }); + }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/google-eu-consent/index.js b/packages/cookie-banner/__tests__/jest/google-eu-consent/index.js similarity index 94% rename from packages/cookie-banner/__tests__/google-eu-consent/index.js rename to packages/cookie-banner/__tests__/jest/google-eu-consent/index.js index ff9fb727..50ce12fb 100644 --- a/packages/cookie-banner/__tests__/google-eu-consent/index.js +++ b/packages/cookie-banner/__tests__/jest/google-eu-consent/index.js @@ -1,65 +1,65 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -/* eslint-disable camelcase */ -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - euConsentTypes: { - ad_storage: 'test', - ad_user_data: 'test', - ad_personalization: 'test', - analytics_storage: 'performance' - }, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > cookies > Google EU consent > default event`, () => { - beforeAll(init); - - it('must set a default consent event with all categories denied', async () => { - const banner = document.querySelector(`.${defaults.classNames.banner}`); - expect(banner).not.toBeNull(); - - //These assertions break Jest because of the use 'arguments' in the gtag implementation - //They have been manually validated in the browser - // expect(window.dataLayer).toEqual([ - // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }] - // ]); - // const acceptAllBtn = document.querySelector(`.${defaults.classNames.acceptBtn}`); - // acceptAllBtn.click(); - - // expect(window.dataLayer).toEqual([ - // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }], - // ['consent', 'update', { ad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted', analytics_storage: 'granted' }] - // ]); - }); - +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +/* eslint-disable camelcase */ +const init = () => { + // Set up our document body + document.body.innerHTML = `
`; + window.__cb__ = cookieBanner({ + secure: false, + euConsentTypes: { + ad_storage: 'test', + ad_user_data: 'test', + ad_personalization: 'test', + analytics_storage: 'performance' + }, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); +}; + + +describe(`Cookie banner > cookies > Google EU consent > default event`, () => { + beforeAll(init); + + it('must set a default consent event with all categories denied', async () => { + const banner = document.querySelector(`.${defaults.classNames.banner}`); + expect(banner).not.toBeNull(); + + //These assertions break Jest because of the use 'arguments' in the gtag implementation + //They have been manually validated in the browser + // expect(window.dataLayer).toEqual([ + // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }] + // ]); + // const acceptAllBtn = document.querySelector(`.${defaults.classNames.acceptBtn}`); + // acceptAllBtn.click(); + + // expect(window.dataLayer).toEqual([ + // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }], + // ['consent', 'update', { ad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted', analytics_storage: 'granted' }] + // ]); + }); + }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/google-eu-consent/no-eu-consent-config.js b/packages/cookie-banner/__tests__/jest/google-eu-consent/no-eu-consent-config.js similarity index 92% rename from packages/cookie-banner/__tests__/google-eu-consent/no-eu-consent-config.js rename to packages/cookie-banner/__tests__/jest/google-eu-consent/no-eu-consent-config.js index 8a94d495..abb4a86d 100644 --- a/packages/cookie-banner/__tests__/google-eu-consent/no-eu-consent-config.js +++ b/packages/cookie-banner/__tests__/jest/google-eu-consent/no-eu-consent-config.js @@ -1,45 +1,45 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > cookies > Google EU consent > no EU consent settings`, () => { - beforeAll(init); - - it('No errors if no consent options configured', async () => { - const banner = document.querySelector(`.${defaults.classNames.banner}`); - expect(banner).not.toBeNull(); - }); - +import cookieBanner from '../../../src'; +import defaults from '../../../src/lib/defaults'; + +const init = () => { + // Set up our document body + document.body.innerHTML = `
`; + window.__cb__ = cookieBanner({ + secure: false, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); +}; + + +describe(`Cookie banner > cookies > Google EU consent > no EU consent settings`, () => { + beforeAll(init); + + it('No errors if no consent options configured', async () => { + const banner = document.querySelector(`.${defaults.classNames.banner}`); + expect(banner).not.toBeNull(); + }); + }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/reject.js b/packages/cookie-banner/__tests__/jest/reject.js similarity index 93% rename from packages/cookie-banner/__tests__/reject.js rename to packages/cookie-banner/__tests__/jest/reject.js index 67d1e208..5f98663f 100644 --- a/packages/cookie-banner/__tests__/reject.js +++ b/packages/cookie-banner/__tests__/jest/reject.js @@ -1,47 +1,47 @@ -import cookieBanner from '../src'; -import defaults from '../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > reject`, () => { - beforeAll(init); - - it('Should reject all cookies whe the reject button is clicked', async () => { - document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); - }); - -}); - +import cookieBanner from '../../src'; +import defaults from '../../src/lib/defaults'; + +const init = () => { + // Set up our document body + document.body.innerHTML = `
`; + window.__cb__ = cookieBanner({ + secure: false, + hideBannerOnFormPage: false, + types: { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + }, + performance: { + title: 'Performance preferences', + description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + } + }); +}; + + +describe(`Cookie banner > reject`, () => { + beforeAll(init); + + it('Should reject all cookies whe the reject button is clicked', async () => { + document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); + expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); + }); + +}); + diff --git a/packages/cookie-banner/__tests__/state.js b/packages/cookie-banner/__tests__/jest/state.js similarity index 95% rename from packages/cookie-banner/__tests__/state.js rename to packages/cookie-banner/__tests__/jest/state.js index c79d8689..1d12fa32 100644 --- a/packages/cookie-banner/__tests__/state.js +++ b/packages/cookie-banner/__tests__/jest/state.js @@ -1,142 +1,142 @@ -import cookieBanner from '../src'; -import { updateConsent, updateExecuted } from '../src/lib/reducers'; - -const init = () => { - // Set up container for form - document.body.innerHTML = `
`; - -}; - -describe(`Cookie banner > state > update/reducers`, () => { - beforeAll(init); - - it('initialState should set the initial state based on options', async () => { - const types = { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - }; - const Store = cookieBanner({ types }); - - expect(Store.getState().settings.types).toEqual(types); - }); - - - it('updateConsent reducer should set consent based on data', async () => { - const types = { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - test2: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - }; - const state = { settings: { types } }; - const data = { test: 1, test2: 0 }; - expect(updateConsent(state, data)).toEqual({ - consent: { - test: 1, test2: 0 - }, - settings: { - types - } - }); - }); - - it('updateExecuted reducer should set executed property based on data', async () => { - const types = { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [] - }, - test2: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [] - } - }; - const state = { settings: { types }, consent: { test: 1, test2: 0 } }; - const data = { - test: { - executed: true, - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [] - }, - test2: { - executed: true, - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [] - } - }; - expect(updateExecuted(state, data)).toEqual({ - consent: { test: 1, test2: 0 }, - settings: { - types: { - test: { - executed: true, - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [] - }, - test2: { - executed: true, - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [] - } - } - } - }); - }); +import cookieBanner from '../../src'; +import { updateConsent, updateExecuted } from '../../src/lib/reducers'; + +const init = () => { + // Set up container for form + document.body.innerHTML = `
`; + +}; + +describe(`Cookie banner > state > update/reducers`, () => { + beforeAll(init); + + it('initialState should set the initial state based on options', async () => { + const types = { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + }; + const Store = cookieBanner({ types }); + + expect(Store.getState().settings.types).toEqual(types); + }); + + + it('updateConsent reducer should set consent based on data', async () => { + const types = { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + }, + test2: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [ + () => { } + ] + } + }; + const state = { settings: { types } }; + const data = { test: 1, test2: 0 }; + expect(updateConsent(state, data)).toEqual({ + consent: { + test: 1, test2: 0 + }, + settings: { + types + } + }); + }); + + it('updateExecuted reducer should set executed property based on data', async () => { + const types = { + test: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [] + }, + test2: { + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [] + } + }; + const state = { settings: { types }, consent: { test: 1, test2: 0 } }; + const data = { + test: { + executed: true, + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [] + }, + test2: { + executed: true, + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [] + } + }; + expect(updateExecuted(state, data)).toEqual({ + consent: { test: 1, test2: 0 }, + settings: { + types: { + test: { + executed: true, + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [] + }, + test2: { + executed: true, + title: 'Test title', + description: 'Test description', + labels: { + yes: 'Pages you visit and actions you take will be measured and used to improve the service', + no: 'Pages you visit and actions you take will not be measured and used to improve the service' + }, + fns: [] + } + } + } + }); + }); }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/store.js b/packages/cookie-banner/__tests__/jest/store.js similarity index 96% rename from packages/cookie-banner/__tests__/store.js rename to packages/cookie-banner/__tests__/jest/store.js index f173f7aa..c0729a61 100644 --- a/packages/cookie-banner/__tests__/store.js +++ b/packages/cookie-banner/__tests__/jest/store.js @@ -1,4 +1,4 @@ -import { createStore } from '../src/lib/store'; +import { createStore } from '../../src/lib/store'; describe(`Cookie banner > Store`, () => { diff --git a/packages/cookie-banner/__tests__/utils.js b/packages/cookie-banner/__tests__/jest/utils.js similarity index 95% rename from packages/cookie-banner/__tests__/utils.js rename to packages/cookie-banner/__tests__/jest/utils.js index 56029478..67187493 100644 --- a/packages/cookie-banner/__tests__/utils.js +++ b/packages/cookie-banner/__tests__/jest/utils.js @@ -1,194 +1,194 @@ -import { groupValueReducer, removeSubdomain, extractFromCookie, broadcast, renderIframe, gtmSnippet } from '../src/lib/utils'; -import defaults from '../src/lib/defaults'; -import { EVENTS } from '../src/lib/constants'; -import { createStore } from '../src/lib/store'; - -describe('Cookie > Utils > removeSubdomain', () => { - it('should return the same vaule for a root domain', async () => { - expect(removeSubdomain('stormid.com')).toEqual('stormid.com'); - }); - - it('should remove www from a url', async () => { - expect(removeSubdomain('www.stormid.com')).toEqual('stormid.com'); - }); - - it('should remove sub sub domains from a domain', async () => { - expect(removeSubdomain('test.demo.stormid.com')).toEqual('stormid.com'); - }); - - it('should remove subsub sub domains from a domain', async () => { - expect(removeSubdomain('cookie.test.demo.stormid.com')).toEqual('stormid.com'); - }); - - it('should handle URLs with multi dot tdls', async () => { - expect(removeSubdomain('cookie.test.demo.stormid.co.uk')).toEqual('stormid.co.uk'); - }); - - it('should handle azurewebsites.net as a multi dot tdl', async () => { - expect(removeSubdomain('cookie-test-wip.azurewebsites.net')).toEqual('cookie-test-wip.azurewebsites.net'); - }); - - it('should handle netlify.app as a multi dot tdl', async () => { - expect(removeSubdomain('cookie-test-wip.netlify.app')).toEqual('cookie-test-wip.netlify.app'); - }); - -}); - -describe('Cookie > Utils > groupValueReducer', () => { - it('should return the String value given an input with a value', async () => { - expect.assertions(1); - document.body.innerHTML = `
- -
`; - const field = document.querySelector('#field'); - expect(groupValueReducer('', field)).toEqual('Test value'); - }); - it('should return an empty String given an input without a value and an initial empty string', async () => { - expect.assertions(1); - document.body.innerHTML = `
- -
`; - const field = document.querySelector('#field'); - expect(groupValueReducer('', field)).toEqual(''); - }); - it('should return an Array containing a String value given a checkable input with a value', async () => { - expect.assertions(1); - document.body.innerHTML = `
- -
`; - const field = document.querySelector('#field'); - expect(groupValueReducer('', field)).toEqual(['Test value']); - }); - it('should return an Array containing a String value given a checkable input with a value and an initial Array', async () => { - expect.assertions(1); - document.body.innerHTML = `
- -
`; - const field = document.querySelector('#field'); - expect(groupValueReducer([], field)).toEqual(['Test value']); - }); - it('should return an empty String given a checkable input that is not checked and an initial empty string', async () => { - expect.assertions(1); - document.body.innerHTML = `
- -
`; - const field = document.querySelector('#field'); - expect(groupValueReducer('', field)).toEqual(''); - }); -}); - - -describe('Cookie > Utils > extractFromCookie > no cookie', () => { - - it('should return default hasCookie and content properties if no cookie', () => { - const [hasCookie, consent ] = extractFromCookie(defaults); - expect(hasCookie).toEqual(false); - expect(consent).toEqual({}); - }); - -}); - - -describe('Cookie > Utils > extractFromCookie > malformed JSON cookie', () => { - - it('should return default hasCookie and content properties if cookie is not JSON and throws when decoding', () => { - document.cookie = `${defaults.name}=${btoa(test)}`; - const [hasCookie, consent ] = extractFromCookie(defaults); - expect(hasCookie).toEqual(false); - expect(consent).toEqual({}); - }); - -}); - -describe('Cookie > Utils > extractFromCookie > category mismatch', () => { - it('should return default hasCookie and content properties if categroies do not match', () => { - document.cookie = `${defaults.name}=${btoa(JSON.stringify({ consent: { performance: 1, thirdParty: 0 } }))}`; - const [hasCookie, consent ] = extractFromCookie({ ...defaults, types: { performance: {}, thirdParty: {}, ads: {} } }); - - expect(hasCookie).toEqual(false); - expect(consent).toEqual({ }); - }); -}); - -describe('Cookie > Utils > extractFromCookie > well-formed JSON cookie', () => { - it('should return hasCookie and content properties from well-formed JSON cookie', () => { - document.cookie = `${defaults.name}=${btoa(JSON.stringify({ consent: { performance: 1, thirdParty: 0 } }))}`; - const [hasCookie, consent ] = extractFromCookie({ ...defaults, types: { performance: {}, thirdParty: {} } }); - - expect(hasCookie).toEqual(true); - expect(consent).toEqual({ performance: 1, thirdParty: 0 }); - }); -}); - -describe('Cookie > Utils > extractFromCookie > cookie not base64 encoded', () => { - - it('should return default hasCookie, and content properties if cookie is not base64 encoded and throws when decoding', () => { - window.atob = jest.fn(); - window.atob.mockImplementation(() => { - throw new Error(); - }); - document.cookie = `${defaults.name}="test"`; - const [hasCookie, consent ] = extractFromCookie(defaults); - expect(window.atob).toHaveBeenCalled(); - expect(hasCookie).toEqual(false); - expect(consent).toEqual({}); - }); - -}); - -describe(`Cookie banner > Utils > broadcast`, () => { - - it('should dispatch a custom event with a detail Object with a reference to Store.getState', async () => { - const Store = createStore(); - const state = { - consent: {}, - bannerOpen: true, - settings: defaults - }; - Store.update(state); - const listener = jest.fn(); - document.addEventListener(EVENTS.SHOW, listener); - document.addEventListener(EVENTS.SHOW, e => { - expect(e.detail).toEqual({ getState: Store.getState }); - }); - - broadcast(EVENTS.SHOW, Store)(state); - expect(listener).toHaveBeenCalled(); - }); - -}); - -describe(`Cookie banner > Utils > renderIframe`, () => { - - it('should render an iframe to an element based on data attributes', async () => { - const SRC = 'https://www.youtube.com/embed/qpLKTUQev30'; - const TITLE = 'Test video'; - const HEIGHT = `500px`; - const WIDTH = `500px`; - document.body.innerHTML = `
`; - renderIframe(); - const iframe = document.querySelector('iframe'); - expect(iframe.getAttribute('src')).toEqual(SRC); - expect(iframe.getAttribute('title')).toEqual(TITLE); - expect(iframe.style.height).toEqual(HEIGHT); - expect(iframe.style.width).toEqual(WIDTH); - }); - -}); - -describe(`Cookie banner > Utils > gtmSnippet`, () => { - - it('should render a Google Tag Manager script tag', async () => { - document.body.innerHTML = ``; //gtm snippet needs a script already on the page to insertBefore - gtmSnippet('ua-1234-5678'); - const gtmScript = document.querySelector('script'); - expect(gtmScript).toBeDefined(); - expect(gtmScript.src).toEqual('https://www.googletagmanager.com/gtm.js?id=ua-1234-5678'); - }); - +import { groupValueReducer, removeSubdomain, extractFromCookie, broadcast, renderIframe, gtmSnippet } from '../../src/lib/utils'; +import defaults from '../../src/lib/defaults'; +import { EVENTS } from '../../src/lib/constants'; +import { createStore } from '../../src/lib/store'; + +describe('Cookie > Utils > removeSubdomain', () => { + it('should return the same vaule for a root domain', async () => { + expect(removeSubdomain('stormid.com')).toEqual('stormid.com'); + }); + + it('should remove www from a url', async () => { + expect(removeSubdomain('www.stormid.com')).toEqual('stormid.com'); + }); + + it('should remove sub sub domains from a domain', async () => { + expect(removeSubdomain('test.demo.stormid.com')).toEqual('stormid.com'); + }); + + it('should remove subsub sub domains from a domain', async () => { + expect(removeSubdomain('cookie.test.demo.stormid.com')).toEqual('stormid.com'); + }); + + it('should handle URLs with multi dot tdls', async () => { + expect(removeSubdomain('cookie.test.demo.stormid.co.uk')).toEqual('stormid.co.uk'); + }); + + it('should handle azurewebsites.net as a multi dot tdl', async () => { + expect(removeSubdomain('cookie-test-wip.azurewebsites.net')).toEqual('cookie-test-wip.azurewebsites.net'); + }); + + it('should handle netlify.app as a multi dot tdl', async () => { + expect(removeSubdomain('cookie-test-wip.netlify.app')).toEqual('cookie-test-wip.netlify.app'); + }); + +}); + +describe('Cookie > Utils > groupValueReducer', () => { + it('should return the String value given an input with a value', async () => { + expect.assertions(1); + document.body.innerHTML = `
+ +
`; + const field = document.querySelector('#field'); + expect(groupValueReducer('', field)).toEqual('Test value'); + }); + it('should return an empty String given an input without a value and an initial empty string', async () => { + expect.assertions(1); + document.body.innerHTML = `
+ +
`; + const field = document.querySelector('#field'); + expect(groupValueReducer('', field)).toEqual(''); + }); + it('should return an Array containing a String value given a checkable input with a value', async () => { + expect.assertions(1); + document.body.innerHTML = `
+ +
`; + const field = document.querySelector('#field'); + expect(groupValueReducer('', field)).toEqual(['Test value']); + }); + it('should return an Array containing a String value given a checkable input with a value and an initial Array', async () => { + expect.assertions(1); + document.body.innerHTML = `
+ +
`; + const field = document.querySelector('#field'); + expect(groupValueReducer([], field)).toEqual(['Test value']); + }); + it('should return an empty String given a checkable input that is not checked and an initial empty string', async () => { + expect.assertions(1); + document.body.innerHTML = `
+ +
`; + const field = document.querySelector('#field'); + expect(groupValueReducer('', field)).toEqual(''); + }); +}); + + +describe('Cookie > Utils > extractFromCookie > no cookie', () => { + + it('should return default hasCookie and content properties if no cookie', () => { + const [hasCookie, consent ] = extractFromCookie(defaults); + expect(hasCookie).toEqual(false); + expect(consent).toEqual({}); + }); + +}); + + +describe('Cookie > Utils > extractFromCookie > malformed JSON cookie', () => { + + it('should return default hasCookie and content properties if cookie is not JSON and throws when decoding', () => { + document.cookie = `${defaults.name}=${btoa(test)}`; + const [hasCookie, consent ] = extractFromCookie(defaults); + expect(hasCookie).toEqual(false); + expect(consent).toEqual({}); + }); + +}); + +describe('Cookie > Utils > extractFromCookie > category mismatch', () => { + it('should return default hasCookie and content properties if categroies do not match', () => { + document.cookie = `${defaults.name}=${btoa(JSON.stringify({ consent: { performance: 1, thirdParty: 0 } }))}`; + const [hasCookie, consent ] = extractFromCookie({ ...defaults, types: { performance: {}, thirdParty: {}, ads: {} } }); + + expect(hasCookie).toEqual(false); + expect(consent).toEqual({ }); + }); +}); + +describe('Cookie > Utils > extractFromCookie > well-formed JSON cookie', () => { + it('should return hasCookie and content properties from well-formed JSON cookie', () => { + document.cookie = `${defaults.name}=${btoa(JSON.stringify({ consent: { performance: 1, thirdParty: 0 } }))}`; + const [hasCookie, consent ] = extractFromCookie({ ...defaults, types: { performance: {}, thirdParty: {} } }); + + expect(hasCookie).toEqual(true); + expect(consent).toEqual({ performance: 1, thirdParty: 0 }); + }); +}); + +describe('Cookie > Utils > extractFromCookie > cookie not base64 encoded', () => { + + it('should return default hasCookie, and content properties if cookie is not base64 encoded and throws when decoding', () => { + window.atob = jest.fn(); + window.atob.mockImplementation(() => { + throw new Error(); + }); + document.cookie = `${defaults.name}="test"`; + const [hasCookie, consent ] = extractFromCookie(defaults); + expect(window.atob).toHaveBeenCalled(); + expect(hasCookie).toEqual(false); + expect(consent).toEqual({}); + }); + +}); + +describe(`Cookie banner > Utils > broadcast`, () => { + + it('should dispatch a custom event with a detail Object with a reference to Store.getState', async () => { + const Store = createStore(); + const state = { + consent: {}, + bannerOpen: true, + settings: defaults + }; + Store.update(state); + const listener = jest.fn(); + document.addEventListener(EVENTS.SHOW, listener); + document.addEventListener(EVENTS.SHOW, e => { + expect(e.detail).toEqual({ getState: Store.getState }); + }); + + broadcast(EVENTS.SHOW, Store)(state); + expect(listener).toHaveBeenCalled(); + }); + +}); + +describe(`Cookie banner > Utils > renderIframe`, () => { + + it('should render an iframe to an element based on data attributes', async () => { + const SRC = 'https://www.youtube.com/embed/qpLKTUQev30'; + const TITLE = 'Test video'; + const HEIGHT = `500px`; + const WIDTH = `500px`; + document.body.innerHTML = `
`; + renderIframe(); + const iframe = document.querySelector('iframe'); + expect(iframe.getAttribute('src')).toEqual(SRC); + expect(iframe.getAttribute('title')).toEqual(TITLE); + expect(iframe.style.height).toEqual(HEIGHT); + expect(iframe.style.width).toEqual(WIDTH); + }); + +}); + +describe(`Cookie banner > Utils > gtmSnippet`, () => { + + it('should render a Google Tag Manager script tag', async () => { + document.body.innerHTML = ``; //gtm snippet needs a script already on the page to insertBefore + gtmSnippet('ua-1234-5678'); + const gtmScript = document.querySelector('script'); + expect(gtmScript).toBeDefined(); + expect(gtmScript.src).toEqual('https://www.googletagmanager.com/gtm.js?id=ua-1234-5678'); + }); + }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/playwright/playwright.spec.js b/packages/cookie-banner/__tests__/playwright/playwright.spec.js new file mode 100644 index 00000000..929a6695 --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/playwright.spec.js @@ -0,0 +1,19 @@ +const { test, expect } = require('@playwright/test'); +import AxeBuilder from '@axe-core/playwright'; + +let tabKey; + +test.beforeEach(async ({ page }, testInfo) => { + await page.goto('/'); + tabKey = testInfo.project.use.defaultBrowserType === 'webkit' + ? "Alt+Tab" + : "Tab"; +}); + +test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { + test('Should not have any automatically detectable accessibility issues', async ({ page }) => { + const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); + expect(accessibilityScanResults.violations).toEqual([]); + }); +}); + diff --git a/packages/cookie-banner/example/src/index.html b/packages/cookie-banner/example/src/index.html index 32be4d83..3b6e6a81 100644 --- a/packages/cookie-banner/example/src/index.html +++ b/packages/cookie-banner/example/src/index.html @@ -1,60 +1,72 @@ - - + + StormID + - - -
-
-
-

Update your cookie preferences to view this content.

- -
+ + + +
+
+
+

Update your cookie preferences to view this content.

+
-
-

Cookies

-

Cookies are a common feature used on almost all websites. A cookie is a small text file that is downloaded onto a device to allow a website to recognise it and to store some information about your preferences.

-

We use cookies for different reasons, including for managing your shopping cart, measuring your visits on our sites, recognising and remembering your preferences and showing you personalised ads. Learn more about cookies and how we use them.

-
-
- - +
+

Cookies

+

Cookies are a common feature used on almost all websites. A cookie is a small text file that is downloaded + onto a device to allow a website to recognise it and to store some information about your preferences.

+

We use cookies for different reasons, including for managing your shopping cart, measuring your visits on our + sites, recognising and remembering your preferences and showing you personalised ads. Learn more about + cookies and how we use them.

+
+ +
+ + + \ No newline at end of file diff --git a/packages/cookie-banner/package.json b/packages/cookie-banner/package.json index 3ca90e2c..0f1121d1 100644 --- a/packages/cookie-banner/package.json +++ b/packages/cookie-banner/package.json @@ -23,9 +23,9 @@ ], "scripts": { "build": "microbundle --name CookieBanner", - "test": "jest --coverage", - "dev": "webpack-dev-server --config example/webpack.config.js", - "prod": "webpack --config example/webpack.config.js --mode production", + "test": "jest --coverage & npx playwright test", + "dev": "webpack-dev-server --config tools/webpack.config.js", + "prod": "webpack --config tools/webpack.config.js --mode production", "prepublish": "npm run -s build" }, "gitHead": "042ec0cbf12848b50c5962a5c8ab139cfb04df39" diff --git a/packages/cookie-banner/playwright.config.js b/packages/cookie-banner/playwright.config.js new file mode 100644 index 00000000..b9c22fb4 --- /dev/null +++ b/packages/cookie-banner/playwright.config.js @@ -0,0 +1,16 @@ + +const { defineConfig } = require('@playwright/test'); +const baseConfig = require('../../tools/playwright/config.base.js'); +const server = require('./tools/playwright.webpack.config.js'); + +module.exports = defineConfig({ + ...baseConfig, + use: { + ...baseConfig.use, + baseURL: `http://127.0.0.1:${server.devServer.port}/`, + }, + webServer: { + ...baseConfig.webServer, + url: `http://127.0.0.1:${server.devServer.port}/`, + }, +}); \ No newline at end of file diff --git a/packages/cookie-banner/tools/playwright.webpack.config.js b/packages/cookie-banner/tools/playwright.webpack.config.js new file mode 100644 index 00000000..d35a771d --- /dev/null +++ b/packages/cookie-banner/tools/playwright.webpack.config.js @@ -0,0 +1,8 @@ +const baseConfig = require('./webpack.config'); + +module.exports = { + ...baseConfig, + devServer: { + port: 8091 + } +}; diff --git a/packages/cookie-banner/example/webpack.config.js b/packages/cookie-banner/tools/webpack.config.js similarity index 100% rename from packages/cookie-banner/example/webpack.config.js rename to packages/cookie-banner/tools/webpack.config.js From 1434e8f03e23723781ccc1c64eeac00fb1ffad9d Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 26 Mar 2025 11:13:17 +0000 Subject: [PATCH 02/29] re-organise tests --- .../__tests__/jest/analytics/index.js | 59 --------- .../__tests__/jest/banner/index.js | 97 -------------- .../cookie-banner/__tests__/jest/cookies.js | 53 -------- .../__tests__/jest/form/interactions.js | 64 ---------- .../__tests__/jest/form/not-render.js | 26 ---- .../__tests__/jest/form/render.js | 54 -------- .../__tests__/jest/google-eu-consent/index.js | 65 ---------- .../google-eu-consent/no-eu-consent-config.js | 45 ------- .../cookie-banner/__tests__/jest/reject.js | 47 ------- .../jest/{form/api.js => render-form.js} | 4 +- .../{banner/showBanner.js => show-banner.js} | 4 +- .../__tests__/playwright/banner.spec.js | 118 ++++++++++++++++++ .../__tests__/playwright/form.spec.js | 72 +++++++++++ .../playwright/google-eu-consent.spec.js | 51 ++++++++ .../__tests__/playwright/playwright.spec.js | 19 --- 15 files changed, 245 insertions(+), 533 deletions(-) delete mode 100644 packages/cookie-banner/__tests__/jest/analytics/index.js delete mode 100644 packages/cookie-banner/__tests__/jest/banner/index.js delete mode 100644 packages/cookie-banner/__tests__/jest/cookies.js delete mode 100644 packages/cookie-banner/__tests__/jest/form/interactions.js delete mode 100644 packages/cookie-banner/__tests__/jest/form/not-render.js delete mode 100644 packages/cookie-banner/__tests__/jest/form/render.js delete mode 100644 packages/cookie-banner/__tests__/jest/google-eu-consent/index.js delete mode 100644 packages/cookie-banner/__tests__/jest/google-eu-consent/no-eu-consent-config.js delete mode 100644 packages/cookie-banner/__tests__/jest/reject.js rename packages/cookie-banner/__tests__/jest/{form/api.js => render-form.js} (94%) rename packages/cookie-banner/__tests__/jest/{banner/showBanner.js => show-banner.js} (96%) create mode 100644 packages/cookie-banner/__tests__/playwright/banner.spec.js create mode 100644 packages/cookie-banner/__tests__/playwright/form.spec.js create mode 100644 packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js delete mode 100644 packages/cookie-banner/__tests__/playwright/playwright.spec.js diff --git a/packages/cookie-banner/__tests__/jest/analytics/index.js b/packages/cookie-banner/__tests__/jest/analytics/index.js deleted file mode 100644 index dfc70180..00000000 --- a/packages/cookie-banner/__tests__/jest/analytics/index.js +++ /dev/null @@ -1,59 +0,0 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; -let instance; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - instance = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - -describe(`Cookie banner > Analytics > Data layer additions`, () => { - beforeAll(init); - - it('It should add to the dataLayer when the banner is shown', async () => { - expect(dataLayer.find(e => e.event === "stormcb_display")).toBeDefined(); - }); - - it('It should add to the datalayer when accept all is clicked', async () => { - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(dataLayer.find(e => e.event === "stormcb_accept_all")).toBeDefined(); - expect(dataLayer.find(e => e.stormcb_performance === 1)).toBeDefined(); - expect(dataLayer.find(e => e.stormcb_test === 1)).toBeDefined(); - }); - - it('It should add to the datalayer when reject all is clicked', async () => { - instance.showBanner(); - document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); - expect(dataLayer.find(e => e.event === "stormcb_reject_all")).toBeDefined(); - expect(dataLayer.find(e => e.stormcb_performance === 0)).toBeDefined(); - expect(dataLayer.find(e => e.stormcb_test === 0)).toBeDefined(); - }); -}); diff --git a/packages/cookie-banner/__tests__/jest/banner/index.js b/packages/cookie-banner/__tests__/jest/banner/index.js deleted file mode 100644 index e6db006a..00000000 --- a/packages/cookie-banner/__tests__/jest/banner/index.js +++ /dev/null @@ -1,97 +0,0 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > DOM > render`, () => { - beforeAll(init); - - it('It should render the banner', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); - }); -}); - -describe(`Cookie banner > DOM > not render`, () => { - - it('It should not render the banner if hideBannerOnFormPage setting is true and on consent form page', async () => { - document.body.innerHTML = `
`; - cookieBanner({ - secure: false, - hideBannerOnFormPage: true, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); - }); -}); - - -describe(`Cookie banner > DOM > accessibility`, () => { - beforeAll(init); - it('The banner should be a region', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('role')).toEqual('region'); - }); - - it('The banner should be a polite aria live region', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-live')).toEqual('polite'); - }); - - it('The banner should have an aria label', async () => { - expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-label')).toBeDefined(); - }); - -}); - -describe(`Cookie banner > DOM > interactions`, () => { - beforeAll(init); - - it('Hides the banner', async () => { - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); - }); - -}); - diff --git a/packages/cookie-banner/__tests__/jest/cookies.js b/packages/cookie-banner/__tests__/jest/cookies.js deleted file mode 100644 index de511637..00000000 --- a/packages/cookie-banner/__tests__/jest/cookies.js +++ /dev/null @@ -1,53 +0,0 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > cookies > update`, () => { - beforeAll(init); - - it('Sets a cookie based on preferences form', async () => { - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); - - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - fields[1].checked = true; - fields[3].checked = true; - document.querySelector(`.${defaults.classNames.submitBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); - }); - -}); - diff --git a/packages/cookie-banner/__tests__/jest/form/interactions.js b/packages/cookie-banner/__tests__/jest/form/interactions.js deleted file mode 100644 index 63ea8109..00000000 --- a/packages/cookie-banner/__tests__/jest/form/interactions.js +++ /dev/null @@ -1,64 +0,0 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; - -const dispatchSyntheticEvent = (node, eventType) => { - let event = document.createEvent('Event'); - event.initEvent(eventType, true, true); - node.dispatchEvent(event); -}; - -describe(`Cookie banner > DOM > form interactions`, () => { - beforeAll(() => { - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Test yes label', - no: 'Test no label' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - }); - - it('Submit button should be disabled', async () => { - expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); - }); - - it('Submit button should be enabled if both field groups have values', async () => { - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - - fields[0].checked = true; - dispatchSyntheticEvent(fields[0], 'change');//for JSDOM - expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); - - fields[2].checked = true; - dispatchSyntheticEvent(fields[2], 'change');//for JSDOM - expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).toEqual(null); - }); - - it('Submit button should set the cookie and hide the banner', async () => { - document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); - expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); - }); -}); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/jest/form/not-render.js b/packages/cookie-banner/__tests__/jest/form/not-render.js deleted file mode 100644 index 7cb4225f..00000000 --- a/packages/cookie-banner/__tests__/jest/form/not-render.js +++ /dev/null @@ -1,26 +0,0 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; - -describe(`Cookie banner > DOM > form > not render`, () => { - document.body.innerHTML = `
`; - cookieBanner({ - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - - it('Should return if there is no form container', async () => { - expect(document.querySelector(`.${defaults.classNames.form}`)).toBeNull(); - }); - -}); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/jest/form/render.js b/packages/cookie-banner/__tests__/jest/form/render.js deleted file mode 100644 index d29d0a65..00000000 --- a/packages/cookie-banner/__tests__/jest/form/render.js +++ /dev/null @@ -1,54 +0,0 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; - -describe(`Cookie banner > DOM > form > render`, () => { - beforeAll(() => { - document.body.innerHTML = `
`; - cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - suggested: true, - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Test yes label', - no: 'Test no label' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); - }); - - it('Should render the form', async () => { - expect(document.querySelector(`.${defaults.classNames.form}`)).not.toBeNull(); - }); - - it('Should render a fieldset for each type', async () => { - const fieldset = Array.from(document.querySelectorAll(`.${defaults.classNames.fieldset}`)); - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - expect(fieldset.length).toEqual(2); - expect(fields.length).toEqual(4); - }); - - it('Should set the default values if any are set and no there is no user consent preferences', async () => { - const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - expect(fields[0].checked).toEqual(true); - }); - -}); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/jest/google-eu-consent/index.js b/packages/cookie-banner/__tests__/jest/google-eu-consent/index.js deleted file mode 100644 index 50ce12fb..00000000 --- a/packages/cookie-banner/__tests__/jest/google-eu-consent/index.js +++ /dev/null @@ -1,65 +0,0 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; - -/* eslint-disable camelcase */ -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - euConsentTypes: { - ad_storage: 'test', - ad_user_data: 'test', - ad_personalization: 'test', - analytics_storage: 'performance' - }, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > cookies > Google EU consent > default event`, () => { - beforeAll(init); - - it('must set a default consent event with all categories denied', async () => { - const banner = document.querySelector(`.${defaults.classNames.banner}`); - expect(banner).not.toBeNull(); - - //These assertions break Jest because of the use 'arguments' in the gtag implementation - //They have been manually validated in the browser - // expect(window.dataLayer).toEqual([ - // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }] - // ]); - // const acceptAllBtn = document.querySelector(`.${defaults.classNames.acceptBtn}`); - // acceptAllBtn.click(); - - // expect(window.dataLayer).toEqual([ - // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }], - // ['consent', 'update', { ad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted', analytics_storage: 'granted' }] - // ]); - }); - -}); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/jest/google-eu-consent/no-eu-consent-config.js b/packages/cookie-banner/__tests__/jest/google-eu-consent/no-eu-consent-config.js deleted file mode 100644 index abb4a86d..00000000 --- a/packages/cookie-banner/__tests__/jest/google-eu-consent/no-eu-consent-config.js +++ /dev/null @@ -1,45 +0,0 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > cookies > Google EU consent > no EU consent settings`, () => { - beforeAll(init); - - it('No errors if no consent options configured', async () => { - const banner = document.querySelector(`.${defaults.classNames.banner}`); - expect(banner).not.toBeNull(); - }); - -}); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/jest/reject.js b/packages/cookie-banner/__tests__/jest/reject.js deleted file mode 100644 index 5f98663f..00000000 --- a/packages/cookie-banner/__tests__/jest/reject.js +++ /dev/null @@ -1,47 +0,0 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - secure: false, - hideBannerOnFormPage: false, - types: { - test: { - title: 'Test title', - description: 'Test description', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - }, - performance: { - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - () => { } - ] - } - } - }); -}; - - -describe(`Cookie banner > reject`, () => { - beforeAll(init); - - it('Should reject all cookies whe the reject button is clicked', async () => { - document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); - expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); - }); - -}); - diff --git a/packages/cookie-banner/__tests__/jest/form/api.js b/packages/cookie-banner/__tests__/jest/render-form.js similarity index 94% rename from packages/cookie-banner/__tests__/jest/form/api.js rename to packages/cookie-banner/__tests__/jest/render-form.js index 8b331ee5..bda5e3a9 100644 --- a/packages/cookie-banner/__tests__/jest/form/api.js +++ b/packages/cookie-banner/__tests__/jest/render-form.js @@ -1,5 +1,5 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; +import cookieBanner from '../../src'; +import defaults from '../../src/lib/defaults'; describe(`Cookie banner > DOM > form > render by api`, () => { diff --git a/packages/cookie-banner/__tests__/jest/banner/showBanner.js b/packages/cookie-banner/__tests__/jest/show-banner.js similarity index 96% rename from packages/cookie-banner/__tests__/jest/banner/showBanner.js rename to packages/cookie-banner/__tests__/jest/show-banner.js index be8d6301..32e9ed00 100644 --- a/packages/cookie-banner/__tests__/jest/banner/showBanner.js +++ b/packages/cookie-banner/__tests__/jest/show-banner.js @@ -1,5 +1,5 @@ -import cookieBanner from '../../../src'; -import defaults from '../../../src/lib/defaults'; +import cookieBanner from '../../src'; +import defaults from '../../src/lib/defaults'; let instance; diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js new file mode 100644 index 00000000..1b644c6d --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -0,0 +1,118 @@ +const { test, expect } = require('@playwright/test'); +import AxeBuilder from '@axe-core/playwright'; + +let tabKey; + +test.beforeEach(async ({ page }, testInfo) => { + await page.goto('/'); + tabKey = testInfo.project.use.defaultBrowserType === 'webkit' + ? "Alt+Tab" + : "Tab"; +}); + +test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { + test('Should not have any automatically detectable accessibility issues', async ({ page }) => { + const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); + expect(accessibilityScanResults.violations).toEqual([]); + }); +}); + +// describe(`Cookie banner > DOM > render`, () => { +// beforeAll(init); + +// it('It should render the banner', async () => { +// expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); +// }); +// }); + +// describe(`Cookie banner > DOM > not render`, () => { + +// it('It should not render the banner if hideBannerOnFormPage setting is true and on consent form page', async () => { +// document.body.innerHTML = `
`; +// cookieBanner({ +// secure: false, +// hideBannerOnFormPage: true, +// types: { +// test: { +// title: 'Test title', +// description: 'Test description', +// labels: { +// yes: 'Pages you visit and actions you take will be measured and used to improve the service', +// no: 'Pages you visit and actions you take will not be measured and used to improve the service' +// }, +// fns: [ +// () => { } +// ] +// } +// } +// }); +// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); +// }); +// }); + + +// describe(`Cookie banner > DOM > accessibility`, () => { +// beforeAll(init); +// it('The banner should be a region', async () => { +// expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('role')).toEqual('region'); +// }); + +// it('The banner should be a polite aria live region', async () => { +// expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-live')).toEqual('polite'); +// }); + +// it('The banner should have an aria label', async () => { +// expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-label')).toBeDefined(); +// }); + +// }); + +// describe(`Cookie banner > DOM > interactions`, () => { +// beforeAll(init); + +// it('Hides the banner', async () => { +// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); +// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); +// }); + +// }); + +// it('Sets a cookie based on preferences form', async () => { +// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); + +// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); +// fields[1].checked = true; +// fields[3].checked = true; +// document.querySelector(`.${defaults.classNames.submitBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); +// }); + +// it('Should reject all cookies whe the reject button is clicked', async () => { +// document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); +// }); + +// describe(`Cookie banner > Analytics > Data layer additions`, () => { +// beforeAll(init); + +// it('It should add to the dataLayer when the banner is shown', async () => { +// expect(dataLayer.find(e => e.event === "stormcb_display")).toBeDefined(); +// }); + +// it('It should add to the datalayer when accept all is clicked', async () => { +// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); +// expect(dataLayer.find(e => e.event === "stormcb_accept_all")).toBeDefined(); +// expect(dataLayer.find(e => e.stormcb_performance === 1)).toBeDefined(); +// expect(dataLayer.find(e => e.stormcb_test === 1)).toBeDefined(); +// }); + +// it('It should add to the datalayer when reject all is clicked', async () => { +// instance.showBanner(); +// document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); +// expect(dataLayer.find(e => e.event === "stormcb_reject_all")).toBeDefined(); +// expect(dataLayer.find(e => e.stormcb_performance === 0)).toBeDefined(); +// expect(dataLayer.find(e => e.stormcb_test === 0)).toBeDefined(); +// }); +// }); + diff --git a/packages/cookie-banner/__tests__/playwright/form.spec.js b/packages/cookie-banner/__tests__/playwright/form.spec.js new file mode 100644 index 00000000..14d66e7f --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/form.spec.js @@ -0,0 +1,72 @@ +const { test, expect } = require('@playwright/test'); +import AxeBuilder from '@axe-core/playwright'; + +let tabKey; + +test.beforeEach(async ({ page }, testInfo) => { + await page.goto('/'); + tabKey = testInfo.project.use.defaultBrowserType === 'webkit' + ? "Alt+Tab" + : "Tab"; +}); + +test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { + test('Should not have any automatically detectable accessibility issues', async ({ page }) => { + const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); + expect(accessibilityScanResults.violations).toEqual([]); + }); +}); + +// it('Submit button should be disabled', async () => { +// expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); +// }); + +// it('Submit button should be enabled if both field groups have values', async () => { +// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); + +// fields[0].checked = true; +// dispatchSyntheticEvent(fields[0], 'change');//for JSDOM +// expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); + +// fields[2].checked = true; +// dispatchSyntheticEvent(fields[2], 'change');//for JSDOM +// expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).toEqual(null); +// }); + +// it('Submit button should set the cookie and hide the banner', async () => { +// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); +// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); +// }); + +// it('Should return if there is no form container', async () => { +// expect(document.querySelector(`.${defaults.classNames.form}`)).toBeNull(); +// }); + +// it('Should render the form', async () => { +// expect(document.querySelector(`.${defaults.classNames.form}`)).not.toBeNull(); +// }); + +// it('Should render a fieldset for each type', async () => { +// const fieldset = Array.from(document.querySelectorAll(`.${defaults.classNames.fieldset}`)); +// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); +// expect(fieldset.length).toEqual(2); +// expect(fields.length).toEqual(4); +// }); + +// it('Should set the default values if any are set and no there is no user consent preferences', async () => { +// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); +// expect(fields[0].checked).toEqual(true); +// }); + +// it('Sets a cookie based on preferences form', async () => { +// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); + +// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); +// fields[1].checked = true; +// fields[3].checked = true; +// document.querySelector(`.${defaults.classNames.submitBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); +// }); + diff --git a/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js new file mode 100644 index 00000000..605a55ad --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js @@ -0,0 +1,51 @@ +const { test, expect } = require('@playwright/test'); +import AxeBuilder from '@axe-core/playwright'; + +let tabKey; + +test.beforeEach(async ({ page }, testInfo) => { + await page.goto('/'); + tabKey = testInfo.project.use.defaultBrowserType === 'webkit' + ? "Alt+Tab" + : "Tab"; +}); + +// test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { +// test('Should not have any automatically detectable accessibility issues', async ({ page }) => { +// const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); +// expect(accessibilityScanResults.violations).toEqual([]); +// }); +// }); + +// describe(`Cookie banner > cookies > Google EU consent > default event`, () => { +// beforeAll(init); + +// it('must set a default consent event with all categories denied', async () => { +// const banner = document.querySelector(`.${defaults.classNames.banner}`); +// expect(banner).not.toBeNull(); + +// //These assertions break Jest because of the use 'arguments' in the gtag implementation +// //They have been manually validated in the browser +// // expect(window.dataLayer).toEqual([ +// // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }] +// // ]); +// // const acceptAllBtn = document.querySelector(`.${defaults.classNames.acceptBtn}`); +// // acceptAllBtn.click(); + +// // expect(window.dataLayer).toEqual([ +// // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }], +// // ['consent', 'update', { ad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted', analytics_storage: 'granted' }] +// // ]); +// }); + +// }); + +// describe(`Cookie banner > cookies > Google EU consent > no EU consent settings`, () => { +// beforeAll(init); + +// it('No errors if no consent options configured', async () => { +// const banner = document.querySelector(`.${defaults.classNames.banner}`); +// expect(banner).not.toBeNull(); +// }); + +// }); diff --git a/packages/cookie-banner/__tests__/playwright/playwright.spec.js b/packages/cookie-banner/__tests__/playwright/playwright.spec.js deleted file mode 100644 index 929a6695..00000000 --- a/packages/cookie-banner/__tests__/playwright/playwright.spec.js +++ /dev/null @@ -1,19 +0,0 @@ -const { test, expect } = require('@playwright/test'); -import AxeBuilder from '@axe-core/playwright'; - -let tabKey; - -test.beforeEach(async ({ page }, testInfo) => { - await page.goto('/'); - tabKey = testInfo.project.use.defaultBrowserType === 'webkit' - ? "Alt+Tab" - : "Tab"; -}); - -test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { - test('Should not have any automatically detectable accessibility issues', async ({ page }) => { - const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); - expect(accessibilityScanResults.violations).toEqual([]); - }); -}); - From a4ef629e77c573f0fcac3ceb43ce7c7c0228dea1 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 26 Mar 2025 15:54:43 +0000 Subject: [PATCH 03/29] WIP --- packages/boilerplate/playwright.config.js | 4 +- .../__tests__/playwright/banner.spec.js | 104 ++++----- .../__tests__/playwright/form.spec.js | 28 ++- .../playwright/google-eu-consent.spec.js | 15 +- packages/cookie-banner/example/src/form.html | 215 ++++++++++++++++++ packages/cookie-banner/example/src/index.html | 15 +- .../cookie-banner/example/src/js/index.js | 46 +--- packages/cookie-banner/playwright.config.js | 4 +- .../cookie-banner/tools/webpack.config.js | 5 + packages/outliner/playwright.config.js | 4 +- packages/skip/playwright.config.js | 4 +- packages/textarea/playwright.config.js | 4 +- tools/playwright/config.base.js | 5 +- 13 files changed, 319 insertions(+), 134 deletions(-) create mode 100644 packages/cookie-banner/example/src/form.html diff --git a/packages/boilerplate/playwright.config.js b/packages/boilerplate/playwright.config.js index b9c22fb4..0968cfa7 100644 --- a/packages/boilerplate/playwright.config.js +++ b/packages/boilerplate/playwright.config.js @@ -7,10 +7,10 @@ module.exports = defineConfig({ ...baseConfig, use: { ...baseConfig.use, - baseURL: `http://127.0.0.1:${server.devServer.port}/`, + baseURL: `http://localhost:${server.devServer.port}/`, }, webServer: { ...baseConfig.webServer, - url: `http://127.0.0.1:${server.devServer.port}/`, + url: `http://localhost:${server.devServer.port}/`, }, }); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 1b644c6d..d525bb04 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -3,77 +3,73 @@ import AxeBuilder from '@axe-core/playwright'; let tabKey; -test.beforeEach(async ({ page }, testInfo) => { +test.beforeEach(async ({ page, context }, testInfo) => { await page.goto('/'); tabKey = testInfo.project.use.defaultBrowserType === 'webkit' ? "Alt+Tab" : "Tab"; }); -test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { - test('Should not have any automatically detectable accessibility issues', async ({ page }) => { - const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); - expect(accessibilityScanResults.violations).toEqual([]); +test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { + test('Should render the banner', async ({ page }) => { + const banner = page.locator('.privacy-banner'); + await expect(banner).toHaveCount(1); + await expect(banner).toBeVisible(); + }); + + test('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { + const banner = page.locator('.privacy-banner'); + const acceptAll = page.locator('.privacy-banner__accept').first(); + + await expect(banner).toBeVisible(); + + await acceptAll.click(); + const cookies = await context.cookies(); + const preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); + + await expect(banner).not.toBeVisible(); + expect(preferences.value).toEqual(btoa(`{"consent":{"performance":1,"ads":1}}`)); + }); + + test('Should hide the banner and update preferences when cookies are rejected', async ({ page, context }) => { + const banner = page.locator('.privacy-banner'); + const rejectAll = page.locator('.privacy-banner__reject').first(); + + await rejectAll.click(); + const cookies = await context.cookies(); + const preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); + + await expect(banner).not.toBeVisible(); + expect(preferences.value).toEqual(btoa(`{"consent":{"performance":0,"ads":0}}`)); }); + }); -// describe(`Cookie banner > DOM > render`, () => { -// beforeAll(init); +test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { -// it('It should render the banner', async () => { -// expect(document.querySelector(`.${defaults.classNames.banner}`)).not.toBeNull(); -// }); -// }); +}); -// describe(`Cookie banner > DOM > not render`, () => { - -// it('It should not render the banner if hideBannerOnFormPage setting is true and on consent form page', async () => { -// document.body.innerHTML = `
`; -// cookieBanner({ -// secure: false, -// hideBannerOnFormPage: true, -// types: { -// test: { -// title: 'Test title', -// description: 'Test description', -// labels: { -// yes: 'Pages you visit and actions you take will be measured and used to improve the service', -// no: 'Pages you visit and actions you take will not be measured and used to improve the service' -// }, -// fns: [ -// () => { } -// ] -// } -// } -// }); -// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); -// }); -// }); +test.describe('Cookie banner > Banner > Aria', { tag: '@all'}, () => { + test('Banner should have the appropriate aria attributes', async ({ page }) => { + const banner = page.locator('.privacy-banner'); + await expect(banner).toHaveAttribute('role', 'region'); + await expect(banner).toHaveAttribute('aria-live', 'polite'); + await expect(banner).toHaveAttribute('aria-label'); + }); +}); +test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { + test('Should not have any automatically detectable accessibility issues', async ({ page }) => { + const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); + expect(accessibilityScanResults.violations).toEqual([]); + }); +}); -// describe(`Cookie banner > DOM > accessibility`, () => { -// beforeAll(init); -// it('The banner should be a region', async () => { -// expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('role')).toEqual('region'); -// }); - -// it('The banner should be a polite aria live region', async () => { -// expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-live')).toEqual('polite'); -// }); - -// it('The banner should have an aria label', async () => { -// expect(document.querySelector(`.${defaults.classNames.banner}`).getAttribute('aria-label')).toBeDefined(); -// }); - -// }); // describe(`Cookie banner > DOM > interactions`, () => { // beforeAll(init); -// it('Hides the banner', async () => { -// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); -// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); -// }); +// // }); diff --git a/packages/cookie-banner/__tests__/playwright/form.spec.js b/packages/cookie-banner/__tests__/playwright/form.spec.js index 14d66e7f..e51205be 100644 --- a/packages/cookie-banner/__tests__/playwright/form.spec.js +++ b/packages/cookie-banner/__tests__/playwright/form.spec.js @@ -4,7 +4,7 @@ import AxeBuilder from '@axe-core/playwright'; let tabKey; test.beforeEach(async ({ page }, testInfo) => { - await page.goto('/'); + await page.goto('/form.html'); tabKey = testInfo.project.use.defaultBrowserType === 'webkit' ? "Alt+Tab" : "Tab"; @@ -17,6 +17,32 @@ test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { }); }); +// describe(`Cookie banner > DOM > not render`, () => { + +// it('It should not render the banner if hideBannerOnFormPage setting is true and on consent form page', async () => { +// document.body.innerHTML = `
`; +// cookieBanner({ +// secure: false, +// hideBannerOnFormPage: true, +// types: { +// test: { +// title: 'Test title', +// description: 'Test description', +// labels: { +// yes: 'Pages you visit and actions you take will be measured and used to improve the service', +// no: 'Pages you visit and actions you take will not be measured and used to improve the service' +// }, +// fns: [ +// () => { } +// ] +// } +// } +// }); +// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); +// }); +// }); + + // it('Submit button should be disabled', async () => { // expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); // }); diff --git a/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js index 605a55ad..8fe881f6 100644 --- a/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js +++ b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js @@ -1,21 +1,14 @@ const { test, expect } = require('@playwright/test'); -import AxeBuilder from '@axe-core/playwright'; -let tabKey; test.beforeEach(async ({ page }, testInfo) => { await page.goto('/'); - tabKey = testInfo.project.use.defaultBrowserType === 'webkit' - ? "Alt+Tab" - : "Tab"; }); -// test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { -// test('Should not have any automatically detectable accessibility issues', async ({ page }) => { -// const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); -// expect(accessibilityScanResults.violations).toEqual([]); -// }); -// }); +test.describe('Cookie banner > Google EU Consent', { tag: '@all'}, () => { + +}); + // describe(`Cookie banner > cookies > Google EU consent > default event`, () => { // beforeAll(init); diff --git a/packages/cookie-banner/example/src/form.html b/packages/cookie-banner/example/src/form.html new file mode 100644 index 00000000..1833aced --- /dev/null +++ b/packages/cookie-banner/example/src/form.html @@ -0,0 +1,215 @@ + + + + StormID + + + + + +
+
+
+

Update your cookie preferences to view this content.

+ +
+
+
+

Cookies

+

Cookies are a common feature used on almost all websites. A cookie is a small text file that is downloaded + onto a device to allow a website to recognise it and to store some information about your preferences.

+

We use cookies for different reasons, including for managing your shopping cart, measuring your visits on our + sites, recognising and remembering your preferences and showing you personalised ads. Learn more about + cookies and how we use them.

+
+ +
+ + + \ No newline at end of file diff --git a/packages/cookie-banner/example/src/index.html b/packages/cookie-banner/example/src/index.html index 3b6e6a81..306c68d0 100644 --- a/packages/cookie-banner/example/src/index.html +++ b/packages/cookie-banner/example/src/index.html @@ -63,7 +63,8 @@ .embed iframe, .embed__placeholder { - width: 600px; + width: 100%; + max-width: 600px; aspect-ratio: 16 / 9; } @@ -191,6 +192,7 @@
+

Cookie banner example

@@ -199,16 +201,7 @@
-

Cookies

-

Cookies are a common feature used on almost all websites. A cookie is a small text file that is downloaded - onto a device to allow a website to recognise it and to store some information about your preferences.

-

We use cookies for different reasons, including for managing your shopping cart, measuring your visits on our - sites, recognising and remembering your preferences and showing you personalised ads. Learn more about - cookies and how we use them.

-
- -
+ \ No newline at end of file diff --git a/packages/cookie-banner/example/src/js/index.js b/packages/cookie-banner/example/src/js/index.js index b195b740..317d2dc7 100644 --- a/packages/cookie-banner/example/src/js/index.js +++ b/packages/cookie-banner/example/src/js/index.js @@ -1,39 +1,17 @@ import cookieBanner from '../../../src/index'; import toggle from '../../../../toggle/src/index'; - -const writeCookie = state => { - document.cookie = [ - `${state.settings.name}=${btoa(JSON.stringify(state))};`, - `expires=${(new Date(new Date().getTime() + (state.settings.expiry*24*60*60*1000))).toGMTString()};`, - state.settings.path ? `path=${state.settings.path};` : '', - state.settings.domain ? `domain=${state.settings.domain};` : '', - state.settings.samesite ? `SameSite=${state.settings.samesite};` : '', - state.settings.secure ? `secure` : '' - ].join(''); -}; const config = { name: '.Components.Dev.Consent', - secure: false, + secure: true, euConsentTypes: { ad_storage: 'ads', ad_user_data: 'ads', ad_personalization: 'ads', analytics_storage: 'performance' }, - hideBannerOnFormPage: false, + hideBannerOnFormPage: true, trapTab: true, - necessary: [ - () => { - writeCookie({ - settings: { - name: '.Test.NecessaryCookie', - expiry: 3 - }, - consent: '666', - }); - } - ], types: { performance: { // suggested: 1, @@ -44,16 +22,6 @@ const config = { no: 'Pages you visit and actions you take will not be measured and used to improve the service' }, fns: [ - () => { - // console.log('Performance fn'); - writeCookie({ - settings: { - name: '.Test.PerformanceCookie', - expiry: 3 - }, - consent: '666', - }); - }, state => state.utils.renderIframe(), state => state.utils.gtmSnippet('12345666') ] @@ -66,16 +34,6 @@ const config = { no: 'Our partners will still serve you ads, but they will not know you have visited out website' }, fns: [ - () => { - // console.log('Ads fn'); - writeCookie({ - settings: { - name: '.Test.AdsCookie', - expiry: 3 - }, - consent: '666', - }); - } ] } }, diff --git a/packages/cookie-banner/playwright.config.js b/packages/cookie-banner/playwright.config.js index b9c22fb4..0968cfa7 100644 --- a/packages/cookie-banner/playwright.config.js +++ b/packages/cookie-banner/playwright.config.js @@ -7,10 +7,10 @@ module.exports = defineConfig({ ...baseConfig, use: { ...baseConfig.use, - baseURL: `http://127.0.0.1:${server.devServer.port}/`, + baseURL: `http://localhost:${server.devServer.port}/`, }, webServer: { ...baseConfig.webServer, - url: `http://127.0.0.1:${server.devServer.port}/`, + url: `http://localhost:${server.devServer.port}/`, }, }); \ No newline at end of file diff --git a/packages/cookie-banner/tools/webpack.config.js b/packages/cookie-banner/tools/webpack.config.js index a2d72d75..5d69257f 100644 --- a/packages/cookie-banner/tools/webpack.config.js +++ b/packages/cookie-banner/tools/webpack.config.js @@ -22,6 +22,11 @@ module.exports = { title: pkg.name, template: './example/src/index.html', filename: 'index.html' + }), + new HtmlWebpackPlugin({ + title: pkg.name, + template: './example/src/form.html', + filename: 'form.html' }) ], module: { diff --git a/packages/outliner/playwright.config.js b/packages/outliner/playwright.config.js index b9c22fb4..0968cfa7 100644 --- a/packages/outliner/playwright.config.js +++ b/packages/outliner/playwright.config.js @@ -7,10 +7,10 @@ module.exports = defineConfig({ ...baseConfig, use: { ...baseConfig.use, - baseURL: `http://127.0.0.1:${server.devServer.port}/`, + baseURL: `http://localhost:${server.devServer.port}/`, }, webServer: { ...baseConfig.webServer, - url: `http://127.0.0.1:${server.devServer.port}/`, + url: `http://localhost:${server.devServer.port}/`, }, }); \ No newline at end of file diff --git a/packages/skip/playwright.config.js b/packages/skip/playwright.config.js index b9c22fb4..0968cfa7 100644 --- a/packages/skip/playwright.config.js +++ b/packages/skip/playwright.config.js @@ -7,10 +7,10 @@ module.exports = defineConfig({ ...baseConfig, use: { ...baseConfig.use, - baseURL: `http://127.0.0.1:${server.devServer.port}/`, + baseURL: `http://localhost:${server.devServer.port}/`, }, webServer: { ...baseConfig.webServer, - url: `http://127.0.0.1:${server.devServer.port}/`, + url: `http://localhost:${server.devServer.port}/`, }, }); \ No newline at end of file diff --git a/packages/textarea/playwright.config.js b/packages/textarea/playwright.config.js index b9c22fb4..0968cfa7 100644 --- a/packages/textarea/playwright.config.js +++ b/packages/textarea/playwright.config.js @@ -7,10 +7,10 @@ module.exports = defineConfig({ ...baseConfig, use: { ...baseConfig.use, - baseURL: `http://127.0.0.1:${server.devServer.port}/`, + baseURL: `http://localhost:${server.devServer.port}/`, }, webServer: { ...baseConfig.webServer, - url: `http://127.0.0.1:${server.devServer.port}/`, + url: `http://localhost:${server.devServer.port}/`, }, }); \ No newline at end of file diff --git a/tools/playwright/config.base.js b/tools/playwright/config.base.js index fc7ce412..1a18f774 100644 --- a/tools/playwright/config.base.js +++ b/tools/playwright/config.base.js @@ -12,7 +12,7 @@ module.exports = { timeout: 10_000, }, use: { - baseURL: 'http://127.0.0.1:8081', + baseURL: 'http://localhost', trace: 'on-first-retry', }, projects: [ @@ -27,7 +27,6 @@ module.exports = { use: { ...devices['Desktop Firefox'] }, grep: /@desktop|@all/, }, - { name: 'webkit', userAgent: 'Safari', @@ -48,7 +47,7 @@ module.exports = { ], webServer: { command: 'webpack-dev-server --config tools/playwright.webpack.config.js --hot --no-open', - url: 'http://127.0.0.1:8081', + url: 'http://localhost', reuseExistingServer: !process.env.CI, }, }; From 9f28d4dd87c5baeca8fff1e974e8f976471fb79a Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 27 Mar 2025 12:21:10 +0000 Subject: [PATCH 04/29] Tests WIP --- .../__tests__/playwright/banner.spec.js | 119 ++++++++++-------- .../__tests__/playwright/form.spec.js | 11 ++ .../__tests__/playwright/utils.spec.js | 16 +++ 3 files changed, 97 insertions(+), 49 deletions(-) create mode 100644 packages/cookie-banner/__tests__/playwright/utils.spec.js diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index d525bb04..e0c954aa 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -3,7 +3,7 @@ import AxeBuilder from '@axe-core/playwright'; let tabKey; -test.beforeEach(async ({ page, context }, testInfo) => { +test.beforeEach(async ({ page }, testInfo) => { await page.goto('/'); tabKey = testInfo.project.use.defaultBrowserType === 'webkit' ? "Alt+Tab" @@ -45,8 +45,77 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { }); +test.describe('Cookie banner > Banner > Analytics', { tag: '@all'}, () => { + + test('Should add to the dataLayer when the banner is shown', async ({ page }) => { + expect(await page.evaluate(() => window.dataLayer.find(e => e.event === "stormcb_display"))).toBeDefined(); + }); + + test('Should add to the datalayer when accept all is clicked', async ({ page }) => { + await page.locator('.privacy-banner__accept').first().click(); + const dataLayer = await page.evaluate(() => window.dataLayer); + expect(dataLayer.find(e => e.event === "stormcb_accept_all")).toBeDefined(); + expect(dataLayer.find(e => e.stormcb_performance === 1)).toBeDefined(); + expect(dataLayer.find(e => e.stormcb_ads === 1)).toBeDefined(); + }); + + test('Should add to the datalayer when reject all is clicked', async ({ page }) => { + await page.locator('.privacy-banner__reject').first().click(); + const dataLayer = await page.evaluate(() => window.dataLayer); + expect(dataLayer.find(e => e.event === "stormcb_reject_all")).toBeDefined(); + expect(dataLayer.find(e => e.stormcb_performance === 0)).toBeDefined(); + expect(dataLayer.find(e => e.stormcb_ads === 0)).toBeDefined(); + }); + +}); + test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { + test('If the banner is open, focus should move there first', async ({ page }, testInfo) => { + await page.keyboard.press(tabKey); + const expectedClass = (testInfo.project.use.defaultBrowserType === 'webkit') ? /privacy-banner__accept/ : /privacy-banner__link/; + await expect(page.locator(':focus')).toHaveClass(expectedClass); + }); + + test('If the banner is open and trapTab is set, focus should not leave the banner', async ({ page }, testInfo) => { + for(let i = 0; i<=5; i++) { + await page.keyboard.press(tabKey); + } + const expectedClass = (testInfo.project.use.defaultBrowserType === 'webkit') ? /privacy-banner__reject/ : /privacy-banner__link/; + await expect(page.locator(':focus')).toHaveClass(expectedClass); + }); + + test('Cookies can be accepted via keyboard', async ({ page, context }, testInfo) => { + const keyPresses = (testInfo.project.use.defaultBrowserType === 'webkit') ? 0 : 2; + const banner = page.locator('.privacy-banner'); + + for(let i = 0; i<=keyPresses; i++) { + await page.keyboard.press(tabKey); + } + + await page.keyboard.press('Enter'); + const cookies = await context.cookies(); + const preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); + await expect(banner).not.toBeVisible(); + expect(preferences.value).toEqual(btoa(`{"consent":{"performance":1,"ads":1}}`)); + }); + + test('Cookies can be rejected via keyboard', async ({ page, context }, testInfo) => { + const keyPresses = (testInfo.project.use.defaultBrowserType === 'webkit') ? 1 : 3; + const banner = page.locator('.privacy-banner'); + + for(let i = 0; i<=keyPresses; i++) { + await page.keyboard.press(tabKey); + } + + await page.keyboard.press('Enter'); + const cookies = await context.cookies(); + const preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); + + await expect(banner).not.toBeVisible(); + expect(preferences.value).toEqual(btoa(`{"consent":{"performance":0,"ads":0}}`)); + }); + }); test.describe('Cookie banner > Banner > Aria', { tag: '@all'}, () => { @@ -64,51 +133,3 @@ test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { expect(accessibilityScanResults.violations).toEqual([]); }); }); - - -// describe(`Cookie banner > DOM > interactions`, () => { -// beforeAll(init); - -// - -// }); - -// it('Sets a cookie based on preferences form', async () => { -// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); - -// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); -// fields[1].checked = true; -// fields[3].checked = true; -// document.querySelector(`.${defaults.classNames.submitBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); -// }); - -// it('Should reject all cookies whe the reject button is clicked', async () => { -// document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); -// }); - -// describe(`Cookie banner > Analytics > Data layer additions`, () => { -// beforeAll(init); - -// it('It should add to the dataLayer when the banner is shown', async () => { -// expect(dataLayer.find(e => e.event === "stormcb_display")).toBeDefined(); -// }); - -// it('It should add to the datalayer when accept all is clicked', async () => { -// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); -// expect(dataLayer.find(e => e.event === "stormcb_accept_all")).toBeDefined(); -// expect(dataLayer.find(e => e.stormcb_performance === 1)).toBeDefined(); -// expect(dataLayer.find(e => e.stormcb_test === 1)).toBeDefined(); -// }); - -// it('It should add to the datalayer when reject all is clicked', async () => { -// instance.showBanner(); -// document.querySelector(`.${defaults.classNames.rejectBtn}`).click(); -// expect(dataLayer.find(e => e.event === "stormcb_reject_all")).toBeDefined(); -// expect(dataLayer.find(e => e.stormcb_performance === 0)).toBeDefined(); -// expect(dataLayer.find(e => e.stormcb_test === 0)).toBeDefined(); -// }); -// }); - diff --git a/packages/cookie-banner/__tests__/playwright/form.spec.js b/packages/cookie-banner/__tests__/playwright/form.spec.js index e51205be..d20fe368 100644 --- a/packages/cookie-banner/__tests__/playwright/form.spec.js +++ b/packages/cookie-banner/__tests__/playwright/form.spec.js @@ -42,6 +42,17 @@ test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { // }); // }); +// it('Sets a cookie based on preferences form', async () => { +// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); + +// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); +// fields[1].checked = true; +// fields[3].checked = true; +// document.querySelector(`.${defaults.classNames.submitBtn}`).click(); +// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); +// }); + // it('Submit button should be disabled', async () => { // expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); diff --git a/packages/cookie-banner/__tests__/playwright/utils.spec.js b/packages/cookie-banner/__tests__/playwright/utils.spec.js new file mode 100644 index 00000000..dafc3e34 --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/utils.spec.js @@ -0,0 +1,16 @@ +const { test, expect } = require('@playwright/test'); + +test.describe('Cookie banner > IFrame ', { tag: '@all'}, () => { + // test('Should render the banner', async ({ page }) => { + // const banner = page.locator('.privacy-banner'); + // await expect(banner).toHaveCount(1); + // await expect(banner).toBeVisible(); + // }); +}); + +test.describe('Cookie banner > GA', { tag: '@all'}, () => { + // test('Should add to the dataLayer when the banner is shown', async ({ page }) => { + // expect(await page.evaluate(() => window.dataLayer.find(e => e.event === "stormcb_display"))).toBeDefined(); + // }); +}); + From bc782633064a1e94603b02b0e5a8a4887b16b2c9 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Mon, 31 Mar 2025 14:33:51 +0100 Subject: [PATCH 05/29] More WIP --- .../playwright/google-eu-consent.spec.js | 28 +++++++++++++++++-- packages/cookie-banner/example/src/form.html | 4 +-- packages/cookie-banner/example/src/index.html | 7 +++-- .../cookie-banner/example/src/js/index.js | 5 ++-- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js index 8fe881f6..1ff8ee75 100644 --- a/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js +++ b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js @@ -1,12 +1,36 @@ const { test, expect } = require('@playwright/test'); - -test.beforeEach(async ({ page }, testInfo) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); }); test.describe('Cookie banner > Google EU Consent', { tag: '@all'}, () => { + test.only('Should set a default consent event with all categories denied', async ({ page }) => { + const dataLayer = await page.evaluate(() => window.dataLayer); + const acceptAll = page.locator('.privacy-banner__accept').first(); + + const expectedConsent = { + '0': 'consent', + '1': 'default', + '2': { + ad_storage: 'denied', + ad_user_data: 'denied', + ad_personalization: 'denied', + analytics_storage: 'denied', + wait_for_update: 500 + } + } + + dataLayer.find(e => {console.log(e, "item being compared"); return e === expectedConsent;}) + + //expect(dataLayer[0]).toEqual(expectedConsent); + //expect(dataLayer.find(e => e === expectedConsent)).toBeDefined(); + + // await acceptAll.click(); + // const newDataLayer = await page.evaluate(() => window.dataLayer); + // console.log(newDataLayer); + }); }); diff --git a/packages/cookie-banner/example/src/form.html b/packages/cookie-banner/example/src/form.html index 1833aced..ebde0a61 100644 --- a/packages/cookie-banner/example/src/form.html +++ b/packages/cookie-banner/example/src/form.html @@ -43,7 +43,7 @@ } p { - margin-top: 1.5rem; + margin-bottom: 1.5rem; } fieldset { @@ -119,7 +119,7 @@ display: inline-block; } - button+button { + button + button, button + a { margin-left: 12px; } diff --git a/packages/cookie-banner/example/src/index.html b/packages/cookie-banner/example/src/index.html index 306c68d0..92e3b041 100644 --- a/packages/cookie-banner/example/src/index.html +++ b/packages/cookie-banner/example/src/index.html @@ -27,7 +27,8 @@ h1 { font: 1.25rem/1.2 sans-serif; - margin-top: 1.5rem; + font-weight: bold; + margin: 1.5rem 0; } h2 { @@ -43,7 +44,7 @@ } p { - margin-top: 1.5rem; + margin-bottom: 1.5rem; } fieldset { @@ -119,7 +120,7 @@ display: inline-block; } - button+button { + button + button, button + a { margin-left: 12px; } diff --git a/packages/cookie-banner/example/src/js/index.js b/packages/cookie-banner/example/src/js/index.js index 1a7c672c..58720efd 100644 --- a/packages/cookie-banner/example/src/js/index.js +++ b/packages/cookie-banner/example/src/js/index.js @@ -1,8 +1,9 @@ import cookieBanner from '../../../src/index'; import toggle from '../../../../toggle/src/index'; -import sampleTemplates from '../../example/src/js/sample-templates'; +import sampleTemplates from './sample-templates'; -const config = {...sampleTemplates, +const config = { + ...sampleTemplates, name: '.Components.Dev.Consent', secure: true, euConsentTypes: { From e50f253b1d7a0c07b82bd964cd82ab9c0dfbdaaf Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Tue, 1 Apr 2025 15:54:09 +0100 Subject: [PATCH 06/29] more tests --- .../__tests__/playwright/banner.spec.js | 13 +++ .../playwright/google-eu-consent.spec.js | 88 ++++++++--------- .../__tests__/playwright/utils.spec.js | 83 +++++++++++++++- .../cookie-banner/example/src/js/index.js | 99 +++++++++---------- 4 files changed, 181 insertions(+), 102 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index e0c954aa..93c59409 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -42,6 +42,19 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { await expect(banner).not.toBeVisible(); expect(preferences.value).toEqual(btoa(`{"consent":{"performance":0,"ads":0}}`)); }); + + + test('Should re-open the banner if Update preferences links are used', async ({ page }) => { + const banner = page.locator('.privacy-banner'); + const updateLink = page.locator('.js-preferences-update').first(); + const rejectAll = page.locator('.privacy-banner__reject').first(); + + await rejectAll.click(); + await expect(banner).not.toBeVisible(); + await updateLink.click(); + await expect(banner).toBeVisible(); + }); + }); diff --git a/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js index 1ff8ee75..12e2958c 100644 --- a/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js +++ b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js @@ -1,14 +1,19 @@ const { test, expect } = require('@playwright/test'); +const deepEqual = (a, b) => { + if (a === b) return true; + if (typeof a !== 'object' || typeof b !== 'object') return false; + if (Object.keys(a).length !== Object.keys(b).length) return false; + return Object.keys(a).every(key => deepEqual(a[key], b[key])); +} + test.beforeEach(async ({ page }) => { await page.goto('/'); }); test.describe('Cookie banner > Google EU Consent', { tag: '@all'}, () => { - test.only('Should set a default consent event with all categories denied', async ({ page }) => { - const dataLayer = await page.evaluate(() => window.dataLayer); - const acceptAll = page.locator('.privacy-banner__accept').first(); - + test('Should set a default consent event with all categories denied', async ({ page }) => { + let dataLayer = await page.evaluate(() => window.dataLayer); const expectedConsent = { '0': 'consent', '1': 'default', @@ -19,50 +24,43 @@ test.describe('Cookie banner > Google EU Consent', { tag: '@all'}, () => { analytics_storage: 'denied', wait_for_update: 500 } - } + }; + expect(dataLayer.find(e => deepEqual(e, expectedConsent))).toBeDefined(); + }); - dataLayer.find(e => {console.log(e, "item being compared"); return e === expectedConsent;}) + test('Should set consent to granted if accept all is clicked', async ({ page }) => { + const acceptAll = page.locator('.privacy-banner__accept').first(); + const updatedConsent = { + '0': 'consent', + '1': 'update', + '2': { + ad_storage: 'granted', + ad_user_data: 'granted', + ad_personalization: 'granted', + analytics_storage: 'granted', + } + }; - //expect(dataLayer[0]).toEqual(expectedConsent); - //expect(dataLayer.find(e => e === expectedConsent)).toBeDefined(); + await acceptAll.click(); + const dataLayer = await page.evaluate(() => window.dataLayer); + expect(dataLayer.find(e => deepEqual(e, updatedConsent))).toBeDefined(); + }); - // await acceptAll.click(); - // const newDataLayer = await page.evaluate(() => window.dataLayer); - // console.log(newDataLayer); + test('Should set consent to denied if reject all is clicked', async ({ page }) => { + const rejectAll = page.locator('.privacy-banner__reject').first(); + const updatedConsent = { + '0': 'consent', + '1': 'update', + '2': { + ad_storage: 'denied', + ad_user_data: 'denied', + ad_personalization: 'denied', + analytics_storage: 'denied', + } + }; + await rejectAll.click(); + const dataLayer = await page.evaluate(() => window.dataLayer); + expect(dataLayer.find(e => deepEqual(e, updatedConsent))).toBeDefined(); }); }); - - -// describe(`Cookie banner > cookies > Google EU consent > default event`, () => { -// beforeAll(init); - -// it('must set a default consent event with all categories denied', async () => { -// const banner = document.querySelector(`.${defaults.classNames.banner}`); -// expect(banner).not.toBeNull(); - -// //These assertions break Jest because of the use 'arguments' in the gtag implementation -// //They have been manually validated in the browser -// // expect(window.dataLayer).toEqual([ -// // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }] -// // ]); -// // const acceptAllBtn = document.querySelector(`.${defaults.classNames.acceptBtn}`); -// // acceptAllBtn.click(); - -// // expect(window.dataLayer).toEqual([ -// // ['consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied' }], -// // ['consent', 'update', { ad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted', analytics_storage: 'granted' }] -// // ]); -// }); - -// }); - -// describe(`Cookie banner > cookies > Google EU consent > no EU consent settings`, () => { -// beforeAll(init); - -// it('No errors if no consent options configured', async () => { -// const banner = document.querySelector(`.${defaults.classNames.banner}`); -// expect(banner).not.toBeNull(); -// }); - -// }); diff --git a/packages/cookie-banner/__tests__/playwright/utils.spec.js b/packages/cookie-banner/__tests__/playwright/utils.spec.js index dafc3e34..5167408c 100644 --- a/packages/cookie-banner/__tests__/playwright/utils.spec.js +++ b/packages/cookie-banner/__tests__/playwright/utils.spec.js @@ -1,11 +1,84 @@ const { test, expect } = require('@playwright/test'); +test.beforeEach(async ({ page }) => { + await page.goto('/'); +}); + + test.describe('Cookie banner > IFrame ', { tag: '@all'}, () => { - // test('Should render the banner', async ({ page }) => { - // const banner = page.locator('.privacy-banner'); - // await expect(banner).toHaveCount(1); - // await expect(banner).toBeVisible(); - // }); + test('Should not have any visible iframes when banner is initially shown', async ({ page }) => { + const banner = page.locator('.privacy-banner'); + await expect(banner).toBeVisible(); + + const iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + + const placeholders = page.locator('[data-iframe-src]'); + expect(await placeholders.count()).toBeGreaterThan(0); + }); + + test('Should not have any visible iframes when cookies are rejected', async ({ page }) => { + let iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + const rejectAll = page.locator('.privacy-banner__reject').first(); + await rejectAll.click(); + iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + }); + + test('Should load the iframes when all cookies are accepted', async ({ page }) => { + let iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + const acceptAll = page.locator('.privacy-banner__accept').first(); + await acceptAll.click(); + iframes = page.locator('iframe'); + expect(await iframes.count()).toBeGreaterThan(0); + }); + + test('Should not have any visible iframes when cookies are rejected via the form', async ({ page }) => { + await page.goto('/form.html'); + + let iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + + const radios = await page.getByLabel(/No thank you/).all(); + for(const radio of radios) { + await radio.check({force: true}); + } + await page.locator('.privacy-banner__submit').click(); + + iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + }); + + test('Should not have any visible iframes if only performance cookies are accepted', async ({ page }) => { + await page.goto('/form.html'); + + let iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + + await page.getByLabel(/Pages you visit and actions you take will be measured and used to improve the service/).check(); + await page.getByLabel(/Our partners will still serve you ads, but they will not know you have visited out website/).check({force: true}); + await page.locator('.privacy-banner__submit').click(); + + iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + }); + + test('Should load the iframe once third party cookies are accepted', async ({ page }) => { + await page.goto('/form.html'); + + let iframes = page.locator('iframe'); + await expect(iframes).toHaveCount(0); + + await page.getByLabel(/Pages you visit and actions you take will not be measured and used to improve the service/).check({force: true}); + await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check(); + await page.locator('.privacy-banner__submit').click(); + + iframes = page.locator('iframe'); + expect(await iframes.count()).toBeGreaterThan(0); + }); + }); test.describe('Cookie banner > GA', { tag: '@all'}, () => { diff --git a/packages/cookie-banner/example/src/js/index.js b/packages/cookie-banner/example/src/js/index.js index 58720efd..32239fff 100644 --- a/packages/cookie-banner/example/src/js/index.js +++ b/packages/cookie-banner/example/src/js/index.js @@ -1,56 +1,51 @@ -import cookieBanner from '../../../src/index'; -import toggle from '../../../../toggle/src/index'; -import sampleTemplates from './sample-templates'; - +import cookieBanner from "../../../src/index"; +import toggle from "../../../../toggle/src/index"; +import sampleTemplates from "./sample-templates"; + const config = { - ...sampleTemplates, - name: '.Components.Dev.Consent', - secure: true, - euConsentTypes: { - ad_storage: 'ads', - ad_user_data: 'ads', - ad_personalization: 'ads', - analytics_storage: 'performance' - }, - hideBannerOnFormPage: true, - trapTab: true, - types: { - performance: { - // suggested: 1, - title: 'Performance preferences', - description: 'Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.', - labels: { - yes: 'Pages you visit and actions you take will be measured and used to improve the service', - no: 'Pages you visit and actions you take will not be measured and used to improve the service' - }, - fns: [ - state => state.utils.renderIframe(), - state => state.utils.gtmSnippet('12345666') - ] - }, - ads: { - title: 'Personalised ads preferences', - description: 'We work with advertising partners to show you ads for our products and services across the web. You can choose whether we collect and share that data with our partners below. ', - labels: { - yes: 'Our partners might serve you ads knowing you have visited our website', - no: 'Our partners will still serve you ads, but they will not know you have visited out website' - }, - fns: [ - ] - } - } + ...sampleTemplates, + name: ".Components.Dev.Consent", + secure: true, + euConsentTypes: { + ad_storage: "ads", + ad_user_data: "ads", + ad_personalization: "ads", + analytics_storage: "performance", + }, + hideBannerOnFormPage: true, + trapTab: true, + types: { + performance: { + // suggested: 1, + title: "Performance preferences", + description: + "Performance cookies are used to measure the performance of our website and make improvements. Your personal data is not identified.", + labels: { + yes: "Pages you visit and actions you take will be measured and used to improve the service", + no: "Pages you visit and actions you take will not be measured and used to improve the service", + }, + fns: [(state) => state.utils.gtmSnippet("12345666")], + }, + ads: { + title: "Personalised ads preferences", + description: + "We work with advertising partners to show you ads for our products and services across the web. You can choose whether we collect and share that data with our partners below. ", + labels: { + yes: "Our partners might serve you ads knowing you have visited our website", + no: "Our partners will still serve you ads, but they will not know you have visited out website", + }, + fns: [(state) => state.utils.renderIframe()], + }, + }, }; -window.addEventListener('DOMContentLoaded', () => { - let bannerToggle; - document.addEventListener('banner.show', () => [ bannerToggle ] = toggle('.js-toggle-banner')); - document.addEventListener('banner.hide', () => bannerToggle.getState().isOpen && bannerToggle.startToggle()); - - const banner = cookieBanner(config); +window.addEventListener("DOMContentLoaded", () => { + const banner = cookieBanner(config); - [].slice.call(document.querySelectorAll('.js-preferences-update')).forEach(btn => btn.addEventListener('click', e => { - if (banner.getState().bannerOpen) return; - banner.showBanner(); - bannerToggle.startToggle(); - })); -}); \ No newline at end of file + [].slice.call(document.querySelectorAll(".js-preferences-update")).forEach((btn) => + btn.addEventListener("click", (e) => { + if (banner.getState().bannerOpen) return; + banner.showBanner(); + }) + ); +}); From 4ac39dad0ba23f4de46cc799a69f1a4f670de0c3 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Tue, 1 Apr 2025 16:57:51 +0100 Subject: [PATCH 07/29] GTM tests --- .../__tests__/playwright/utils.spec.js | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/utils.spec.js b/packages/cookie-banner/__tests__/playwright/utils.spec.js index 5167408c..a7556948 100644 --- a/packages/cookie-banner/__tests__/playwright/utils.spec.js +++ b/packages/cookie-banner/__tests__/playwright/utils.spec.js @@ -82,8 +82,74 @@ test.describe('Cookie banner > IFrame ', { tag: '@all'}, () => { }); test.describe('Cookie banner > GA', { tag: '@all'}, () => { - // test('Should add to the dataLayer when the banner is shown', async ({ page }) => { - // expect(await page.evaluate(() => window.dataLayer.find(e => e.event === "stormcb_display"))).toBeDefined(); - // }); + test('Should not load a GTM container by default', async ({ page }) => { + const banner = page.locator('.privacy-banner'); + await expect(banner).toBeVisible(); + + const GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + }); + + test('Should not load a GTM container when cookies are rejected', async ({ page }) => { + let GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + const rejectAll = page.locator('.privacy-banner__reject').first(); + await rejectAll.click(); + GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + }); + + test('Should load a GTM container when cookies are accepted', async ({ page }) => { + let GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + const acceptAll = page.locator('.privacy-banner__accept').first(); + await acceptAll.click(); + GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(1); + }); + + test('Should not load a GTM container when cookies are rejected via the form', async ({ page }) => { + await page.goto('/form.html'); + + let GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + + const radios = await page.getByLabel(/No thank you/).all(); + for(const radio of radios) { + await radio.check({force: true}); + } + await page.locator('.privacy-banner__submit').click(); + + GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + }); + + test('Should not have any visible iframes if only ads cookies are accepted', async ({ page }) => { + await page.goto('/form.html'); + + let GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + + await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check(); + await page.getByLabel(/Pages you visit and actions you take will not be measured and used to improve the service/).check({force: true}); + await page.locator('.privacy-banner__submit').click(); + + GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + }); + + test('Should load a GTM container if performance cookies are accepted', async ({ page }) => { + await page.goto('/form.html'); + + let GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(0); + + await page.getByLabel(/Pages you visit and actions you take will be measured and used to improve the service/).check(); + await page.getByLabel(/Our partners will still serve you ads, but they will not know you have visited out website/).check({force: true}); + await page.locator('.privacy-banner__submit').click(); + + GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(1); + }); }); From 206c91fc8c4f8d1ac6ef03bbefe1478d56a45e92 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 09:44:22 +0100 Subject: [PATCH 08/29] Form based tests --- .../__tests__/playwright/form.spec.js | 204 +++++++++--------- .../__tests__/playwright/utils.spec.js | 8 +- 2 files changed, 109 insertions(+), 103 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/form.spec.js b/packages/cookie-banner/__tests__/playwright/form.spec.js index d20fe368..10847bdf 100644 --- a/packages/cookie-banner/__tests__/playwright/form.spec.js +++ b/packages/cookie-banner/__tests__/playwright/form.spec.js @@ -1,109 +1,115 @@ -const { test, expect } = require('@playwright/test'); -import AxeBuilder from '@axe-core/playwright'; +const { test, expect } = require("@playwright/test"); +import AxeBuilder from "@axe-core/playwright"; let tabKey; test.beforeEach(async ({ page }, testInfo) => { - await page.goto('/form.html'); - tabKey = testInfo.project.use.defaultBrowserType === 'webkit' - ? "Alt+Tab" - : "Tab"; + await page.goto("/form.html"); + tabKey = testInfo.project.use.defaultBrowserType === "webkit" ? "Alt+Tab" : "Tab"; }); -test.describe('Cookie banner > Axe', { tag: '@reduced'}, () => { - test('Should not have any automatically detectable accessibility issues', async ({ page }) => { - const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); - expect(accessibilityScanResults.violations).toEqual([]); +test.describe("Cookie banner > Functionality", { tag: "@all" }, () => { + test("Should not render the banner when the hideBannerOnFormPage has been used", async ({ page }) => { + const banner = page.locator(".privacy-banner"); + await expect(banner).toHaveCount(0); + }); + + test("Should not render the form if there is no form container on the page", async ({ page }) => { + await page.goto("/"); + const form = page.locator(".privacy-banner__form"); + await expect(form).toHaveCount(0); + }); + + test("Should render the form if the container is on the page", async ({ page }) => { + const form = page.locator(".privacy-banner__form"); + await expect(form).toHaveCount(1); + await expect(form).toBeVisible(); + }); + + test("The submit button should be disabled if no choices are made", async ({ page }) => { + const radios = await page.getByRole('radio').all(); + const submitBtn = page.locator(".privacy-banner__submit"); + await expect(submitBtn).toHaveRole('button'); + + for (const radio of radios) { + await expect(radio).not.toBeChecked(); + } + + await expect(submitBtn).toBeDisabled(); + }); + + test("The submit button should be enabled if choices are made for all consent types", async ({ page }) => { + const submitBtn = page.locator(".privacy-banner__submit"); + await expect(submitBtn).toBeDisabled(); + await expect(submitBtn).toHaveRole('button'); + + await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check({force: true}); + await expect(submitBtn).toBeDisabled(); + + await page.getByLabel(/Pages you visit and actions you take will not be measured and used to improve the service/).check({force: true}); + await expect(submitBtn).toBeEnabled(); + }); + + test("A cookie should be set when the form is submitted and user preferences updated", async ({ page, context }) => { + const submitBtn = page.locator(".privacy-banner__submit"); + + await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check({force: true}); + await page.getByLabel(/Pages you visit and actions you take will not be measured and used to improve the service/).check({force: true}); + await submitBtn.click(); + + let cookies = await context.cookies(); + let preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); + expect(preferences.value).toEqual(btoa(`{"consent":{"performance":0,"ads":1}}`)); + + await page.getByLabel(/Pages you visit and actions you take will be measured and used to improve the service/).check({force: true}); + await page.getByLabel(/Our partners will still serve you ads, but they will not know you have visited out website/).check({force: true}); + await submitBtn.click(); + + cookies = await context.cookies(); + preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); + expect(preferences.value).toEqual(btoa(`{"consent":{"performance":1,"ads":0}}`)); }); }); -// describe(`Cookie banner > DOM > not render`, () => { - -// it('It should not render the banner if hideBannerOnFormPage setting is true and on consent form page', async () => { -// document.body.innerHTML = `
`; -// cookieBanner({ -// secure: false, -// hideBannerOnFormPage: true, -// types: { -// test: { -// title: 'Test title', -// description: 'Test description', -// labels: { -// yes: 'Pages you visit and actions you take will be measured and used to improve the service', -// no: 'Pages you visit and actions you take will not be measured and used to improve the service' -// }, -// fns: [ -// () => { } -// ] -// } -// } -// }); -// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); -// }); -// }); - -// it('Sets a cookie based on preferences form', async () => { -// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); - -// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); -// fields[1].checked = true; -// fields[3].checked = true; -// document.querySelector(`.${defaults.classNames.submitBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); -// }); - - -// it('Submit button should be disabled', async () => { -// expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); -// }); - -// it('Submit button should be enabled if both field groups have values', async () => { -// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); - -// fields[0].checked = true; -// dispatchSyntheticEvent(fields[0], 'change');//for JSDOM -// expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).not.toBeNull(); - -// fields[2].checked = true; -// dispatchSyntheticEvent(fields[2], 'change');//for JSDOM -// expect(document.querySelector(`.${defaults.classNames.submitBtn}`).getAttribute('disabled')).toEqual(null); -// }); - -// it('Submit button should set the cookie and hide the banner', async () => { -// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); -// expect(document.querySelector(`.${defaults.classNames.banner}`)).toBeNull(); -// }); - -// it('Should return if there is no form container', async () => { -// expect(document.querySelector(`.${defaults.classNames.form}`)).toBeNull(); -// }); - -// it('Should render the form', async () => { -// expect(document.querySelector(`.${defaults.classNames.form}`)).not.toBeNull(); -// }); - -// it('Should render a fieldset for each type', async () => { -// const fieldset = Array.from(document.querySelectorAll(`.${defaults.classNames.fieldset}`)); -// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); -// expect(fieldset.length).toEqual(2); -// expect(fields.length).toEqual(4); -// }); - -// it('Should set the default values if any are set and no there is no user consent preferences', async () => { -// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); -// expect(fields[0].checked).toEqual(true); -// }); - -// it('Sets a cookie based on preferences form', async () => { -// document.querySelector(`.${defaults.classNames.acceptBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":1,"performance":1}}`)}`); - -// const fields = Array.from(document.querySelectorAll(`.${defaults.classNames.field}`)); -// fields[1].checked = true; -// fields[3].checked = true; -// document.querySelector(`.${defaults.classNames.submitBtn}`).click(); -// expect(document.cookie).toEqual(`${defaults.name}=${btoa(`{"consent":{"test":0,"performance":0}}`)}`); -// }); +test.describe("Cookie banner > Form >Markup", { tag: "@all" }, () => { + test("Should render a fieldset for each cookie type", async ({ page }) => { + const fieldsets = page.locator(".privacy-banner__fieldset"); + await expect(fieldsets).toHaveCount(2); + for (const fieldset of await fieldsets.all()) { + await expect(fieldset.locator('legend')).toHaveCount(1); + } + }); + + test("Should have a yes/no radio button per cookie type with appropriate labels", async ({ page }) => { + const labels = page.locator(".privacy-banner__fieldset label"); + + for (const label of await labels.all()) { + await expect(label.locator('input[type=radio]')).toHaveCount(1); + } + }); +}); + +test.describe("Cookie banner > Form > Keyboard", { tag: "@all" }, () => { + test("Should be able to update cookie preferences via keyboard", async ({ page, context }) => { + for(let i = 0; i < 2; i++) { + await page.keyboard.press(tabKey); + } + for(let i = 0; i < 2; i++) { + await page.keyboard.press('Space'); + await page.keyboard.press(tabKey); + } + await page.keyboard.press('Enter'); + + let cookies = await context.cookies(); + let preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); + expect(preferences.value).toEqual(btoa(`{"consent":{"performance":1,"ads":1}}`)); + }); +}); + +test.describe("Cookie banner > Axe", { tag: "@reduced" }, () => { + test("Should not have any automatically detectable accessibility issues", async ({ page }) => { + const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); + expect(accessibilityScanResults.violations).toEqual([]); + }); +}); \ No newline at end of file diff --git a/packages/cookie-banner/__tests__/playwright/utils.spec.js b/packages/cookie-banner/__tests__/playwright/utils.spec.js index a7556948..289fad32 100644 --- a/packages/cookie-banner/__tests__/playwright/utils.spec.js +++ b/packages/cookie-banner/__tests__/playwright/utils.spec.js @@ -57,7 +57,7 @@ test.describe('Cookie banner > IFrame ', { tag: '@all'}, () => { let iframes = page.locator('iframe'); await expect(iframes).toHaveCount(0); - await page.getByLabel(/Pages you visit and actions you take will be measured and used to improve the service/).check(); + await page.getByLabel(/Pages you visit and actions you take will be measured and used to improve the service/).check({force: true}); await page.getByLabel(/Our partners will still serve you ads, but they will not know you have visited out website/).check({force: true}); await page.locator('.privacy-banner__submit').click(); @@ -72,7 +72,7 @@ test.describe('Cookie banner > IFrame ', { tag: '@all'}, () => { await expect(iframes).toHaveCount(0); await page.getByLabel(/Pages you visit and actions you take will not be measured and used to improve the service/).check({force: true}); - await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check(); + await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check({force: true}); await page.locator('.privacy-banner__submit').click(); iframes = page.locator('iframe'); @@ -130,7 +130,7 @@ test.describe('Cookie banner > GA', { tag: '@all'}, () => { let GTMscript = page.locator('script[src*="googletagmanager"]'); await expect(GTMscript).toHaveCount(0); - await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check(); + await page.getByLabel(/Our partners might serve you ads knowing you have visited our website/).check({force: true}); await page.getByLabel(/Pages you visit and actions you take will not be measured and used to improve the service/).check({force: true}); await page.locator('.privacy-banner__submit').click(); @@ -144,7 +144,7 @@ test.describe('Cookie banner > GA', { tag: '@all'}, () => { let GTMscript = page.locator('script[src*="googletagmanager"]'); await expect(GTMscript).toHaveCount(0); - await page.getByLabel(/Pages you visit and actions you take will be measured and used to improve the service/).check(); + await page.getByLabel(/Pages you visit and actions you take will be measured and used to improve the service/).check({force: true}); await page.getByLabel(/Our partners will still serve you ads, but they will not know you have visited out website/).check({force: true}); await page.locator('.privacy-banner__submit').click(); From 2a48cf833aa2111bcb0e350469c5c17f99fb4d63 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 11:58:40 +0100 Subject: [PATCH 09/29] Adding wait for webkit --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 93c59409..3f602b13 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -84,6 +84,8 @@ test.describe('Cookie banner > Banner > Analytics', { tag: '@all'}, () => { test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { test('If the banner is open, focus should move there first', async ({ page }, testInfo) => { + //Webkit tests can be slow to load the banner, so we need to wait for it to be visible before pressing tab + await page.waitForSelector('.privacy-banner'); await page.keyboard.press(tabKey); const expectedClass = (testInfo.project.use.defaultBrowserType === 'webkit') ? /privacy-banner__accept/ : /privacy-banner__link/; await expect(page.locator(':focus')).toHaveClass(expectedClass); From 7130547e4bf1d42c20cca3df0c6cd56015317ad7 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 12:09:35 +0100 Subject: [PATCH 10/29] debug github tests --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 5 ++--- tools/playwright/config.base.js | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 3f602b13..96c0b645 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -17,7 +17,7 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { await expect(banner).toBeVisible(); }); - test('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { + test.only('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); const acceptAll = page.locator('.privacy-banner__accept').first(); @@ -25,6 +25,7 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { await acceptAll.click(); const cookies = await context.cookies(); + console.log(cookies); const preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); await expect(banner).not.toBeVisible(); @@ -84,8 +85,6 @@ test.describe('Cookie banner > Banner > Analytics', { tag: '@all'}, () => { test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { test('If the banner is open, focus should move there first', async ({ page }, testInfo) => { - //Webkit tests can be slow to load the banner, so we need to wait for it to be visible before pressing tab - await page.waitForSelector('.privacy-banner'); await page.keyboard.press(tabKey); const expectedClass = (testInfo.project.use.defaultBrowserType === 'webkit') ? /privacy-banner__accept/ : /privacy-banner__link/; await expect(page.locator(':focus')).toHaveClass(expectedClass); diff --git a/tools/playwright/config.base.js b/tools/playwright/config.base.js index c9c41a3b..54f879ff 100644 --- a/tools/playwright/config.base.js +++ b/tools/playwright/config.base.js @@ -3,7 +3,7 @@ const { devices } = require('@playwright/test'); module.exports = { testDir: './__tests__/playwright', fullyParallel: true, - forbidOnly: !!process.env.CI, + //forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: 'line', From ffdfcde0ceac1b8b6dedfb79cc69e00565f80a79 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 12:13:25 +0100 Subject: [PATCH 11/29] run just one failing test --- tools/playwright/config.base.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/playwright/config.base.js b/tools/playwright/config.base.js index 54f879ff..40ea6199 100644 --- a/tools/playwright/config.base.js +++ b/tools/playwright/config.base.js @@ -4,6 +4,7 @@ module.exports = { testDir: './__tests__/playwright', fullyParallel: true, //forbidOnly: !!process.env.CI, + forbidOnly: false, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: 'line', From 7bfdd2284e28a083e7ff424415c85556969423aa Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 14:04:52 +0100 Subject: [PATCH 12/29] debugging --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 3 +-- packages/cookie-banner/example/src/js/index.js | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 96c0b645..f90fed81 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -20,14 +20,13 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { test.only('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); const acceptAll = page.locator('.privacy-banner__accept').first(); + console.log(page.evaluate(() => window.location.hostname)); await expect(banner).toBeVisible(); await acceptAll.click(); const cookies = await context.cookies(); - console.log(cookies); const preferences = cookies.find((c) => c.name === '.Components.Dev.Consent'); - await expect(banner).not.toBeVisible(); expect(preferences.value).toEqual(btoa(`{"consent":{"performance":1,"ads":1}}`)); }); diff --git a/packages/cookie-banner/example/src/js/index.js b/packages/cookie-banner/example/src/js/index.js index 32239fff..3194c16d 100644 --- a/packages/cookie-banner/example/src/js/index.js +++ b/packages/cookie-banner/example/src/js/index.js @@ -1,5 +1,4 @@ import cookieBanner from "../../../src/index"; -import toggle from "../../../../toggle/src/index"; import sampleTemplates from "./sample-templates"; const config = { From a2e73c3ba1080ad560c94871d7b4b770ff78d0e1 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 14:09:45 +0100 Subject: [PATCH 13/29] debugging --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index f90fed81..00c2877a 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -20,7 +20,7 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { test.only('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); const acceptAll = page.locator('.privacy-banner__accept').first(); - console.log(page.evaluate(() => window.location.hostname)); + console.log(await page.evaluate(() => window.location.hostname)); await expect(banner).toBeVisible(); From 1d85a8d621e298ad68ccc41f65d713b2ea707978 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 14:18:45 +0100 Subject: [PATCH 14/29] debugging --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 00c2877a..0f5ff539 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -20,7 +20,7 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { test.only('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); const acceptAll = page.locator('.privacy-banner__accept').first(); - console.log(await page.evaluate(() => window.location.hostname)); + console.log("USING HOSTNAME: ", await page.evaluate(() => window.location.hostname)); await expect(banner).toBeVisible(); From a063fe2a87ae9c8af1c3d43bfc99a19be59386f3 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 14:45:44 +0100 Subject: [PATCH 15/29] Test non secure --- packages/cookie-banner/example/src/js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cookie-banner/example/src/js/index.js b/packages/cookie-banner/example/src/js/index.js index 3194c16d..248dd7a0 100644 --- a/packages/cookie-banner/example/src/js/index.js +++ b/packages/cookie-banner/example/src/js/index.js @@ -4,7 +4,7 @@ import sampleTemplates from "./sample-templates"; const config = { ...sampleTemplates, name: ".Components.Dev.Consent", - secure: true, + secure: false, euConsentTypes: { ad_storage: "ads", ad_user_data: "ads", From a7a65a3f4199731e3c3f5877f1bea421f66b1367 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 14:51:45 +0100 Subject: [PATCH 16/29] undo debuggong --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 3 +-- tools/playwright/config.base.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 0f5ff539..4cd06b53 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -17,10 +17,9 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { await expect(banner).toBeVisible(); }); - test.only('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { + test('Should hide the banner and update preferences when cookies are accepted', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); const acceptAll = page.locator('.privacy-banner__accept').first(); - console.log("USING HOSTNAME: ", await page.evaluate(() => window.location.hostname)); await expect(banner).toBeVisible(); diff --git a/tools/playwright/config.base.js b/tools/playwright/config.base.js index 40ea6199..c9c41a3b 100644 --- a/tools/playwright/config.base.js +++ b/tools/playwright/config.base.js @@ -3,8 +3,7 @@ const { devices } = require('@playwright/test'); module.exports = { testDir: './__tests__/playwright', fullyParallel: true, - //forbidOnly: !!process.env.CI, - forbidOnly: false, + forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: 'line', From b579e47b166fcfdef8ed896384cb93b282123222 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Wed, 2 Apr 2025 16:18:26 +0100 Subject: [PATCH 17/29] new tab trap test --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 4cd06b53..c14828c2 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -92,8 +92,7 @@ test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { for(let i = 0; i<=5; i++) { await page.keyboard.press(tabKey); } - const expectedClass = (testInfo.project.use.defaultBrowserType === 'webkit') ? /privacy-banner__reject/ : /privacy-banner__link/; - await expect(page.locator(':focus')).toHaveClass(expectedClass); + expect(await page.evaluate(() => document.querySelector('.privacy-banner').contains(document.querySelector(':focus')))).toBeTruthy(); }); test('Cookies can be accepted via keyboard', async ({ page, context }, testInfo) => { From 2df7ba76a8bd34fcfa8c7673da79b59c6ebad3b0 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 12:05:20 +0100 Subject: [PATCH 18/29] further test alterations --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index c14828c2..f11654f6 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -84,8 +84,7 @@ test.describe('Cookie banner > Banner > Analytics', { tag: '@all'}, () => { test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { test('If the banner is open, focus should move there first', async ({ page }, testInfo) => { await page.keyboard.press(tabKey); - const expectedClass = (testInfo.project.use.defaultBrowserType === 'webkit') ? /privacy-banner__accept/ : /privacy-banner__link/; - await expect(page.locator(':focus')).toHaveClass(expectedClass); + expect(await page.evaluate(() => document.querySelector('.privacy-banner').contains(document.querySelector(':focus')))).toBeTruthy(); }); test('If the banner is open and trapTab is set, focus should not leave the banner', async ({ page }, testInfo) => { From f7b46eb35b8ee3e59804bc571ac87c6c553ddb17 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 13:59:42 +0100 Subject: [PATCH 19/29] More test refactoring --- .../__tests__/playwright/banner.spec.js | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index f11654f6..ec0df9e9 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -10,6 +10,22 @@ test.beforeEach(async ({ page }, testInfo) => { : "Tab"; }); +const tabLoop = async (page) => { + let focussed = page.locator(':focus'); + + if(!await focussed.evaluate((el) => el.classList.contains('privacy-banner__accept'))) { + let maxTabCount = 10; // Prevent infinite loop in case of failure + + /*Keep tabbling until the accept button is focused*/ + /* Different browsers and environments require different numbers */ + do { + await page.keyboard.press(tabKey); + focussed = page.locator(':focus'); + maxTabCount--; + } while (await focussed.evaluate((el) => !el.classList.contains('privacy-banner__accept')) && maxTabCount > 0); + }; +} + test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { test('Should render the banner', async ({ page }) => { const banner = page.locator('.privacy-banner'); @@ -53,8 +69,6 @@ test.describe('Cookie banner > Banner > functionality', { tag: '@all'}, () => { await updateLink.click(); await expect(banner).toBeVisible(); }); - - }); test.describe('Cookie banner > Banner > Analytics', { tag: '@all'}, () => { @@ -82,25 +96,22 @@ test.describe('Cookie banner > Banner > Analytics', { tag: '@all'}, () => { }); test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { - test('If the banner is open, focus should move there first', async ({ page }, testInfo) => { + test('If the banner is open, focus should move there first', async ({ page }) => { await page.keyboard.press(tabKey); expect(await page.evaluate(() => document.querySelector('.privacy-banner').contains(document.querySelector(':focus')))).toBeTruthy(); }); - test('If the banner is open and trapTab is set, focus should not leave the banner', async ({ page }, testInfo) => { + test('If the banner is open and trapTab is set, focus should not leave the banner', async ({ page }) => { for(let i = 0; i<=5; i++) { await page.keyboard.press(tabKey); } expect(await page.evaluate(() => document.querySelector('.privacy-banner').contains(document.querySelector(':focus')))).toBeTruthy(); }); - test('Cookies can be accepted via keyboard', async ({ page, context }, testInfo) => { - const keyPresses = (testInfo.project.use.defaultBrowserType === 'webkit') ? 0 : 2; + test.only('Cookies can be accepted via keyboard', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); - - for(let i = 0; i<=keyPresses; i++) { - await page.keyboard.press(tabKey); - } + await page.keyboard.press(tabKey); + await tabLoop(page); await page.keyboard.press('Enter'); const cookies = await context.cookies(); @@ -110,13 +121,10 @@ test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { expect(preferences.value).toEqual(btoa(`{"consent":{"performance":1,"ads":1}}`)); }); - test('Cookies can be rejected via keyboard', async ({ page, context }, testInfo) => { - const keyPresses = (testInfo.project.use.defaultBrowserType === 'webkit') ? 1 : 3; + test('Cookies can be rejected via keyboard', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); - - for(let i = 0; i<=keyPresses; i++) { - await page.keyboard.press(tabKey); - } + await page.keyboard.press(tabKey); + await tabLoop(page); await page.keyboard.press('Enter'); const cookies = await context.cookies(); From e1676adb3402c2b5c236bb411eed20206f8d14a3 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 14:46:41 +0100 Subject: [PATCH 20/29] remove only --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index ec0df9e9..3a74d535 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -108,7 +108,7 @@ test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { expect(await page.evaluate(() => document.querySelector('.privacy-banner').contains(document.querySelector(':focus')))).toBeTruthy(); }); - test.only('Cookies can be accepted via keyboard', async ({ page, context }) => { + test('Cookies can be accepted via keyboard', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); await page.keyboard.press(tabKey); await tabLoop(page); From e8f3f6e66c06c2fa81ca3f1278ce969be0cffb23 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 16:05:16 +0100 Subject: [PATCH 21/29] test refactor --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 4 ++-- packages/cookie-banner/src/lib/ui.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 3a74d535..fd05a1d9 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -22,7 +22,7 @@ const tabLoop = async (page) => { await page.keyboard.press(tabKey); focussed = page.locator(':focus'); maxTabCount--; - } while (await focussed.evaluate((el) => !el.classList.contains('privacy-banner__accept')) && maxTabCount > 0); + } while ((await focussed.count() === 0 || await focussed.evaluate((el) => !el.classList.contains('privacy-banner__accept'))) && maxTabCount > 0); }; } @@ -108,7 +108,7 @@ test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { expect(await page.evaluate(() => document.querySelector('.privacy-banner').contains(document.querySelector(':focus')))).toBeTruthy(); }); - test('Cookies can be accepted via keyboard', async ({ page, context }) => { + test.only('Cookies can be accepted via keyboard', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); await page.keyboard.press(tabKey); await tabLoop(page); diff --git a/packages/cookie-banner/src/lib/ui.js b/packages/cookie-banner/src/lib/ui.js index b048d6d0..b8ad6ab3 100644 --- a/packages/cookie-banner/src/lib/ui.js +++ b/packages/cookie-banner/src/lib/ui.js @@ -115,6 +115,7 @@ const trapTab = state => event => { }; export const keyListener = store => event => { +console.log(event.keyCode); if (store.getState().banner && event.keyCode === 9) trapTab(store.getState())(event); }; From b78f17f2440414f1bb032dd7c9fb4d963cf8387e Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 16:05:30 +0100 Subject: [PATCH 22/29] remove debugging --- packages/cookie-banner/src/lib/ui.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cookie-banner/src/lib/ui.js b/packages/cookie-banner/src/lib/ui.js index b8ad6ab3..b048d6d0 100644 --- a/packages/cookie-banner/src/lib/ui.js +++ b/packages/cookie-banner/src/lib/ui.js @@ -115,7 +115,6 @@ const trapTab = state => event => { }; export const keyListener = store => event => { -console.log(event.keyCode); if (store.getState().banner && event.keyCode === 9) trapTab(store.getState())(event); }; From 9db8cc3cf891c513a9e2bc3ff529bfa2d38b506e Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 16:09:37 +0100 Subject: [PATCH 23/29] remove only flag --- .../__tests__/playwright/banner.spec.js | 4 ++-- .../__tests__/playwright/form.spec.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index fd05a1d9..005315ad 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -16,7 +16,7 @@ const tabLoop = async (page) => { if(!await focussed.evaluate((el) => el.classList.contains('privacy-banner__accept'))) { let maxTabCount = 10; // Prevent infinite loop in case of failure - /*Keep tabbling until the accept button is focused*/ + /*Keep tabbing until the accept button is focused*/ /* Different browsers and environments require different numbers */ do { await page.keyboard.press(tabKey); @@ -108,7 +108,7 @@ test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { expect(await page.evaluate(() => document.querySelector('.privacy-banner').contains(document.querySelector(':focus')))).toBeTruthy(); }); - test.only('Cookies can be accepted via keyboard', async ({ page, context }) => { + test('Cookies can be accepted via keyboard', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); await page.keyboard.press(tabKey); await tabLoop(page); diff --git a/packages/cookie-banner/__tests__/playwright/form.spec.js b/packages/cookie-banner/__tests__/playwright/form.spec.js index 10847bdf..cc682250 100644 --- a/packages/cookie-banner/__tests__/playwright/form.spec.js +++ b/packages/cookie-banner/__tests__/playwright/form.spec.js @@ -8,6 +8,22 @@ test.beforeEach(async ({ page }, testInfo) => { tabKey = testInfo.project.use.defaultBrowserType === "webkit" ? "Alt+Tab" : "Tab"; }); +const tabLoop = async (page) => { + let focussed = page.locator(':focus'); + + if(!await focussed.evaluate((el) => el.classList.contains('privacy-banner__accept'))) { + let maxTabCount = 10; // Prevent infinite loop in case of failure + + /*Keep tabbing until the accept button is focused*/ + /* Different browsers and environments require different numbers */ + do { + await page.keyboard.press(tabKey); + focussed = page.locator(':focus'); + maxTabCount--; + } while ((await focussed.count() === 0 || await focussed.evaluate((el) => !el.classList.contains('privacy-banner__accept'))) && maxTabCount > 0); + }; +} + test.describe("Cookie banner > Functionality", { tag: "@all" }, () => { test("Should not render the banner when the hideBannerOnFormPage has been used", async ({ page }) => { const banner = page.locator(".privacy-banner"); From 1d6986011f3c4d26bb4e4e81d3734bbf4966e9e3 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 16:21:10 +0100 Subject: [PATCH 24/29] Fixing tab loop --- .../cookie-banner/__tests__/playwright/banner.spec.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 005315ad..2c63f700 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -10,10 +10,10 @@ test.beforeEach(async ({ page }, testInfo) => { : "Tab"; }); -const tabLoop = async (page) => { +const tabLoop = async (page, selector) => { let focussed = page.locator(':focus'); - if(!await focussed.evaluate((el) => el.classList.contains('privacy-banner__accept'))) { + if(!await focussed.evaluate((el) => el.classList.contains(selector))) { let maxTabCount = 10; // Prevent infinite loop in case of failure /*Keep tabbing until the accept button is focused*/ @@ -22,7 +22,7 @@ const tabLoop = async (page) => { await page.keyboard.press(tabKey); focussed = page.locator(':focus'); maxTabCount--; - } while ((await focussed.count() === 0 || await focussed.evaluate((el) => !el.classList.contains('privacy-banner__accept'))) && maxTabCount > 0); + } while ((await focussed.count() === 0 || await focussed.evaluate((el) => !el.classList.contains(selector))) && maxTabCount > 0); }; } @@ -111,7 +111,7 @@ test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { test('Cookies can be accepted via keyboard', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); await page.keyboard.press(tabKey); - await tabLoop(page); + await tabLoop(page, 'privacy-banner__accept'); await page.keyboard.press('Enter'); const cookies = await context.cookies(); @@ -124,7 +124,7 @@ test.describe('Cookie banner > Banner > keyboard', { tag: '@all'}, () => { test('Cookies can be rejected via keyboard', async ({ page, context }) => { const banner = page.locator('.privacy-banner'); await page.keyboard.press(tabKey); - await tabLoop(page); + await tabLoop(page, 'privacy-banner__reject'); await page.keyboard.press('Enter'); const cookies = await context.cookies(); From 9ef24446a1118e5c69895788eb519690cf69b449 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 16:21:36 +0100 Subject: [PATCH 25/29] remove funciton --- .../__tests__/playwright/form.spec.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/form.spec.js b/packages/cookie-banner/__tests__/playwright/form.spec.js index cc682250..10847bdf 100644 --- a/packages/cookie-banner/__tests__/playwright/form.spec.js +++ b/packages/cookie-banner/__tests__/playwright/form.spec.js @@ -8,22 +8,6 @@ test.beforeEach(async ({ page }, testInfo) => { tabKey = testInfo.project.use.defaultBrowserType === "webkit" ? "Alt+Tab" : "Tab"; }); -const tabLoop = async (page) => { - let focussed = page.locator(':focus'); - - if(!await focussed.evaluate((el) => el.classList.contains('privacy-banner__accept'))) { - let maxTabCount = 10; // Prevent infinite loop in case of failure - - /*Keep tabbing until the accept button is focused*/ - /* Different browsers and environments require different numbers */ - do { - await page.keyboard.press(tabKey); - focussed = page.locator(':focus'); - maxTabCount--; - } while ((await focussed.count() === 0 || await focussed.evaluate((el) => !el.classList.contains('privacy-banner__accept'))) && maxTabCount > 0); - }; -} - test.describe("Cookie banner > Functionality", { tag: "@all" }, () => { test("Should not render the banner when the hideBannerOnFormPage has been used", async ({ page }) => { const banner = page.locator(".privacy-banner"); From f621f05c69f224cebd6eddd9e76381ed5c9dc7f0 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 16:29:34 +0100 Subject: [PATCH 26/29] debugging --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 2c63f700..65d9f582 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -22,7 +22,7 @@ const tabLoop = async (page, selector) => { await page.keyboard.press(tabKey); focussed = page.locator(':focus'); maxTabCount--; - } while ((await focussed.count() === 0 || await focussed.evaluate((el) => !el.classList.contains(selector))) && maxTabCount > 0); + } while ((await focussed.count() === 0 || await focussed.evaluate((el, selector) => !el.classList.contains(selector))) && maxTabCount > 0); }; } From a4f986e9046f13817589ed2dcf250b3ee6b7c864 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 16:31:11 +0100 Subject: [PATCH 27/29] debugging --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 65d9f582..e04f5cd4 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -22,7 +22,7 @@ const tabLoop = async (page, selector) => { await page.keyboard.press(tabKey); focussed = page.locator(':focus'); maxTabCount--; - } while ((await focussed.count() === 0 || await focussed.evaluate((el, selector) => !el.classList.contains(selector))) && maxTabCount > 0); + } while ((await focussed.count() === 0 || await focussed.evaluate((el, selector) => !el.classList.contains(selector), selector)) && maxTabCount > 0); }; } From b9005648439824ca980b7f6cd94a128a640ec890 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 18:34:36 +0100 Subject: [PATCH 28/29] debugging --- packages/cookie-banner/__tests__/playwright/banner.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index e04f5cd4..1e23c586 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -13,7 +13,7 @@ test.beforeEach(async ({ page }, testInfo) => { const tabLoop = async (page, selector) => { let focussed = page.locator(':focus'); - if(!await focussed.evaluate((el) => el.classList.contains(selector))) { + if(!await focussed.evaluate((el) => el.classList.contains(selector), selector)) { let maxTabCount = 10; // Prevent infinite loop in case of failure /*Keep tabbing until the accept button is focused*/ From 6f0deff54a89fa7d8a30d345c6821281993ece61 Mon Sep 17 00:00:00 2001 From: Sarah Richards Date: Thu, 3 Apr 2025 18:45:15 +0100 Subject: [PATCH 29/29] More debugging --- .../cookie-banner/__tests__/playwright/banner.spec.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/cookie-banner/__tests__/playwright/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js index 1e23c586..88be68f0 100644 --- a/packages/cookie-banner/__tests__/playwright/banner.spec.js +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -13,7 +13,9 @@ test.beforeEach(async ({ page }, testInfo) => { const tabLoop = async (page, selector) => { let focussed = page.locator(':focus'); - if(!await focussed.evaluate((el) => el.classList.contains(selector), selector)) { + if(!await focussed.evaluate((el, selector) => { + return el.classList.contains(selector); + }, selector)) { let maxTabCount = 10; // Prevent infinite loop in case of failure /*Keep tabbing until the accept button is focused*/ @@ -22,7 +24,9 @@ const tabLoop = async (page, selector) => { await page.keyboard.press(tabKey); focussed = page.locator(':focus'); maxTabCount--; - } while ((await focussed.count() === 0 || await focussed.evaluate((el, selector) => !el.classList.contains(selector), selector)) && maxTabCount > 0); + } while ((await focussed.count() === 0 || await focussed.evaluate((el, selector) => { + return !el.classList.contains(selector); + }, selector)) && maxTabCount > 0); }; }