From 316c958c7c011e18d34174792b94c7f2c1ceaea1 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Tue, 19 Jul 2016 13:16:14 +0100 Subject: [PATCH 1/9] Add a more generic way to manage GOV.UK surveys The current code (in `user-satisfaction-survey.js`) ties together both the mechanism to present a survey for the user to fill out, and the metadata about the survey itself. Historically, there has only been a single survey, but this is about to change. Therefore, create a more "generic" mechanism to display surveys, where the metadata about a survey is separated from the mechanism of selecting the "Active" survey and displaying it. Thus, we can add more small surveys -- with varying start and end times, and varying frequencies -- by adding a single set of metadata to the array in `surveys.js` Furthermore, there are identifiable enhancement paths where we can make surveys conditionally appear on different parts of the site -- a requirement coming up in a few weeks time. With @NeilvB TODO: Figure out how cache expiry needs to work when this change deploys. What's the impact of it? --- app/assets/javascripts/header-footer-only.js | 1 + app/assets/javascripts/surveys.js | 106 +++++++++++++ spec/javascripts/surveys-spec.js | 157 +++++++++++++++++++ 3 files changed, 264 insertions(+) create mode 100644 app/assets/javascripts/surveys.js create mode 100644 spec/javascripts/surveys-spec.js diff --git a/app/assets/javascripts/header-footer-only.js b/app/assets/javascripts/header-footer-only.js index eb7612a32..024e2a094 100644 --- a/app/assets/javascripts/header-footer-only.js +++ b/app/assets/javascripts/header-footer-only.js @@ -3,6 +3,7 @@ //= require analytics //= require start-modules //= require user-satisfaction-survey +//= require surveys //= require core //= require report-a-problem-form //= require report-a-problem diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js new file mode 100644 index 000000000..a1ec69985 --- /dev/null +++ b/app/assets/javascripts/surveys.js @@ -0,0 +1,106 @@ +(function() { + "use strict"; + + var root = this, + $ = root.jQuery; + if(typeof root.GOVUK === 'undefined') { root.GOVUK = {}; } + + var TEMPLATE = '
' + + '
' + + '

Tell us what you think of GOV.UK

' + + '

No thanks

' + + '

Take the 3 minute survey This will open a short survey on another website

