diff --git a/packages/cookie-banner/__tests__/analytics/index.js b/packages/cookie-banner/__tests__/analytics/index.js deleted file mode 100644 index 54a146db..00000000 --- a/packages/cookie-banner/__tests__/analytics/index.js +++ /dev/null @@ -1,61 +0,0 @@ -import cookieBanner from '../../src'; -import sampleTemplates from '../../example/src/js/sample-templates'; -import defaults from '../../src/lib/defaults'; -let instance; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - instance = cookieBanner({ - ...sampleTemplates, - 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__/banner/index.js b/packages/cookie-banner/__tests__/banner/index.js deleted file mode 100644 index e8e0f74c..00000000 --- a/packages/cookie-banner/__tests__/banner/index.js +++ /dev/null @@ -1,99 +0,0 @@ -import sampleTemplates from '../../example/src/js/sample-templates'; -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - cookieBanner({ - ...sampleTemplates, - 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__/cookies.js b/packages/cookie-banner/__tests__/cookies.js deleted file mode 100644 index 46ea343a..00000000 --- a/packages/cookie-banner/__tests__/cookies.js +++ /dev/null @@ -1,55 +0,0 @@ -import sampleTemplates from '../example/src/js/sample-templates'; -import cookieBanner from '../src'; -import defaults from '../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - ...sampleTemplates, - 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/interactions.js b/packages/cookie-banner/__tests__/form/interactions.js deleted file mode 100644 index 96e22402..00000000 --- a/packages/cookie-banner/__tests__/form/interactions.js +++ /dev/null @@ -1,66 +0,0 @@ -import sampleTemplates from '../../example/src/js/sample-templates'; -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({ - ...sampleTemplates, - 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__/form/not-render.js deleted file mode 100644 index c7b7ebcc..00000000 --- a/packages/cookie-banner/__tests__/form/not-render.js +++ /dev/null @@ -1,28 +0,0 @@ -import sampleTemplates from '../../example/src/js/sample-templates'; -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -describe(`Cookie banner > DOM > form > not render`, () => { - document.body.innerHTML = `
`; - cookieBanner({ - ...sampleTemplates, - 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__/form/render.js deleted file mode 100644 index 33f371be..00000000 --- a/packages/cookie-banner/__tests__/form/render.js +++ /dev/null @@ -1,56 +0,0 @@ -import sampleTemplates from '../../example/src/js/sample-templates'; -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -describe(`Cookie banner > DOM > form > render`, () => { - beforeAll(() => { - document.body.innerHTML = `
`; - cookieBanner({ - ...sampleTemplates, - 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__/google-eu-consent/index.js deleted file mode 100644 index 0e8acfa8..00000000 --- a/packages/cookie-banner/__tests__/google-eu-consent/index.js +++ /dev/null @@ -1,67 +0,0 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; -import sampleTemplates from '../../example/src/js/sample-templates'; - -/* eslint-disable camelcase */ -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - ...sampleTemplates, - 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__/google-eu-consent/no-eu-consent-config.js deleted file mode 100644 index 76637377..00000000 --- a/packages/cookie-banner/__tests__/google-eu-consent/no-eu-consent-config.js +++ /dev/null @@ -1,47 +0,0 @@ -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; -import sampleTemplates from '../../example/src/js/sample-templates'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - ...sampleTemplates, - 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__/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__/form/api.js b/packages/cookie-banner/__tests__/jest/render-form.js similarity index 97% rename from packages/cookie-banner/__tests__/form/api.js rename to packages/cookie-banner/__tests__/jest/render-form.js index 1116c09b..9064d3b4 100644 --- a/packages/cookie-banner/__tests__/form/api.js +++ b/packages/cookie-banner/__tests__/jest/render-form.js @@ -1,47 +1,47 @@ -import sampleTemplates from '../../example/src/js/sample-templates'; -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({ - ...sampleTemplates, - 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'; +import sampleTemplates from '../../example/src/js/sample-templates'; + +describe(`Cookie banner > DOM > form > render by api`, () => { + + it('Should render the form via the API', async () => { + document.body.innerHTML = `
`; + const instance = cookieBanner({ + ...sampleTemplates, + 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__/banner/showBanner.js b/packages/cookie-banner/__tests__/jest/show-banner.js similarity index 97% rename from packages/cookie-banner/__tests__/banner/showBanner.js rename to packages/cookie-banner/__tests__/jest/show-banner.js index c66d5297..25784427 100644 --- a/packages/cookie-banner/__tests__/banner/showBanner.js +++ b/packages/cookie-banner/__tests__/jest/show-banner.js @@ -1,67 +1,67 @@ -import sampleTemplates from '../../example/src/js/sample-templates'; -import cookieBanner from '../../src'; -import defaults from '../../src/lib/defaults'; - -let instance; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - instance = cookieBanner({ - ...sampleTemplates, - 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'; +import sampleTemplates from '../../example/src/js/sample-templates'; + +let instance; + +const init = () => { + // Set up our document body + document.body.innerHTML = `
`; + instance = cookieBanner({ + ...sampleTemplates, + 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__/state.js b/packages/cookie-banner/__tests__/jest/state.js similarity index 94% rename from packages/cookie-banner/__tests__/state.js rename to packages/cookie-banner/__tests__/jest/state.js index 2d3c7d85..707e941d 100644 --- a/packages/cookie-banner/__tests__/state.js +++ b/packages/cookie-banner/__tests__/jest/state.js @@ -1,143 +1,143 @@ -import cookieBanner from '../src'; -import sampleTemplates from '../example/src/js/sample-templates'; -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({ ...sampleTemplates, 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'; +import sampleTemplates from '../../example/src/js/sample-templates'; + +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({ ...sampleTemplates, 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 94% rename from packages/cookie-banner/__tests__/utils.js rename to packages/cookie-banner/__tests__/jest/utils.js index 61810af7..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 value 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/banner.spec.js b/packages/cookie-banner/__tests__/playwright/banner.spec.js new file mode 100644 index 00000000..88be68f0 --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/banner.spec.js @@ -0,0 +1,157 @@ +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"; +}); + +const tabLoop = async (page, selector) => { + let focussed = page.locator(':focus'); + + 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*/ + /* 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, selector) => { + return !el.classList.contains(selector); + }, selector)) && maxTabCount > 0); + }; +} + +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}}`)); + }); + + + 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(); + }); +}); + +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 }) => { + 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 }) => { + 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 }) => { + const banner = page.locator('.privacy-banner'); + await page.keyboard.press(tabKey); + await tabLoop(page, 'privacy-banner__accept'); + + 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 }) => { + const banner = page.locator('.privacy-banner'); + await page.keyboard.press(tabKey); + await tabLoop(page, 'privacy-banner__reject'); + + 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'}, () => { + 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([]); + }); +}); 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..10847bdf --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/form.spec.js @@ -0,0 +1,115 @@ +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"; +}); + +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}}`)); + }); +}); + +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/google-eu-consent.spec.js b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js new file mode 100644 index 00000000..12e2958c --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/google-eu-consent.spec.js @@ -0,0 +1,66 @@ +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('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', + '2': { + ad_storage: 'denied', + ad_user_data: 'denied', + ad_personalization: 'denied', + analytics_storage: 'denied', + wait_for_update: 500 + } + }; + expect(dataLayer.find(e => deepEqual(e, expectedConsent))).toBeDefined(); + }); + + 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', + } + }; + + await acceptAll.click(); + const dataLayer = await page.evaluate(() => window.dataLayer); + expect(dataLayer.find(e => deepEqual(e, updatedConsent))).toBeDefined(); + }); + + 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(); + }); +}); 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..289fad32 --- /dev/null +++ b/packages/cookie-banner/__tests__/playwright/utils.spec.js @@ -0,0 +1,155 @@ +const { test, expect } = require('@playwright/test'); + +test.beforeEach(async ({ page }) => { + await page.goto('/'); +}); + + +test.describe('Cookie banner > IFrame ', { tag: '@all'}, () => { + 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({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(); + + 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({force: true}); + await page.locator('.privacy-banner__submit').click(); + + iframes = page.locator('iframe'); + expect(await iframes.count()).toBeGreaterThan(0); + }); + +}); + +test.describe('Cookie banner > GA', { tag: '@all'}, () => { + 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({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(); + + 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({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(); + + GTMscript = page.locator('script[src*="googletagmanager"]'); + await expect(GTMscript).toHaveCount(1); + }); +}); + diff --git a/packages/cookie-banner/__tests__/reject.js b/packages/cookie-banner/__tests__/reject.js deleted file mode 100644 index 5950a4bd..00000000 --- a/packages/cookie-banner/__tests__/reject.js +++ /dev/null @@ -1,49 +0,0 @@ -import sampleTemplates from '../example/src/js/sample-templates'; -import cookieBanner from '../src'; -import defaults from '../src/lib/defaults'; - -const init = () => { - // Set up our document body - document.body.innerHTML = `
`; - window.__cb__ = cookieBanner({ - ...sampleTemplates, - 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/example/src/form.html b/packages/cookie-banner/example/src/form.html new file mode 100644 index 00000000..ebde0a61 --- /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 32be4d83..92e3b041 100644 --- a/packages/cookie-banner/example/src/index.html +++ b/packages/cookie-banner/example/src/index.html @@ -1,60 +1,74 @@ - - + + StormID + - - -
-
-
-

Update your cookie preferences to view this content.

- -
+ + + +
+

Cookie banner example

+
+
+

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/js/index.js b/packages/cookie-banner/example/src/js/index.js index 9d9ccc4c..248dd7a0 100644 --- a/packages/cookie-banner/example/src/js/index.js +++ b/packages/cookie-banner/example/src/js/index.js @@ -1,97 +1,50 @@ -import cookieBanner from '../../../src/index'; -import toggle from '../../../../toggle/src/index'; -import SampleTemplates from './sample-templates'; +import cookieBanner from "../../../src/index"; +import sampleTemplates from "./sample-templates"; -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 = { + ...sampleTemplates, + name: ".Components.Dev.Consent", + secure: false, + 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()], + }, + }, }; - -const config = {...SampleTemplates, - name: '.Components.Dev.Consent', - secure: false, - euConsentTypes: { - ad_storage: 'ads', - ad_user_data: 'ads', - ad_personalization: 'ads', - analytics_storage: 'performance' - }, - hideBannerOnFormPage: false, - trapTab: true, - necessary: [ - () => { - writeCookie({ - settings: { - name: '.Test.NecessaryCookie', - expiry: 3 - }, - consent: '666', - }); - } - ], - 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: [ - () => { - // console.log('Performance fn'); - writeCookie({ - settings: { - name: '.Test.PerformanceCookie', - expiry: 3 - }, - consent: '666', - }); - }, - 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: [ - () => { - // console.log('Ads fn'); - writeCookie({ - settings: { - name: '.Test.AdsCookie', - expiry: 3 - }, - consent: '666', - }); - } - ] - } - } -}; - -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(); + }) + ); +}); 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..0968cfa7 --- /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://localhost:${server.devServer.port}/`, + }, + webServer: { + ...baseConfig.webServer, + url: `http://localhost:${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 87% rename from packages/cookie-banner/example/webpack.config.js rename to packages/cookie-banner/tools/webpack.config.js index a2d72d75..5d69257f 100644 --- a/packages/cookie-banner/example/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/tools/playwright/config.base.js b/tools/playwright/config.base.js index 1fbf77e3..c9c41a3b 100644 --- a/tools/playwright/config.base.js +++ b/tools/playwright/config.base.js @@ -27,7 +27,6 @@ module.exports = { use: { ...devices['Desktop Firefox'] }, grep: /@desktop|@all/, }, - { name: 'webkit', userAgent: 'Safari',