diff --git a/docs/cookie-banner.html b/docs/cookie-banner.html index cdb9faba..67a5d4b5 100644 --- a/docs/cookie-banner.html +++ b/docs/cookie-banner.html @@ -197,13 +197,20 @@

Cookie banner

GDPR compliant cookie banner and consent form.

Renders a cookie banner and a consent form based on configuration settings, and conditionally invokes cookie-reliant functionality based on user consent.

-

Optionally send anonymous predefined cookie banner and consent form interaction measurements to a specified Google Analytics using the Google Measurement API.


Usage

Cookie consent is based on categorising cookies and the functions that initialise them, describing them in a configuration object passed into the module at initialisition.

The cookie banner renders itself if no consent preferences are recorded in the browser.

The consent form renders into a DOMElement with a particular className configurable options (classNames.formContainer).

A page containing a cookie consent form should include a visually hidden live region (role=alert) with a particular className (classNames.formAnnouncement), default: ‘privacy-banner__form-announcement’.

+

Optionally the banner also supports basic Google EU consent mode [https://developers.google.com/tag-platform/security/guides/consent?consentmode=basic], and can push user consent preferences to the dataLayer for Google libraries to use. All that is necessary to suport Google consent mode is to map Google consent categories to the cookie categories in the configuration.

+

For example, to map the ad_storage, ad_user_data, and ad_personalisation to an ‘ads’ consent category defined in the banner config, add a euConsentTypes object to the configuration like this:

+
euConsentTypes: {
+    ad_storage: 'test',
+    ad_user_data: 'test',
+    ad_personalization: 'test'
+}
+

Install the package

npm i -S @stormid/cookie-banner
 
@@ -248,38 +255,7 @@

Usage

state => state.utils.gtmSnippet(<UA-CODE>) ] } - } -}); - -

Options