' + + '
' + + '
'; + + var userSurveys = { + defaultSurvey: { + url: 'https://www.surveymonkey.com/s/2MRDLTW', + analytics_code: 'user_satisfaction_survey', + template: TEMPLATE, + frequency: 50, + }, + smallSurveys: [], + + getActiveSurvey: function(defaultSurvey, smallSurveys) { + var activeSurvey = defaultSurvey; + + $.each(smallSurveys, function(_index, survey) { + if(userSurveys.currentTime() >= survey.startTime && userSurveys.currentTime() <= survey.endTime) { + activeSurvey = survey; + } + }); + + return activeSurvey; + }, + + displaySurvey: function(survey) { + $("#user-satisfaction-survey-container").append(survey.template); + userSurveys.setEventHandlers(survey); + + var $surveyLink = $('#take-survey'); + var surveyUrl = survey.url; + + if (surveyUrl.indexOf('?c=') === -1) { + surveyUrl += "?c=" + root.location.pathname; + } + + $surveyLink.attr('href', surveyUrl); + userSurveys.trackEvent(survey.analytics_code, 'banner_shown', 'Banner has been shown'); + }, + + setEventHandlers: function(survey) { + var $noThanks = $('#survey-no-thanks'); + var $takeSurvey = $('#take-survey'); + + $noThanks.click(function (e) { + userSurveys.setCookieTakenSurvey(); + userSurveys.trackEvent(survey.analytics_code, 'banner_no_thanks', 'No thanks clicked'); + e.stopPropagation(); + return false; + }); + $takeSurvey.click(function () { + userSurveys.setCookieTakenSurvey(); + userSurveys.trackEvent(survey.analytics_code, 'banner_taken', 'User taken survey'); + }); + }, + + shouldSurveyDisplay: function(survey) { + if (userSurveys.otherNotificationVisible() || + GOVUK.cookie(userSurveys.cookieNameTakenSurvey) === 'true') { + return false; + } else if ($('#user-satisfaction-survey-container').length <= 0) { + return false; + } else if (userSurveys.randomNumberMatches(survey.frequency)) { + return true; + } else { + return false; + } + }, + + trackEvent: function (analytics_code, action, label) { + GOVUK.analytics.trackEvent(analytics_code, action, { + label: label, + value: 1, + nonInteraction: true + }); + }, + + setCookieTakenSurvey: function () { + GOVUK.cookie(userSurveys.cookieNameTakenSurvey, true, { days: 30*4 }); + $("#user-satisfaction-survey").removeClass('visible').attr('aria-hidden', 'true'); + }, + + randomNumberMatches: function(frequency) { + return (Math.floor(Math.random() * frequency) === 0); + }, + + otherNotificationVisible: function() { + return $('#banner-notification:visible, #global-cookie-message:visible, #global-browser-prompt:visible').length > 0; + }, + cookieNameTakenSurvey: "govuk_takenUserSatisfactionSurvey", + currentTime: function() { return new Date().getTime(); } + }; + + root.GOVUK.userSurveys = userSurveys; +}).call(this); diff --git a/spec/javascripts/surveys-spec.js b/spec/javascripts/surveys-spec.js new file mode 100644 index 000000000..78588a4c0 --- /dev/null +++ b/spec/javascripts/surveys-spec.js @@ -0,0 +1,157 @@ +describe("Surveys", function() { + var surveys = GOVUK.userSurveys; + var $block; + + var defaultSurvey = { + url: 'example.com/default', + frequency: 1, // no randomness in the test suite pls + analytics_code: 'user_satisfaction_survey', + template: '
' + + ' No thanks' + + ' ' + + '
' + }; + var smallSurvey = { + startTime: new Date("July 5, 2016").getTime(), + endTime: new Date("July 10, 2016 23:50:00").getTime(), + url: 'example.com/small-survey' + }; + + beforeEach(function () { + $block = $('' + + '' + + '' + + '
'); + + $('body').append($block); + $("#user-satisfaction-survey").remove(); + + // Don't actually try and take a survey in test. + $('#take-survey').on('click', function(e) { + e.preventDefault(); + }); + }); + + afterEach(function () { + GOVUK.cookie(surveys.cookieNameTakenSurvey, null); + $block.remove(); + }); + + describe("displaySurvey", function() { + it("displays the user satisfaction div", function () { + expect($('#user-satisfaction-survey').length).toBe(0); + surveys.displaySurvey(defaultSurvey); + expect($('#user-satisfaction-survey').length).toBe(1); + expect($('#user-satisfaction-survey').hasClass('visible')).toBe(true); + expect($('#user-satisfaction-survey').attr('aria-hidden')).toBe('false'); + }); + + it("links to the url for the survey with a completion redirect query parameter", function () { + surveys.displaySurvey(defaultSurvey); + + expect($('#take-survey').attr('href')).toContain(defaultSurvey.url); + expect($('#take-survey').attr('href')).toContain("?c=" + window.location.pathname); + }); + + it("records an event when showing the survey", function() { + spyOn(surveys, 'trackEvent'); + surveys.displaySurvey(defaultSurvey); + expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.analytics_code, 'banner_shown', 'Banner has been shown'); + }); + }); + + // this is a crap function name, fix it + describe("shouldSurveyDisplay", function() { + it("returns false if another notification banner is visible", function() { + $('#global-cookie-message').css('display', 'block'); + + expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeFalsy(); + }); + + it("returns false if the 'survey taken' cookie is set", function () { + GOVUK.cookie(surveys.cookieNameTakenSurvey, 'true'); + + expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeFalsy(); + }); + + it("returns false when the random number does not match", function() { + spyOn(surveys, 'randomNumberMatches').and.returnValue(false); + expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeFalsy(); + }); + + it("returns true when the random number matches", function() { + spyOn(surveys, 'randomNumberMatches').and.returnValue(true); + expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeTruthy(); + }); + }); + + describe("Event handlers", function () { + beforeEach(function() { + surveys.displaySurvey(defaultSurvey); + }); + + it("sets a cookie when clicking 'take survey'", function () { + $('#take-survey').trigger('click'); + expect(GOVUK.cookie(surveys.cookieNameTakenSurvey)).toBe('true'); + }); + + it("sets a cookie when clicking 'no thanks'", function () { + $('#survey-no-thanks').trigger('click'); + expect(GOVUK.cookie(surveys.cookieNameTakenSurvey)).toBe('true'); + }); + + it("hides the satisfaction survey bar after clicking 'take survey'", function () { + $('#take-survey').trigger('click'); + expect($('#user-satisfaction-survey').hasClass('visible')).toBe(false); + expect($('#user-satisfaction-survey').attr('aria-hidden')).toBe('true'); + }); + + it("hides the satisfaction survey bar after clicking 'no thanks'", function () { + $('#survey-no-thanks').trigger('click'); + expect($('#user-satisfaction-survey').hasClass('visible')).toBe(false); + }); + + it("records an event when clicking 'take survey'", function() { + spyOn(surveys, 'trackEvent'); + $('#take-survey').trigger('click'); + expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.analytics_code, 'banner_taken', 'User taken survey'); + }); + + it("records an event when clicking 'no thanks'", function() { + spyOn(surveys, 'trackEvent'); + $('#survey-no-thanks').trigger('click'); + expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.analytics_code, 'banner_no_thanks', 'No thanks clicked'); + }); + }); + + describe("currentTime", function() { + it("actually returns a value from `currentTime`", function() { + expect(surveys.currentTime()).not.toBe(undefined); + }); + }); + + describe("getActiveSurvey", function() { + it("returns the default survey when no smallSurveys are present", function() { + var smallSurveys = [smallSurvey]; + + var activeSurvey = surveys.getActiveSurvey(defaultSurvey, smallSurveys); + expect(activeSurvey).toBe(defaultSurvey); + }); + + it("returns the default survey when a smallSurvey is not active", function() { + var smallSurveys = [smallSurvey]; + spyOn(surveys, 'currentTime').and.returnValue(new Date("July 11, 2016 10:00:00").getTime()); + + var activeSurvey = surveys.getActiveSurvey(defaultSurvey, smallSurveys); + expect(activeSurvey).toBe(defaultSurvey); + }); + + it("returns the small survey when a smallSurvey is active", function() { + var smallSurveys = [smallSurvey]; + spyOn(surveys, 'currentTime').and.returnValue(new Date("July 9, 2016 10:00:00").getTime()); + + var activeSurvey = surveys.getActiveSurvey(defaultSurvey, smallSurveys); + expect(activeSurvey).toBe(smallSurvey); + }); + }); +}); From 0bbccf9044e48189e7ce49160d8b36f68d6e961c Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Tue, 19 Jul 2016 16:24:19 +0100 Subject: [PATCH 2/9] Switch entrypoint to the new survey code With @NeilvB --- app/assets/javascripts/core.js | 2 +- app/assets/javascripts/surveys.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/core.js b/app/assets/javascripts/core.js index 0ee14e9dd..0af85ca6a 100644 --- a/app/assets/javascripts/core.js +++ b/app/assets/javascripts/core.js @@ -30,7 +30,7 @@ $(document).ready(function() { if (!stringContains(currentURL, "/done") && !stringContains(currentURL, "/transaction-finished") && !stringContains(currentURL, "/driving-transaction-finished")) { - GOVUK.userSatisfaction.randomlyShowSurveyBar(); + GOVUK.userSurveys.init(); } } } diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js index a1ec69985..23841fa24 100644 --- a/app/assets/javascripts/surveys.js +++ b/app/assets/javascripts/surveys.js @@ -22,6 +22,13 @@ }, smallSurveys: [], + init: function() { + var activeSurvey = userSurveys.getActiveSurvey(userSurveys.defaultSurvey, userSurveys.smallSurveys); + if (userSurveys.shouldSurveyDisplay(activeSurvey)) { + userSurveys.displaySurvey(activeSurvey); + } + }, + getActiveSurvey: function(defaultSurvey, smallSurveys) { var activeSurvey = defaultSurvey; From 8f1f835c8191d6128705950ecbb3750c8aaaeba9 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Tue, 19 Jul 2016 16:50:19 +0100 Subject: [PATCH 3/9] Refactor transaction survey prevention The correct place for this logic is inside the survey javascript where other decisions are made with a bearing on if we should display the survey. During this refactor, we moved the `window.GOVUK` guard to surround what appears to also be relevant code that should be protected by this guard. + @NeilvB --- app/assets/javascripts/core.js | 31 +++++++++---------------------- app/assets/javascripts/surveys.js | 19 +++++++++++++++++++ spec/javascripts/surveys-spec.js | 15 +++++++++++++++ 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/core.js b/app/assets/javascripts/core.js index 0af85ca6a..92c3e35a3 100644 --- a/app/assets/javascripts/core.js +++ b/app/assets/javascripts/core.js @@ -17,31 +17,18 @@ $(document).ready(function() { }); if (window.GOVUK) { - if (GOVUK.userSatisfaction){ - var currentURL = window.location.pathname; - - function stringContains(str, substr) { - return str.indexOf(substr) > -1; - } - - // We don't want the satisfaction survey appearing for users who - // have completed a transaction as they may complete the survey with - // the department's transaction in mind as opposed to the GOV.UK content. - if (!stringContains(currentURL, "/done") && - !stringContains(currentURL, "/transaction-finished") && - !stringContains(currentURL, "/driving-transaction-finished")) { - GOVUK.userSurveys.init(); - } + if (GOVUK.userSurveys){ + GOVUK.userSurveys.init(); } - } - // for radio buttons and checkboxes - var buttonsSelector = "label.selectable input[type='radio'], label.selectable input[type='checkbox']"; - new GOVUK.SelectionButtons(buttonsSelector); + // for radio buttons and checkboxes + var buttonsSelector = "label.selectable input[type='radio'], label.selectable input[type='checkbox']"; + new GOVUK.SelectionButtons(buttonsSelector); - // HMRC webchat - if (GOVUK.webchat) { - GOVUK.webchat.init(); + // HMRC webchat + if (GOVUK.webchat) { + GOVUK.webchat.init(); + } } }); diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js index 23841fa24..9828af279 100644 --- a/app/assets/javascripts/surveys.js +++ b/app/assets/javascripts/surveys.js @@ -76,6 +76,11 @@ if (userSurveys.otherNotificationVisible() || GOVUK.cookie(userSurveys.cookieNameTakenSurvey) === 'true') { return false; + } else if (userSurveys.userCompletedTransaction()) { + // We don't want any survey appearing for users who have completed a + // transaction as they may complete the survey with the department's + // transaction in mind as opposed to the GOV.UK content. + return false; } else if ($('#user-satisfaction-survey-container').length <= 0) { return false; } else if (userSurveys.randomNumberMatches(survey.frequency)) { @@ -85,6 +90,20 @@ } }, + userCompletedTransaction: function() { + var currentURL = window.location.pathname; + + function stringContains(str, substr) { + return str.indexOf(substr) > -1; + } + + if (stringContains(currentURL, "/done") && + stringContains(currentURL, "/transaction-finished") && + stringContains(currentURL, "/driving-transaction-finished")) { + return true; + } + }, + trackEvent: function (analytics_code, action, label) { GOVUK.analytics.trackEvent(analytics_code, action, { label: label, diff --git a/spec/javascripts/surveys-spec.js b/spec/javascripts/surveys-spec.js index 78588a4c0..415636d8e 100644 --- a/spec/javascripts/surveys-spec.js +++ b/spec/javascripts/surveys-spec.js @@ -37,6 +37,21 @@ describe("Surveys", function() { $block.remove(); }); + describe("init", function() { + it("shows the default survey", function() { + spyOn(surveys, 'randomNumberMatches').and.returnValue(true); + // So we're working with the user satisfaction survey, not any future small survey + spyOn(surveys, 'currentTime').and.returnValue(new Date("July 11, 201610:00:00").getTime()); + surveys.init(); + + expect($('#take-survey').attr('href')).toContain(surveys.defaultSurvey.url); + expect($('#take-survey').attr('href')).toContain("?c=" + window.location.pathname); + expect($('#user-satisfaction-survey').length).toBe(1); + expect($('#user-satisfaction-survey').hasClass('visible')).toBe(true); + expect($('#user-satisfaction-survey').attr('aria-hidden')).toBe('false'); + }); + }); + describe("displaySurvey", function() { it("displays the user satisfaction div", function () { expect($('#user-satisfaction-survey').length).toBe(0); From affc706c78c4c50c6c287f416491910e5ebe6d22 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Tue, 19 Jul 2016 17:00:31 +0100 Subject: [PATCH 4/9] Remove old user satisfaction survey code + @NeilvB --- app/assets/javascripts/header-footer-only.js | 1 - .../javascripts/user-satisfaction-survey.js | 95 ------------ .../user-satisfaction-survey-spec.js | 143 ------------------ 3 files changed, 239 deletions(-) delete mode 100644 app/assets/javascripts/user-satisfaction-survey.js delete mode 100644 spec/javascripts/user-satisfaction-survey-spec.js diff --git a/app/assets/javascripts/header-footer-only.js b/app/assets/javascripts/header-footer-only.js index 024e2a094..bcab9bf6c 100644 --- a/app/assets/javascripts/header-footer-only.js +++ b/app/assets/javascripts/header-footer-only.js @@ -2,7 +2,6 @@ //= require vendor/polyfills/bind //= require analytics //= require start-modules -//= require user-satisfaction-survey //= require surveys //= require core //= require report-a-problem-form diff --git a/app/assets/javascripts/user-satisfaction-survey.js b/app/assets/javascripts/user-satisfaction-survey.js deleted file mode 100644 index 292155d3b..000000000 --- a/app/assets/javascripts/user-satisfaction-survey.js +++ /dev/null @@ -1,95 +0,0 @@ -(function() { - "use strict"; - - var root = this, - $ = root.jQuery; - if(typeof root.GOVUK === 'undefined') { root.GOVUK = {}; } - - var userSatisfaction = { - TEMPLATE: '
' + - '
' + - '

