From bfdae2502609be594e567c97960563b0b47dc784 Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 5 Oct 2016 12:27:33 +0200 Subject: [PATCH 1/7] add prop "cookieExpiration" and use it to set seconds since cookie expiration --- src/CookieBanner.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/CookieBanner.js b/src/CookieBanner.js index 6b79281..9544be4 100644 --- a/src/CookieBanner.js +++ b/src/CookieBanner.js @@ -5,6 +5,8 @@ import { t, props } from 'tcomb-react'; import { cookie as cookieLite } from 'browser-cookie-lite'; import styleUtils from './styleUtils'; +const NotEmptyStruct = t.refinement(t.struct, x => Object.keys(x).length > 0); + const Props = { children: t.maybe(t.ReactChildren), message: t.maybe(t.String), @@ -16,6 +18,11 @@ const Props = { })), buttonMessage: t.maybe(t.String), cookie: t.maybe(t.String), + cookieExpiration: t.maybe(t.union([NotEmptyStruct({ + years: t.maybe(t.Number), + days: t.maybe(t.Number), + hours: t.maybe(t.Number) + }), t.Integer])), dismissOnScroll: t.maybe(t.Boolean), dismissOnScrollThreshold: t.maybe(t.Number), closeIcon: t.maybe(t.String), @@ -45,6 +52,7 @@ export default class CookieBanner extends React.Component { onAccept: () => {}, dismissOnScroll: true, cookie: 'accepts-cookies', + cookieExpiration: { years: 1 }, buttonMessage: 'Got it', dismissOnScrollThreshold: 0, styles: {} @@ -89,8 +97,17 @@ export default class CookieBanner extends React.Component { } onAccept = () => { - const { cookie, onAccept } = this.props; - cookieLite(cookie, true, 60*60*24*365); + const { cookie, cookieExpiration, onAccept } = this.props; + + const SECONDS_IN_YEAR = 31536000; + const SECONDS_IN_DAY = 86400; + const SECONDS_IN_HOUR = 3600; + + const secondsSinceExpiration = t.Integer.is(cookieExpiration) ? + cookieExpiration : + (cookieExpiration.years * SECONDS_IN_YEAR) + (cookieExpiration.days * SECONDS_IN_DAY) + (cookieExpiration.hours * SECONDS_IN_HOUR); + + cookieLite(cookie, true, secondsSinceExpiration); onAccept({ cookie }); if (this.state.listeningScroll) { From c670315b7fd11c511e6bb94768429d52bd3d60bb Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 5 Oct 2016 12:43:13 +0200 Subject: [PATCH 2/7] move secondsSinceExpiration computation into separate function --- src/CookieBanner.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/CookieBanner.js b/src/CookieBanner.js index 9544be4..066ddd7 100644 --- a/src/CookieBanner.js +++ b/src/CookieBanner.js @@ -5,8 +5,6 @@ import { t, props } from 'tcomb-react'; import { cookie as cookieLite } from 'browser-cookie-lite'; import styleUtils from './styleUtils'; -const NotEmptyStruct = t.refinement(t.struct, x => Object.keys(x).length > 0); - const Props = { children: t.maybe(t.ReactChildren), message: t.maybe(t.String), @@ -18,7 +16,7 @@ const Props = { })), buttonMessage: t.maybe(t.String), cookie: t.maybe(t.String), - cookieExpiration: t.maybe(t.union([NotEmptyStruct({ + cookieExpiration: t.maybe(t.union([t.interface({ years: t.maybe(t.Number), days: t.maybe(t.Number), hours: t.maybe(t.Number) @@ -96,18 +94,29 @@ export default class CookieBanner extends React.Component { } } - onAccept = () => { - const { cookie, cookieExpiration, onAccept } = this.props; + getSecondsSinceExpiration = cookieExpiration => { + if (t.Integer.is(cookieExpiration)) { + return cookieExpiration; + } const SECONDS_IN_YEAR = 31536000; const SECONDS_IN_DAY = 86400; const SECONDS_IN_HOUR = 3600; - const secondsSinceExpiration = t.Integer.is(cookieExpiration) ? - cookieExpiration : - (cookieExpiration.years * SECONDS_IN_YEAR) + (cookieExpiration.days * SECONDS_IN_DAY) + (cookieExpiration.hours * SECONDS_IN_HOUR); + const _cookieExpiration = { + years: 0, days: 0, hours: 0, + ...cookieExpiration + }; + + const { years, days, hours } = _cookieExpiration; + + return (years * SECONDS_IN_YEAR) + (days * SECONDS_IN_DAY) + (hours * SECONDS_IN_HOUR); + } + + onAccept = () => { + const { cookie, cookieExpiration, onAccept } = this.props; - cookieLite(cookie, true, secondsSinceExpiration); + cookieLite(cookie, true, this.getSecondsSinceExpiration(cookieExpiration)); onAccept({ cookie }); if (this.state.listeningScroll) { From fdb110e2e21d86062bccdb2510641249b4af776d Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 5 Oct 2016 12:53:17 +0200 Subject: [PATCH 3/7] t.interface should be strict; replace t.struct with t.interface --- src/CookieBanner.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CookieBanner.js b/src/CookieBanner.js index 066ddd7..92391c0 100644 --- a/src/CookieBanner.js +++ b/src/CookieBanner.js @@ -4,12 +4,13 @@ import omit from 'lodash.omit'; import { t, props } from 'tcomb-react'; import { cookie as cookieLite } from 'browser-cookie-lite'; import styleUtils from './styleUtils'; +t.interface.strict = true; const Props = { children: t.maybe(t.ReactChildren), message: t.maybe(t.String), onAccept: t.maybe(t.Function), - link: t.maybe(t.struct({ + link: t.maybe(t.interface({ msg: t.maybe(t.String), url: t.String, target: t.maybe(t.enums.of(['_blank', '_self', '_parent', '_top', 'framename'])) From 3c506b45116dc750093704818523a36ee608ce30 Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 5 Oct 2016 12:55:58 +0200 Subject: [PATCH 4/7] code clean --- src/CookieBanner.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/CookieBanner.js b/src/CookieBanner.js index 92391c0..787ebd4 100644 --- a/src/CookieBanner.js +++ b/src/CookieBanner.js @@ -17,11 +17,14 @@ const Props = { })), buttonMessage: t.maybe(t.String), cookie: t.maybe(t.String), - cookieExpiration: t.maybe(t.union([t.interface({ - years: t.maybe(t.Number), - days: t.maybe(t.Number), - hours: t.maybe(t.Number) - }), t.Integer])), + cookieExpiration: t.maybe(t.union([ + t.Integer, + t.interface({ + years: t.maybe(t.Number), + days: t.maybe(t.Number), + hours: t.maybe(t.Number) + }) + ])), dismissOnScroll: t.maybe(t.Boolean), dismissOnScrollThreshold: t.maybe(t.Number), closeIcon: t.maybe(t.String), From 219cbb6a8b22f0879546dc5af533b74b30474a02 Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 5 Oct 2016 13:10:55 +0200 Subject: [PATCH 5/7] fix lint errors --- test/tests/CookieBanner-test.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/test/tests/CookieBanner-test.js b/test/tests/CookieBanner-test.js index e6aa1e0..3ab7bf0 100644 --- a/test/tests/CookieBanner-test.js +++ b/test/tests/CookieBanner-test.js @@ -4,21 +4,22 @@ import expect from 'expect'; import CookieBanner from '../../src/CookieBanner'; const resetCookies = function () { - const cookies = document.cookie.split(";"); + const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i]; - const eqPos = cookie.indexOf("="); + const eqPos = cookie.indexOf('='); const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; - document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT"; + document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`; } }; const renderBanner = (props) => { - const component = + const component = (
-
; + + ); const cookieWrapper = TestUtils.renderIntoDocument(component); return { @@ -29,14 +30,14 @@ const renderBanner = (props) => { beforeEach(resetCookies); -describe('CookieBanner', function() { +describe('CookieBanner', () => { - it('should be displayed if no cookies are set', function() { + it('should be displayed if no cookies are set', () => { const banner = renderBanner().banner; expect(banner.length).toBe(1, 'cookie banner is not displayed'); }); - it('should hide on click', function() { + it('should hide on click', () => { const banner = renderBanner().banner[0]; const closeButton = TestUtils.findRenderedDOMComponentWithClass(banner, 'button-close'); TestUtils.Simulate.click(closeButton); @@ -46,7 +47,7 @@ describe('CookieBanner', function() { expect(cookieBanner2.length).toBe(0, 'cookie banner is displayed'); }); - it('should hide on click when dismissOnScroll is false', function() { + it('should hide on click when dismissOnScroll is false', () => { const { banner, wrapper } = renderBanner({ dismissOnScroll: false }); const closeButton = TestUtils.findRenderedDOMComponentWithClass(banner[0], 'button-close'); TestUtils.Simulate.click(closeButton); @@ -55,7 +56,7 @@ describe('CookieBanner', function() { expect(cookieBanners.length).toBe(0, 'cookie banner is displayed'); }); - it('should be displayed with correct message', function() { + it('should be displayed with correct message', () => { const cookieWrapper = TestUtils.renderIntoDocument(
@@ -67,7 +68,7 @@ describe('CookieBanner', function() { expect(message.innerHTML).toBe('cookie message', 'wrong message displayed'); }); - it('should be replaced with custom child component', function() { + it('should be replaced with custom child component', () => { const MyComponent = React.createClass({ render() { @@ -75,12 +76,13 @@ describe('CookieBanner', function() { } }); - const component = + const component = (
-
; +
+ ); const cookieWrapper = TestUtils.renderIntoDocument(component); From 431f8017e73c1ef56422de2af082850c37c45c04 Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 5 Oct 2016 13:17:05 +0200 Subject: [PATCH 6/7] test "secondsSinceExpiration" computation --- test/tests/CookieBanner-test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/tests/CookieBanner-test.js b/test/tests/CookieBanner-test.js index 3ab7bf0..7c670c0 100644 --- a/test/tests/CookieBanner-test.js +++ b/test/tests/CookieBanner-test.js @@ -30,6 +30,24 @@ const renderBanner = (props) => { beforeEach(resetCookies); +describe('secondsSinceExpiration', () => { + const { getSecondsSinceExpiration } = new CookieBanner(); + + it('should return "cookieExpiration" if it is an integer', () => { + expect(getSecondsSinceExpiration(12345)).toBe(12345); + }); + + it('should transform "years", "days" and "hours" into seconds', () => { + expect(getSecondsSinceExpiration({ years: 1, days: 10, hours: 5 })).toBe(32418000); + }); + + it('should handle missing "years", "days" or "hours"', () => { + expect(getSecondsSinceExpiration({ days: 10 })).toBe(864000); + expect(getSecondsSinceExpiration({})).toBe(0); + }); + +}); + describe('CookieBanner', () => { it('should be displayed if no cookies are set', () => { From af823f18b23860ae9dfc8f523ca5adbc52a7ba3a Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 5 Oct 2016 13:17:38 +0200 Subject: [PATCH 7/7] lint tests too --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d4befb4..4550fb3 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "test": "./node_modules/karma/bin/karma start", "build": "rm -rf lib && mkdir lib && babel --loose --stage 0 --out-dir lib src", - "lint": "eslint src", + "lint": "eslint src test", "preversion": "npm run lint && npm run test && npm run build-examples", "prepublish": "npm run build", "build-examples": "npm run clean && webpack --config examples/webpack.config.build.js --progress",