-
{
-    name: '.CookiePreferences', //name of the cookie set to record user consent
-    path: '/', //path of the preferences cookie
-    domain: window.location.hostname === 'localhost' ? '' : `.${removeSubdomain(window.location.hostname)}`, //domain of the preferences cookie, defaults to .<root-domain>
-    secure: true, //preferences cookie secure
-    samesite: 'lax', //preferences cookie samesite
-    expiry: 365, //preferences cookie expiry in days
-    types: {}, //types of cookie-dependent functionality 
-    necessary: [], //cookie-dependent functionality that will always execute, for convenience only
-    policyURL: '/cookie-policy#preferences', //URL to cookie policy page (location of cookie consent form) rendered in the banner
-    classNames: {
-        banner: 'privacy-banner',
-        acceptBtn: 'privacy-banner__accept',
-        rejectBtn: 'privacy-banner__reject',
-        submitBtn: 'privacy-banner__submit',
-        field: 'privacy-banner__field',
-        form: 'privacy-banner__form',
-        fieldset: 'privacy-banner__fieldset',
-        legend: 'privacy-banner__legend',
-        formContainer: 'privacy-banner__form-container', //where the form is rendered
-        formMessage: 'privacy-banner__form-msg',
-        formAnnouncement: 'privacy-banner__form-announcement', //screen reader announcement
-        title: 'privacy-banner__form-title',
-        description: 'privacy-banner__form-description'
     },
-    hideBannerOnFormPage: false, //don't show the banner when the user is on the same page as a consent form
-    savedMessage: 'Your settings have been saved.', //displayed after consent form update,
-    trapTab: false, //trap the user's keyboard tab within the banner when open
     bannerTemplate(model){
         return `<section role="dialog" aria-live="polite" aria-label="Your privacy" class="${model.classNames.banner}">
             <div class="privacy-content">
@@ -288,18 +264,19 @@ 

Options

<div class="privacy-banner__title">Cookies</div> <p>We use cookies to improve your experience on our site and show you personalised advertising.</p> <p>Find out more from our <a class="privacy-banner__link" rel="noopener noreferrer nofollow" href="/privacy-policy">privacy policy</a> and <a class="privacy-banner__link" rel="noopener noreferrer nofollow" href="${model.policyURL}">cookie policy</a>.</p> - <button class="btn btn--primary ${model.classNames.acceptBtn}">Accept and close</button> - <a class="privacy-banner__link" rel="noopener noreferrer nofollow" href="${model.policyURL}">Your options</a> + <button type="button" class="btn btn--primary ${model.classNames.acceptBtn}">Accept all</button> + <button type="button" class="btn btn--primary ${model.classNames.rejectBtn}">Reject all</button> + <a class="privacy-banner__link ${model.classNames.optionsBtn}" rel="noopener noreferrer nofollow" href="${model.policyURL}">Your options</a> <!--googleon: all--> </div> </div> </section>`; }, messageTemplate(model){ - return `<div class="${model.settings.classNames.formMessage}" aria-role="alert">${model.settings.savedMessage}</div>` + return `<div class="${model.settings.classNames.formMessage}" aria-hidden="true">${model.settings.savedMessage}</div>` }, formTemplate(model){ - return `<form id="preferences" class="${model.settings.classNames.form}" novalidate> + return `<form id="preferences" class="${model.settings.classNames.form}" novalidate> ${Object.keys(model.settings.types).map(type => `<fieldset class="${model.settings.classNames.fieldset}"> <legend class="${model.settings.classNames.legend}"> <span class="${model.settings.classNames.title}">${model.settings.types[type].title}</span> @@ -313,8 +290,44 @@

Options

type="radio" name="privacy-${type.split(' ')[0].replace(' ', '-')}" value="1" - ${model.consent[type] === 1 ? ` checked` : ''}> - <span class="privacy-banner__label-text">I am OK with this</span> + ${model.consent[type] === 1 ? `checked` : ''}> + <span class="privacy-banner__label-text&qureturn `<form id="preferences" class="${model.settings.classNames.form}" novalidate> + ${Object.keys(model.settings.types).map(type => `<fieldset class="${model.settings.classNames.fieldset}"> + <legend class="${model.settings.classNames.legend}"> + <span class="${model.settings.classNames.title}">${model.settings.types[type].title}</span> + <span class="${model.settings.classNames.description}">${model.settings.types[type].description}</span> + </legend> + <div class="form-row"> + <div class="relative"> + <label class="privacy-banner__label"> + <input + class="${model.settings.classNames.field}" + type="radio" + name="privacy-${type.split(' ')[0].replace(' ', '-')}" + value="1" + ${model.consent[type] === 1 ? `checked` : ''}> + <span class="privacy-banner__label-text">I am OK with this</span> + <span class="privacy-banner__label-description">${model.settings.types[type].labels.yes}</span> + </label> + </div> + </div> + <div class="form-row"> + <div class="relative"> + <label class="privacy-banner__label"> + <input + class="${model.settings.classNames.field}" + type="radio" + name="privacy-${type.split(' ')[0].replace(' ', '-')}" + value="0" + ${model.consent[type] === 0 ? `checked` : ''}> + <span class="privacy-banner__label-text">No thank you</span> + <span class="privacy-banner__label-description">${model.settings.types[type].labels.no}</span> + </label> + </div> + </div> +</fieldset>`).join('')} +<button class="${model.settings.classNames.submitBtn}"${Object.keys(model.consent).length !== Object.keys(model.settings.types).length ? ` disabled` : ''}>Save my settings</button> +</form>`;ot;>I am OK with this</span> <span class="privacy-banner__label-description">${model.settings.types[type].labels.yes}</span> </label> </div> @@ -327,16 +340,53 @@

Options

type="radio" name="privacy-${type.split(' ')[0].replace(' ', '-')}" value="0" - ${model.consent[type] === 0 ? ` checked` : ''}> + ${model.consent[type] === 0 ? `checked` : ''}> <span class="privacy-banner__label-text">No thank you</span> <span class="privacy-banner__label-description">${model.settings.types[type].labels.no}</span> </label> </div> </div> </fieldset>`).join('')} - <button class="${model.settings.classNames.submitBtn}"${Object.keys(model.consent).length === 0 ? ` disabled` : ''}>Save my settings</button> + <button class="${model.settings.classNames.submitBtn}"${Object.keys(model.consent).length !== Object.keys(model.settings.types).length ? ` disabled` : ''}>Save my settings</button> </form>`; } +}); +
+

Options

+
{
+    name: '.CookiePreferences', //name of the cookie set to record user consent
+    path: '/', //path of the preferences cookie
+    domain: window.location.hostname === 'localhost' ? '' : `.${removeSubdomain(window.location.hostname)}`, //domain of the preferences cookie, defaults to .<root-domain>
+    secure: true, //preferences cookie secure
+    samesite: 'lax', //preferences cookie samesite
+    expiry: 365, //preferences cookie expiry in days
+    types: {}, //types of cookie-dependent functionality
+    euConsentTypes: {}, //map Google EU consent categories to types of cookie defined in 'types'
+    necessary: [], //cookie-dependent functionality that will always execute, for convenience only
+    policyURL: '/cookie-policy#preferences', //URL to cookie policy page (location of cookie consent form) rendered in the banner
+    classNames: {
+        banner: 'privacy-banner',
+        acceptBtn: 'privacy-banner__accept',
+        rejectBtn: 'privacy-banner__reject',
+        submitBtn: 'privacy-banner__submit',
+        field: 'privacy-banner__field',
+        form: 'privacy-banner__form',
+        fieldset: 'privacy-banner__fieldset',
+        legend: 'privacy-banner__legend',
+        formContainer: 'privacy-banner__form-container', //where the form is rendered
+        formMessage: 'privacy-banner__form-msg',
+        formAnnouncement: 'privacy-banner__form-announcement', //screen reader announcement
+        title: 'privacy-banner__form-title',
+        description: 'privacy-banner__form-description'
+    },
+    hideBannerOnFormPage: false, //don't show the banner when the user is on the same page as a consent form
+    savedMessage: 'Your settings have been saved.', //displayed after consent form update,
+    trapTab: false, //trap the user's keyboard tab within the banner when open
+    bannerTemplate: null, //a function which returns the HTML string for the banner.  There is no default for this since if varies significantly from project to project. **This option is mandatory** - the banner will not initialise if this is not provided. See example configration above.
+    formTemplate: null, //a function which returns the HTML string for the preferences form.  There is no default for this since it varies significantly from project to project. **This option is mandatory** - the banner will not initialise if this is not provided.  See example configration above.
+    messageTemplate(model){ 
+       return `<div class="${model.settings.classNames.formMessage}" aria-hidden="true">${model.settings.savedMessage}</div>`
+    } //A function which returns an HTML string to create the confirmation message.  Default HTML is provided as above.
 }
 

Utility functions

diff --git a/docs/tabs.html b/docs/tabs.html index f82734ae..65fcc80e 100644 --- a/docs/tabs.html +++ b/docs/tabs.html @@ -240,17 +240,27 @@

Options

focusOnLoad: true //a boolean to set whether the page should focus on the first tab after loading } -

API

-

tabs() returns an array of instances. Each instance exposes the interface

-
{
-    getState, a Function that returns the current state Object
-}
+

Setting the active tab

+
On page load the active tab will be set by (in order of precedence):
+1. The page hash.  If the page hash in the address bar matches the ID of a panel, it will be activated on page load
+2. The data-active-index attribute.  If the tabs node found to have a <pre>data-active-index</pre> attribute, that tab will be activated on page load.  This is a zero-based index.   
+3. The tab specified by the activeIndex in the settings. This is a zero-based index.
+4. The first tab in the set.
+
+## API
+
+tabs() returns an array of instances. Each instance exposes the interface
 
-

Tests

-
npm t
+

{ +getState, a Function that returns the current state Object +}

+

+## Tests
 
-

License

-

MIT

+

npm t

+

+## License
+MIT
diff --git a/packages/cookie-banner/README.md b/packages/cookie-banner/README.md index 231cb2c4..b64f346a 100644 --- a/packages/cookie-banner/README.md +++ b/packages/cookie-banner/README.md @@ -79,41 +79,7 @@ const cookieBanner = banner({ state => state.utils.gtmSnippet() ] } - } -}); -``` - -## Options -``` -{ - name: '.CookiePreferences', //name of the cookie set to record user consent - path: '/', //path of the preferences cookie - domain: window.location.hostname === 'localhost' ? '' : `.${removeSubdomain(window.location.hostname)}`, //domain of the preferences cookie, defaults to . - secure: true, //preferences cookie secure - samesite: 'lax', //preferences cookie samesite - expiry: 365, //preferences cookie expiry in days - types: {}, //types of cookie-dependent functionality - euConsentTypes: {}, //map Google EU consent categories to types of cookie defined in 'types' - necessary: [], //cookie-dependent functionality that will always execute, for convenience only - policyURL: '/cookie-policy#preferences', //URL to cookie policy page (location of cookie consent form) rendered in the banner - classNames: { - banner: 'privacy-banner', - acceptBtn: 'privacy-banner__accept', - rejectBtn: 'privacy-banner__reject', - submitBtn: 'privacy-banner__submit', - field: 'privacy-banner__field', - form: 'privacy-banner__form', - fieldset: 'privacy-banner__fieldset', - legend: 'privacy-banner__legend', - formContainer: 'privacy-banner__form-container', //where the form is rendered - formMessage: 'privacy-banner__form-msg', - formAnnouncement: 'privacy-banner__form-announcement', //screen reader announcement - title: 'privacy-banner__form-title', - description: 'privacy-banner__form-description' }, - hideBannerOnFormPage: false, //don't show the banner when the user is on the same page as a consent form - savedMessage: 'Your settings have been saved.', //displayed after consent form update, - trapTab: false, //trap the user's keyboard tab within the banner when open bannerTemplate(model){ return ``; }, messageTemplate(model){ - return `
${model.settings.savedMessage}
` + return `` }, formTemplate(model){ - return `
+ return ` ${Object.keys(model.settings.types).map(type => `
${model.settings.types[type].title} @@ -147,7 +114,7 @@ const cookieBanner = banner({ type="radio" name="privacy-${type.split(' ')[0].replace(' ', '-')}" value="1" - ${model.consent[type] === 1 ? ` checked` : ''}> + ${model.consent[type] === 1 ? `checked` : ''}> I am OK with this ${model.settings.types[type].labels.yes} @@ -161,18 +128,64 @@ const cookieBanner = banner({ type="radio" name="privacy-${type.split(' ')[0].replace(' ', '-')}" value="0" - ${model.consent[type] === 0 ? ` checked` : ''}> + ${model.consent[type] === 0 ? `checked` : ''}> No thank you ${model.settings.types[type].labels.no}
`).join('')} - +
`; } +}); +``` + +## Options +``` +{ + name: '.CookiePreferences', //name of the cookie set to record user consent + path: '/', //path of the preferences cookie + domain: window.location.hostname === 'localhost' ? '' : `.${removeSubdomain(window.location.hostname)}`, //domain of the preferences cookie, defaults to . + secure: true, //preferences cookie secure + samesite: 'lax', //preferences cookie samesite + expiry: 365, //preferences cookie expiry in days + types: {}, //types of cookie-dependent functionality + euConsentTypes: {}, //map Google EU consent categories to types of cookie defined in 'types' + necessary: [], //cookie-dependent functionality that will always execute, for convenience only + policyURL: '/cookie-policy#preferences', //URL to cookie policy page (location of cookie consent form) rendered in the banner + classNames: { + banner: 'privacy-banner', + acceptBtn: 'privacy-banner__accept', + rejectBtn: 'privacy-banner__reject', + submitBtn: 'privacy-banner__submit', + field: 'privacy-banner__field', + form: 'privacy-banner__form', + fieldset: 'privacy-banner__fieldset', + legend: 'privacy-banner__legend', + formContainer: 'privacy-banner__form-container', //where the form is rendered + formMessage: 'privacy-banner__form-msg', + formAnnouncement: 'privacy-banner__form-announcement', //screen reader announcement + title: 'privacy-banner__form-title', + description: 'privacy-banner__form-description' + }, + hideBannerOnFormPage: false, //don't show the banner when the user is on the same page as a consent form + savedMessage: 'Your settings have been saved.', //displayed after consent form update, + trapTab: false, //trap the user's keyboard tab within the banner when open + bannerTemplate: null, //**This option is mandatory** - the banner will not initialise if this is not provided. See below. + formTemplate: null, //**This option is mandatory** - the banner will not initialise if this is not provided. See below. + messageTemplate(model){ + return `` + } //A function which returns an HTML string to create the confirmation message. Default HTML is provided as above. } ``` +## HTML templates + +When using the cookie banner, you **must** provide suitable HTML templates for both the banner and the preferences form. These should set via the config as the bannerTemplate and formTemplate options respectively. + +The templates should take the form of a function which returns a valid HTML string. The functions will be passed a 'model' which will expose the state of the cookie banner to help with rendering. See the example config above as a startring point. + +If these functions are not provided, the cookie banner will fail to initialise. ## Utility functions There are two utility functions provided by the library designed to be invoked following user consent. diff --git a/packages/cookie-banner/__tests__/banner/index.js b/packages/cookie-banner/__tests__/banner/index.js index 68ff38a2..c9e88b55 100644 --- a/packages/cookie-banner/__tests__/banner/index.js +++ b/packages/cookie-banner/__tests__/banner/index.js @@ -1,3 +1,4 @@ +import sampleTemplates from '../../example/src/js/sample-templates'; import cookieBanner from '../../src'; import defaults from '../../src/lib/defaults'; @@ -5,6 +6,7 @@ const init = () => { // Set up our document body document.body.innerHTML = `
`; cookieBanner({ + ...sampleTemplates, secure: false, hideBannerOnFormPage: false, types: { diff --git a/packages/cookie-banner/__tests__/banner/showBanner.js b/packages/cookie-banner/__tests__/banner/showBanner.js index 04ed3741..2c7fe179 100644 --- a/packages/cookie-banner/__tests__/banner/showBanner.js +++ b/packages/cookie-banner/__tests__/banner/showBanner.js @@ -1,3 +1,4 @@ +import sampleTemplates from '../../example/src/js/sample-templates'; import cookieBanner from '../../src'; import defaults from '../../src/lib/defaults'; @@ -7,6 +8,7 @@ const init = () => { // Set up our document body document.body.innerHTML = `
`; instance = cookieBanner({ + ...sampleTemplates, secure: false, types: { test: { diff --git a/packages/cookie-banner/__tests__/cookies.js b/packages/cookie-banner/__tests__/cookies.js index 09e30f0d..46ea343a 100644 --- a/packages/cookie-banner/__tests__/cookies.js +++ b/packages/cookie-banner/__tests__/cookies.js @@ -1,3 +1,4 @@ +import sampleTemplates from '../example/src/js/sample-templates'; import cookieBanner from '../src'; import defaults from '../src/lib/defaults'; @@ -5,6 +6,7 @@ const init = () => { // Set up our document body document.body.innerHTML = `
`; window.__cb__ = cookieBanner({ + ...sampleTemplates, secure: false, hideBannerOnFormPage: false, types: { diff --git a/packages/cookie-banner/__tests__/form/api.js b/packages/cookie-banner/__tests__/form/api.js index e9a86f95..1116c09b 100644 --- a/packages/cookie-banner/__tests__/form/api.js +++ b/packages/cookie-banner/__tests__/form/api.js @@ -1,3 +1,4 @@ +import sampleTemplates from '../../example/src/js/sample-templates'; import cookieBanner from '../../src'; import defaults from '../../src/lib/defaults'; @@ -6,6 +7,7 @@ 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: { diff --git a/packages/cookie-banner/__tests__/form/interactions.js b/packages/cookie-banner/__tests__/form/interactions.js index 3db92465..96e22402 100644 --- a/packages/cookie-banner/__tests__/form/interactions.js +++ b/packages/cookie-banner/__tests__/form/interactions.js @@ -1,3 +1,4 @@ +import sampleTemplates from '../../example/src/js/sample-templates'; import cookieBanner from '../../src'; import defaults from '../../src/lib/defaults'; @@ -11,6 +12,7 @@ describe(`Cookie banner > DOM > form interactions`, () => { beforeAll(() => { document.body.innerHTML = `
`; window.__cb__ = cookieBanner({ + ...sampleTemplates, secure: false, hideBannerOnFormPage: false, types: { diff --git a/packages/cookie-banner/__tests__/form/not-render.js b/packages/cookie-banner/__tests__/form/not-render.js index 2bd8532a..c7b7ebcc 100644 --- a/packages/cookie-banner/__tests__/form/not-render.js +++ b/packages/cookie-banner/__tests__/form/not-render.js @@ -1,9 +1,11 @@ +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', diff --git a/packages/cookie-banner/__tests__/form/render.js b/packages/cookie-banner/__tests__/form/render.js index 2d32f727..33f371be 100644 --- a/packages/cookie-banner/__tests__/form/render.js +++ b/packages/cookie-banner/__tests__/form/render.js @@ -1,3 +1,4 @@ +import sampleTemplates from '../../example/src/js/sample-templates'; import cookieBanner from '../../src'; import defaults from '../../src/lib/defaults'; @@ -5,6 +6,7 @@ describe(`Cookie banner > DOM > form > render`, () => { beforeAll(() => { document.body.innerHTML = `
`; cookieBanner({ + ...sampleTemplates, secure: false, hideBannerOnFormPage: false, types: { diff --git a/packages/cookie-banner/__tests__/google-eu-consent/index.js b/packages/cookie-banner/__tests__/google-eu-consent/index.js index ff9fb727..0e8acfa8 100644 --- a/packages/cookie-banner/__tests__/google-eu-consent/index.js +++ b/packages/cookie-banner/__tests__/google-eu-consent/index.js @@ -1,11 +1,13 @@ 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', 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 index f0197cc2..cb848384 100644 --- 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 @@ -1,10 +1,12 @@ 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: { diff --git a/packages/cookie-banner/__tests__/reject.js b/packages/cookie-banner/__tests__/reject.js index 67d1e208..5950a4bd 100644 --- a/packages/cookie-banner/__tests__/reject.js +++ b/packages/cookie-banner/__tests__/reject.js @@ -1,3 +1,4 @@ +import sampleTemplates from '../example/src/js/sample-templates'; import cookieBanner from '../src'; import defaults from '../src/lib/defaults'; @@ -5,6 +6,7 @@ const init = () => { // Set up our document body document.body.innerHTML = `
`; window.__cb__ = cookieBanner({ + ...sampleTemplates, secure: false, hideBannerOnFormPage: false, types: { diff --git a/packages/cookie-banner/__tests__/state.js b/packages/cookie-banner/__tests__/state.js index 3d3f090a..c1810482 100644 --- a/packages/cookie-banner/__tests__/state.js +++ b/packages/cookie-banner/__tests__/state.js @@ -1,4 +1,5 @@ import cookieBanner from '../src'; +import sampleTemplates from '../example/src/js/sample-templates'; import { updateConsent, updateExecuted } from '../src/lib/reducers'; const init = () => { @@ -10,13 +11,18 @@ const init = () => { describe(`Cookie banner > state > init`, () => { beforeAll(init); - it('Should return the Store.getState method on initialisation', async () => { + it('Should return undefined if mandatory options are missing', async () => { const Store = cookieBanner({ types: {} }); + expect(Store).toBeUndefined(); + }); + + it('Should return the Store.getState method on initialisation', async () => { + const Store = cookieBanner({ ...sampleTemplates, types: {} }); expect(Store.getState).not.toBeUndefined(); }); it('Should return the state Object from Store.getState', async () => { - const Store = cookieBanner({ types: {} }); + const Store = cookieBanner({ ...sampleTemplates, types: {} }); expect(Store.getState()).toBeDefined(); expect(Store.getState().consent).toEqual({}); @@ -42,7 +48,7 @@ describe(`Cookie banner > state > update/reducers`, () => { ] } }; - const Store = cookieBanner({ types }); + const Store = cookieBanner({ ...sampleTemplates, types }); expect(Store.getState().settings.types).toEqual(types); }); diff --git a/packages/cookie-banner/__tests__/utils.js b/packages/cookie-banner/__tests__/utils.js index e31bd7c6..d71aa3fa 100644 --- a/packages/cookie-banner/__tests__/utils.js +++ b/packages/cookie-banner/__tests__/utils.js @@ -4,7 +4,7 @@ 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 () => { + it('should return the same value for a root domain', async () => { expect(removeSubdomain('stormid.com')).toEqual('stormid.com'); }); diff --git a/packages/cookie-banner/example/src/js/index.js b/packages/cookie-banner/example/src/js/index.js index 948a469d..9c924486 100644 --- a/packages/cookie-banner/example/src/js/index.js +++ b/packages/cookie-banner/example/src/js/index.js @@ -1,5 +1,6 @@ import cookieBanner from '../../../src/index'; import toggle from '../../../../toggle/src/index'; +import SampleTemplates from './sample-templates'; const writeCookie = state => { document.cookie = [ @@ -12,7 +13,7 @@ const writeCookie = state => { ].join(''); }; -const config = { +const config = {...SampleTemplates, name: '.Components.Dev.Consent', secure: false, euConsentTypes: { @@ -78,74 +79,6 @@ const config = { } ] } - }, - bannerTemplate(model){ - return ``; - }, - formTemplate(model){ - return `
- ${Object.keys(model.settings.types).map(type => `
- - ${model.settings.types[type].title} - ${model.settings.types[type].description} - -
-
- -
-
-
-
- -
-
-
`).join('')} -
- -
Or
-
-
`; } }; diff --git a/packages/cookie-banner/example/src/js/sample-templates.js b/packages/cookie-banner/example/src/js/sample-templates.js new file mode 100644 index 00000000..02839425 --- /dev/null +++ b/packages/cookie-banner/example/src/js/sample-templates.js @@ -0,0 +1,60 @@ +export default { + bannerTemplate(model){ + return `<`; + }, + messageTemplate(model){ + return `` + }, + formTemplate(model){ + return `
+ ${Object.keys(model.settings.types).map(type => `
+ + ${model.settings.types[type].title} + ${model.settings.types[type].description} + +
+
+ +
+
+
+
+ +
+
+
`).join('')} + +
`; + } +} \ No newline at end of file diff --git a/packages/cookie-banner/src/lib/defaults.js b/packages/cookie-banner/src/lib/defaults.js index 18ea9d69..019f391b 100755 --- a/packages/cookie-banner/src/lib/defaults.js +++ b/packages/cookie-banner/src/lib/defaults.js @@ -32,62 +32,9 @@ export default { hideBannerOnFormPage: true, trapTab: false, savedMessage: 'Your settings have been saved.', - bannerTemplate(model){ - return ``; + messageTemplate(model){ + return `
${model.settings.savedMessage}
` }, - messageTemplate(model){ - return ``; - }, - formTemplate(model){ - return `
- ${Object.keys(model.settings.types).map(type => `
- - ${model.settings.types[type].title} - ${model.settings.types[type].description} - -
-
- -
-
-
-
- -
-
-
`).join('')} - -
`; - } + bannerTemplate: null, + formTemplate: null }; \ No newline at end of file diff --git a/packages/cookie-banner/src/lib/factory.js b/packages/cookie-banner/src/lib/factory.js index 0715f191..6073baae 100644 --- a/packages/cookie-banner/src/lib/factory.js +++ b/packages/cookie-banner/src/lib/factory.js @@ -7,6 +7,10 @@ import { initialState } from './reducers'; export default settings => { /* istanbul ignore next */ if (!cookiesEnabled()) return; + if(!settings.bannerTemplate || !settings.formTemplate) { + console.warn('Missing required cookie banner and/or preferences form markup. Cookie banner not initialised.'); + return; + } const Store = createStore(); //extractFromCookie adds a try/catch guard for cookie reading and JSON.parse in case of cookie name collisions caused by versioning