Tell us what you think of GOV.UK

' + - '

No thanks

' + - '

Take the 3 minute survey This will open a short survey on another website

' + - '
' + - '
', - - cookieNameTakenSurvey: "govuk_takenUserSatisfactionSurvey", - trackEvent: function (action, label) { - GOVUK.analytics.trackEvent('user_satisfaction_survey', action, { - label: label, - value: 1, - nonInteraction: true - }); - }, - setCookieTakenSurvey: function () { - GOVUK.cookie(userSatisfaction.cookieNameTakenSurvey, true, { days: 30*4 }); - $("#user-satisfaction-survey").removeClass('visible').attr('aria-hidden', 'true'); - }, - setEventHandlers: function () { - var $noThanks = $('#survey-no-thanks'); - var $takeSurvey = $('#take-survey'); - - $noThanks.click(function (e) { - userSatisfaction.setCookieTakenSurvey(); - userSatisfaction.trackEvent('banner_no_thanks', 'No thanks clicked'); - e.stopPropagation(); - return false; - }); - $takeSurvey.click(function () { - userSatisfaction.setCookieTakenSurvey(); - userSatisfaction.trackEvent('banner_taken', 'User taken survey'); - }); - }, - showSurveyBar: function () { - if (GOVUK.cookie(userSatisfaction.cookieNameTakenSurvey) === "true" || - userSatisfaction.otherNotificationVisible()) { - return; - } - - $("#user-satisfaction-survey-container").append(userSatisfaction.TEMPLATE); - - userSatisfaction.setEventHandlers(); - userSatisfaction.setSurveyUrl(); - userSatisfaction.trackEvent('banner_shown', 'Banner has been shown'); - }, - otherNotificationVisible: function() { - return $('#banner-notification:visible, #global-cookie-message:visible, #global-browser-prompt:visible').length > 0; - }, - randomlyShowSurveyBar: function () { - if ($('#user-satisfaction-survey-container').length <= 0) { - return; - } - if (Math.floor(Math.random() * userSatisfaction.surveyFrequency()) === 0) { - userSatisfaction.showSurveyBar(); - } - }, - surveyFrequency: function() { - if (userSatisfaction.inTestPeriod()) { - return 100; - } - - return 50; - }, - setSurveyUrl: function(href) { - var $surveyLink = $('#take-survey'); - var surveyUrl = $('#user-satisfaction-survey-container').data('survey-url'); - - if (surveyUrl.indexOf('?c=') === -1) { - surveyUrl += "?c=" + root.location.pathname; - } - - $surveyLink.attr('href', surveyUrl); - }, - inTestPeriod: function() { - var starts = new Date("May 4, 2016").getTime(); - var ends = new Date("May 5, 2016 23:59:59").getTime(); - - return userSatisfaction.currentDate() >= starts && - userSatisfaction.currentDate() <= ends; - }, - currentDate: function() { return new Date().getTime(); } - }; - - root.GOVUK.userSatisfaction = userSatisfaction; -}).call(this); diff --git a/spec/javascripts/user-satisfaction-survey-spec.js b/spec/javascripts/user-satisfaction-survey-spec.js deleted file mode 100644 index e3522890a..000000000 --- a/spec/javascripts/user-satisfaction-survey-spec.js +++ /dev/null @@ -1,143 +0,0 @@ -describe("User Satisfaction Survey", function () { - describe("Cookies", function () { - var survey, $surveyBar, $block, inTestPeriodSpy; - - beforeEach(function () { - $block = $('' + - '' + - '' + - '
'); - - $('body').append($block); - $("#user-satisfaction-survey").remove(); - - // Don't actually try and take a survey in test. - $('#take-survey').on('click', function(e) { - e.preventDefault(); - }); - - survey = GOVUK.userSatisfaction; - }); - - afterEach(function () { - GOVUK.cookie(survey.cookieNameTakenSurvey, null); - $block.remove(); - survey = null; - }); - - it("should display the user satisfaction div", function () { - expect($('#user-satisfaction-survey').length).toBe(0); - survey.showSurveyBar(); - expect($('#user-satisfaction-survey').length).toBe(1); - expect($('#user-satisfaction-survey').hasClass('visible')).toBe(true); - expect($('#user-satisfaction-survey').attr('aria-hidden')).toBe('false'); - }); - - it("actually returns a value from `currentDate`", function() { - expect(survey.currentDate()).not.toBe(undefined); - }); - - it("should set the take survey link's href to the survey monkey's url as defined by the wrapper's data-survey-url, appending the page's current path when not already specified", function() { - spyOn(GOVUK.userSatisfaction, 'inTestPeriod').and.returnValue(false); - $("#user-satisfaction-survey-container").data('survey-url', 'https://www.surveymonkey.com/r/some-survey-id'); - survey.showSurveyBar(); - expect($('#take-survey').attr('href')).toBe("https://www.surveymonkey.com/r/some-survey-id?c="+window.location.pathname); - }); - - it("should set the take survey link's href to the survey monkey's url as defined by the wrapper's data-survey-url, appending nothing when a path is already specified", function() { - spyOn(GOVUK.userSatisfaction, 'inTestPeriod').and.returnValue(false); - $("#user-satisfaction-survey-container").data('survey-url', 'https://www.surveymonkey.com/r/some-survey-id?c=/somewhere'); - survey.showSurveyBar(); - expect($('#take-survey').attr('href')).toBe("https://www.surveymonkey.com/r/some-survey-id?c=/somewhere"); - }); - - it("should show the survey approximately 1 in every 50 pageviews", function () { - spyOn(GOVUK.userSatisfaction, 'inTestPeriod').and.returnValue(false); - expect(survey.surveyFrequency()).toBe(50); - }); - - it("should decrease the frequency to 1 in every 100 pageviews during test period", function () { - spyOn(GOVUK.userSatisfaction, 'inTestPeriod').and.returnValue(true); - expect(survey.surveyFrequency()).toBe(100); - }); - - it("should display the survey when the random number matches", function () { - expect($('#user-satisfaction-survey').length).toBe(0); - spyOn(GOVUK.userSatisfaction, 'surveyFrequency').and.returnValue(1); - survey.randomlyShowSurveyBar(); - expect($('#user-satisfaction-survey').length).toBe(1); - }); - - it("should not display the user satisfaction div if another notification banner is visible", function() { - $('#global-cookie-message').css('display', 'block'); - - survey.showSurveyBar(); - expect($('#user-satisfaction-survey').length).toBe(0); - }); - - it("shouldn't show the user satisfaction div if the 'survey taken' cookie is set", function () { - GOVUK.cookie(survey.cookieNameTakenSurvey, 'true'); - - var counter = 0; - for (var i = 0; i < 100; i++) { - survey.randomlyShowSurveyBar(); - - if ($('#user-satisfaction-survey').length > 0) { - counter += 1; - break; - } - } - - expect(counter).toBe(0); - }); - - describe("Event handlers", function () { - beforeEach(function() { - survey.showSurveyBar(); - }); - - it("should set a cookie when clicking 'take survey'", function () { - $('#take-survey').trigger('click'); - expect(GOVUK.cookie(survey.cookieNameTakenSurvey)).toBe('true'); - }); - - it("should set a cookie when clicking 'no thanks'", function () { - $('#survey-no-thanks').trigger('click'); - expect(GOVUK.cookie(survey.cookieNameTakenSurvey)).toBe('true'); - }); - - it("should hide the satisfaction survey bar after clicking 'take survey'", function () { - $('#take-survey').trigger('click'); - expect($('#user-satisfaction-survey').hasClass('visible')).toBe(false); - expect($('#user-satisfaction-survey').attr('aria-hidden')).toBe('true'); - }); - - it("should hide the satisfaction survey bar after clicking 'no thanks'", function () { - $('#survey-no-thanks').trigger('click'); - expect($('#user-satisfaction-survey').hasClass('visible')).toBe(false); - }); - }); - - describe("inTestPeriod", function () { - it("should be false on 3 May 2016", function() { - spyOn(survey, 'currentDate').and.returnValue(new Date("May 3, 2016 23:50:00").getTime()); - expect(survey.inTestPeriod()).toBe(false); - }); - - it("should be true on 4 May 2016", function() { - spyOn(survey, 'currentDate').and.returnValue(new Date("May 4, 2016 00:01:00").getTime()); - expect(survey.inTestPeriod()).toBe(true); - }); - - it("should be true on 5 May 2016", function() { - spyOn(survey, 'currentDate').and.returnValue(new Date("May 5, 2016 23:50:00").getTime()); - expect(survey.inTestPeriod()).toBe(true); - }); - - it("should be false on 6 May 2016", function() { - spyOn(survey, 'currentDate').and.returnValue(new Date("May 6, 2016 00:01:00").getTime()); - expect(survey.inTestPeriod()).toBe(false); - }); - }); - }); -}); From 85bca0b1230c5223e5cd55a90d620bed97d78eea Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 20 Jul 2016 10:18:56 +0100 Subject: [PATCH 5/9] Use the identifier to set a custom cookie per survey Previously, the analytics code was solely used for analytics, but we're going to want a different cookie set for each survey. Completion of a particular survey means that the user will not be prompted for that survey for 4 months, but can be prompted for other survey types. --- app/assets/javascripts/surveys.js | 30 ++++++++++++++++++------------ spec/javascripts/surveys-spec.js | 23 +++++++++++++++-------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js index 9828af279..abd9014df 100644 --- a/app/assets/javascripts/surveys.js +++ b/app/assets/javascripts/surveys.js @@ -16,7 +16,7 @@ var userSurveys = { defaultSurvey: { url: 'https://www.surveymonkey.com/s/2MRDLTW', - analytics_code: 'user_satisfaction_survey', + identifier: 'user_satisfaction_survey', template: TEMPLATE, frequency: 50, }, @@ -53,7 +53,7 @@ } $surveyLink.attr('href', surveyUrl); - userSurveys.trackEvent(survey.analytics_code, 'banner_shown', 'Banner has been shown'); + userSurveys.trackEvent(survey.identifier, 'banner_shown', 'Banner has been shown'); }, setEventHandlers: function(survey) { @@ -61,20 +61,20 @@ var $takeSurvey = $('#take-survey'); $noThanks.click(function (e) { - userSurveys.setCookieTakenSurvey(); - userSurveys.trackEvent(survey.analytics_code, 'banner_no_thanks', 'No thanks clicked'); + userSurveys.setCookieTakenSurvey(survey); + userSurveys.trackEvent(survey.identifier, 'banner_no_thanks', 'No thanks clicked'); e.stopPropagation(); return false; }); $takeSurvey.click(function () { - userSurveys.setCookieTakenSurvey(); - userSurveys.trackEvent(survey.analytics_code, 'banner_taken', 'User taken survey'); + userSurveys.setCookieTakenSurvey(survey); + userSurveys.trackEvent(survey.identifier, 'banner_taken', 'User taken survey'); }); }, shouldSurveyDisplay: function(survey) { if (userSurveys.otherNotificationVisible() || - GOVUK.cookie(userSurveys.cookieNameTakenSurvey) === 'true') { + GOVUK.cookie(userSurveys.cookieNameTakenSurvey(survey)) === 'true') { return false; } else if (userSurveys.userCompletedTransaction()) { // We don't want any survey appearing for users who have completed a @@ -104,16 +104,16 @@ } }, - trackEvent: function (analytics_code, action, label) { - GOVUK.analytics.trackEvent(analytics_code, action, { + trackEvent: function (identifier, action, label) { + GOVUK.analytics.trackEvent(identifier, action, { label: label, value: 1, nonInteraction: true }); }, - setCookieTakenSurvey: function () { - GOVUK.cookie(userSurveys.cookieNameTakenSurvey, true, { days: 30*4 }); + setCookieTakenSurvey: function (survey) { + GOVUK.cookie(userSurveys.cookieNameTakenSurvey(survey), true, { days: 30*4 }); $("#user-satisfaction-survey").removeClass('visible').attr('aria-hidden', 'true'); }, @@ -124,9 +124,15 @@ otherNotificationVisible: function() { return $('#banner-notification:visible, #global-cookie-message:visible, #global-browser-prompt:visible').length > 0; }, - cookieNameTakenSurvey: "govuk_takenUserSatisfactionSurvey", + cookieNameTakenSurvey: function(survey) { + //user_satisfaction_survey => takenUserSatisfactionSurvey + var cookieStr = "taken_" + survey.identifier; + var cookieStub = cookieStr.replace(/(\_\w)/g, function(m){return m[1].toUpperCase();}); + return "govuk_" + cookieStub; + }, currentTime: function() { return new Date().getTime(); } }; root.GOVUK.userSurveys = userSurveys; }).call(this); + diff --git a/spec/javascripts/surveys-spec.js b/spec/javascripts/surveys-spec.js index 415636d8e..ea7d05364 100644 --- a/spec/javascripts/surveys-spec.js +++ b/spec/javascripts/surveys-spec.js @@ -5,7 +5,7 @@ describe("Surveys", function() { var defaultSurvey = { url: 'example.com/default', frequency: 1, // no randomness in the test suite pls - analytics_code: 'user_satisfaction_survey', + identifier: 'user_satisfaction_survey', template: '
' + ' No thanks' + ' ' + @@ -33,7 +33,7 @@ describe("Surveys", function() { }); afterEach(function () { - GOVUK.cookie(surveys.cookieNameTakenSurvey, null); + GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey), null); $block.remove(); }); @@ -71,7 +71,7 @@ describe("Surveys", function() { it("records an event when showing the survey", function() { spyOn(surveys, 'trackEvent'); surveys.displaySurvey(defaultSurvey); - expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.analytics_code, 'banner_shown', 'Banner has been shown'); + expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.identifier, 'banner_shown', 'Banner has been shown'); }); }); @@ -84,7 +84,7 @@ describe("Surveys", function() { }); it("returns false if the 'survey taken' cookie is set", function () { - GOVUK.cookie(surveys.cookieNameTakenSurvey, 'true'); + GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey), 'true'); expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeFalsy(); }); @@ -107,12 +107,12 @@ describe("Surveys", function() { it("sets a cookie when clicking 'take survey'", function () { $('#take-survey').trigger('click'); - expect(GOVUK.cookie(surveys.cookieNameTakenSurvey)).toBe('true'); + expect(GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey))).toBe('true'); }); it("sets a cookie when clicking 'no thanks'", function () { $('#survey-no-thanks').trigger('click'); - expect(GOVUK.cookie(surveys.cookieNameTakenSurvey)).toBe('true'); + expect(GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey))).toBe('true'); }); it("hides the satisfaction survey bar after clicking 'take survey'", function () { @@ -129,13 +129,13 @@ describe("Surveys", function() { it("records an event when clicking 'take survey'", function() { spyOn(surveys, 'trackEvent'); $('#take-survey').trigger('click'); - expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.analytics_code, 'banner_taken', 'User taken survey'); + expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.identifier, 'banner_taken', 'User taken survey'); }); it("records an event when clicking 'no thanks'", function() { spyOn(surveys, 'trackEvent'); $('#survey-no-thanks').trigger('click'); - expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.analytics_code, 'banner_no_thanks', 'No thanks clicked'); + expect(surveys.trackEvent).toHaveBeenCalledWith(defaultSurvey.identifier, 'banner_no_thanks', 'No thanks clicked'); }); }); @@ -145,6 +145,13 @@ describe("Surveys", function() { }); }); + describe("cookieNameTakenSurvey", function() { + it("returns a cookie name based on the survey identifier", function() { + var surveyMock = {identifier: 'sample_survey'} + expect(surveys.cookieNameTakenSurvey(surveyMock)).toBe('govuk_takenSampleSurvey'); + }); + }); + describe("getActiveSurvey", function() { it("returns the default survey when no smallSurveys are present", function() { var smallSurveys = [smallSurvey]; From f6b872b08f7eed3b9e1261327b5f0a2a1345f4aa Mon Sep 17 00:00:00 2001 From: Neil van Beinum Date: Wed, 20 Jul 2016 10:54:55 +0100 Subject: [PATCH 6/9] Rename function in surveys module shouldSurveyDisplay -> isSurveyToBeDisplayed Also: - Removed spec comment --- app/assets/javascripts/surveys.js | 4 ++-- spec/javascripts/surveys-spec.js | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js index abd9014df..03015f50a 100644 --- a/app/assets/javascripts/surveys.js +++ b/app/assets/javascripts/surveys.js @@ -24,7 +24,7 @@ init: function() { var activeSurvey = userSurveys.getActiveSurvey(userSurveys.defaultSurvey, userSurveys.smallSurveys); - if (userSurveys.shouldSurveyDisplay(activeSurvey)) { + if (userSurveys.isSurveyToBeDisplayed(activeSurvey)) { userSurveys.displaySurvey(activeSurvey); } }, @@ -72,7 +72,7 @@ }); }, - shouldSurveyDisplay: function(survey) { + isSurveyToBeDisplayed: function(survey) { if (userSurveys.otherNotificationVisible() || GOVUK.cookie(userSurveys.cookieNameTakenSurvey(survey)) === 'true') { return false; diff --git a/spec/javascripts/surveys-spec.js b/spec/javascripts/surveys-spec.js index ea7d05364..5de48fefa 100644 --- a/spec/javascripts/surveys-spec.js +++ b/spec/javascripts/surveys-spec.js @@ -75,28 +75,27 @@ describe("Surveys", function() { }); }); - // this is a crap function name, fix it - describe("shouldSurveyDisplay", function() { + describe("isSurveyToBeDisplayed", function() { it("returns false if another notification banner is visible", function() { $('#global-cookie-message').css('display', 'block'); - expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeFalsy(); + expect(surveys.isSurveyToBeDisplayed(defaultSurvey)).toBeFalsy(); }); it("returns false if the 'survey taken' cookie is set", function () { GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey), 'true'); - expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeFalsy(); + expect(surveys.isSurveyToBeDisplayed(defaultSurvey)).toBeFalsy(); }); it("returns false when the random number does not match", function() { spyOn(surveys, 'randomNumberMatches').and.returnValue(false); - expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeFalsy(); + expect(surveys.isSurveyToBeDisplayed(defaultSurvey)).toBeFalsy(); }); it("returns true when the random number matches", function() { spyOn(surveys, 'randomNumberMatches').and.returnValue(true); - expect(surveys.shouldSurveyDisplay(defaultSurvey)).toBeTruthy(); + expect(surveys.isSurveyToBeDisplayed(defaultSurvey)).toBeTruthy(); }); }); From d7db4fbd536d9bb61051f3e9797c0d7d42291743 Mon Sep 17 00:00:00 2001 From: Neil van Beinum Date: Wed, 20 Jul 2016 11:04:45 +0100 Subject: [PATCH 7/9] Rename function surveys module cookieNameTakenSurvey -> surveyTakenCookieName --- app/assets/javascripts/surveys.js | 8 +++++--- spec/javascripts/surveys-spec.js | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js index 03015f50a..4e06761d6 100644 --- a/app/assets/javascripts/surveys.js +++ b/app/assets/javascripts/surveys.js @@ -74,7 +74,7 @@ isSurveyToBeDisplayed: function(survey) { if (userSurveys.otherNotificationVisible() || - GOVUK.cookie(userSurveys.cookieNameTakenSurvey(survey)) === 'true') { + GOVUK.cookie(userSurveys.surveyTakenCookieName(survey)) === 'true') { return false; } else if (userSurveys.userCompletedTransaction()) { // We don't want any survey appearing for users who have completed a @@ -113,7 +113,7 @@ }, setCookieTakenSurvey: function (survey) { - GOVUK.cookie(userSurveys.cookieNameTakenSurvey(survey), true, { days: 30*4 }); + GOVUK.cookie(userSurveys.surveyTakenCookieName(survey), true, { days: 30*4 }); $("#user-satisfaction-survey").removeClass('visible').attr('aria-hidden', 'true'); }, @@ -124,12 +124,14 @@ otherNotificationVisible: function() { return $('#banner-notification:visible, #global-cookie-message:visible, #global-browser-prompt:visible').length > 0; }, - cookieNameTakenSurvey: function(survey) { + + surveyTakenCookieName: function(survey) { //user_satisfaction_survey => takenUserSatisfactionSurvey var cookieStr = "taken_" + survey.identifier; var cookieStub = cookieStr.replace(/(\_\w)/g, function(m){return m[1].toUpperCase();}); return "govuk_" + cookieStub; }, + currentTime: function() { return new Date().getTime(); } }; diff --git a/spec/javascripts/surveys-spec.js b/spec/javascripts/surveys-spec.js index 5de48fefa..18cb8ea8b 100644 --- a/spec/javascripts/surveys-spec.js +++ b/spec/javascripts/surveys-spec.js @@ -33,7 +33,7 @@ describe("Surveys", function() { }); afterEach(function () { - GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey), null); + GOVUK.cookie(surveys.surveyTakenCookieName(defaultSurvey), null); $block.remove(); }); @@ -83,7 +83,7 @@ describe("Surveys", function() { }); it("returns false if the 'survey taken' cookie is set", function () { - GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey), 'true'); + GOVUK.cookie(surveys.surveyTakenCookieName(defaultSurvey), 'true'); expect(surveys.isSurveyToBeDisplayed(defaultSurvey)).toBeFalsy(); }); @@ -106,12 +106,12 @@ describe("Surveys", function() { it("sets a cookie when clicking 'take survey'", function () { $('#take-survey').trigger('click'); - expect(GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey))).toBe('true'); + expect(GOVUK.cookie(surveys.surveyTakenCookieName(defaultSurvey))).toBe('true'); }); it("sets a cookie when clicking 'no thanks'", function () { $('#survey-no-thanks').trigger('click'); - expect(GOVUK.cookie(surveys.cookieNameTakenSurvey(defaultSurvey))).toBe('true'); + expect(GOVUK.cookie(surveys.surveyTakenCookieName(defaultSurvey))).toBe('true'); }); it("hides the satisfaction survey bar after clicking 'take survey'", function () { @@ -144,10 +144,10 @@ describe("Surveys", function() { }); }); - describe("cookieNameTakenSurvey", function() { + describe("surveyTakenCookieName", function() { it("returns a cookie name based on the survey identifier", function() { var surveyMock = {identifier: 'sample_survey'} - expect(surveys.cookieNameTakenSurvey(surveyMock)).toBe('govuk_takenSampleSurvey'); + expect(surveys.surveyTakenCookieName(surveyMock)).toBe('govuk_takenSampleSurvey'); }); }); From 9f9ec01fd8161fcaac298af8322bba233a51ef7f Mon Sep 17 00:00:00 2001 From: Neil van Beinum Date: Wed, 20 Jul 2016 11:20:57 +0100 Subject: [PATCH 8/9] Rename function in surveys module setCookieTakenSurvey -> setSurveyTakenCookie --- app/assets/javascripts/surveys.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js index 4e06761d6..c6bd6f1ae 100644 --- a/app/assets/javascripts/surveys.js +++ b/app/assets/javascripts/surveys.js @@ -61,13 +61,13 @@ var $takeSurvey = $('#take-survey'); $noThanks.click(function (e) { - userSurveys.setCookieTakenSurvey(survey); + userSurveys.setSurveyTakenCookie(survey); userSurveys.trackEvent(survey.identifier, 'banner_no_thanks', 'No thanks clicked'); e.stopPropagation(); return false; }); $takeSurvey.click(function () { - userSurveys.setCookieTakenSurvey(survey); + userSurveys.setSurveyTakenCookie(survey); userSurveys.trackEvent(survey.identifier, 'banner_taken', 'User taken survey'); }); }, @@ -112,7 +112,7 @@ }); }, - setCookieTakenSurvey: function (survey) { + setSurveyTakenCookie: function (survey) { GOVUK.cookie(userSurveys.surveyTakenCookieName(survey), true, { days: 30*4 }); $("#user-satisfaction-survey").removeClass('visible').attr('aria-hidden', 'true'); }, From ea0adc0c003d9584d96a8afa5f787396910305f4 Mon Sep 17 00:00:00 2001 From: Neil van Beinum Date: Wed, 20 Jul 2016 11:25:30 +0100 Subject: [PATCH 9/9] Remove a now-redundant html data attribute Survey link URLs are now contained within the survey metadata. --- app/views/root/_base.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/root/_base.html.erb b/app/views/root/_base.html.erb index 123e3e9e5..59f444263 100644 --- a/app/views/root/_base.html.erb +++ b/app/views/root/_base.html.erb @@ -23,7 +23,7 @@ <% end %> <% content_for :after_header do %> -
+
<% if @banner_notification.present? %> <%= @banner_notification %> <% end %>