From af1daf8dbbf3c64b8f82052671b2ef0fa668799f Mon Sep 17 00:00:00 2001 From: hannako Date: Fri, 18 Nov 2022 12:21:41 +0000 Subject: [PATCH 1/3] Add the button text to data attributes We need to update the button text via an ajax call to the account API. Storing the button text as data attributes makes them available to the js function that is amended in the next commit. --- .../single_page_notification_button_helper.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb b/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb index b953c787ce..db3a391c33 100644 --- a/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb +++ b/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb @@ -24,6 +24,8 @@ def data @data_attributes[:track_category] = "Single-page-notification-button" # This attribute is passed through to the personalisation API to ensure when a new button is returned from the API, it has the same button_location @data_attributes[:button_location] = button_location + @data_attributes[:button_text_subscribe] = button_text_subscribe + @data_attributes[:button_text_unsubscribe] = button_text_unsubscribe @data_attributes end @@ -32,7 +34,15 @@ def button_location_is_valid? end def button_text - @already_subscribed ? I18n.t("components.single_page_notification_button.unsubscribe_text") : I18n.t("components.single_page_notification_button.subscribe_text") + @already_subscribed ? button_text_unsubscribe : button_text_subscribe + end + + def button_text_subscribe + I18n.t("components.single_page_notification_button.subscribe_text") + end + + def button_text_unsubscribe + I18n.t("components.single_page_notification_button.unsubscribe_text") end end end From 209c34b32f941d778f5f891e619140925fdbbdab Mon Sep 17 00:00:00 2001 From: Hanna Laakso Date: Wed, 9 Nov 2022 19:34:26 +0000 Subject: [PATCH 2/3] Update notification button attributes from API No longer replace the entire single page notification button HTML from the personalisation API response. Instead, check the boolean "active" in the response: if active is true, user has subscribed to notifications. Update the tracking attribute on the button HTML according to the value of active in the API response. Append the value of data-button-location, if it is provided in the markup, to the tracking attribute value. Update the button text if both data-button-text-unsubscribe and data-button-text-subscribe are provided in the markup attributes Add a new wrapper class .gem-c-single-page-notication-button__text to more reliably target the button text. Add tests to check whether the tracking attribute, including optional location, and the custom button text are updated correctly upon receiving the API response. Remove some no longer relevant test classes (.old-button-for-test and .new-button-for-test) since the whole button is no longer being replaced. Add an additional test for checking that the button is rendered visible when the API call completes (the button is initially hidden when JS runs) --- .../single-page-notification-button.js | 32 ++++-- .../_single_page_notification_button.html.erb | 2 +- .../docs/single_page_notification_button.yml | 3 +- .../single-page-notification-button-spec.js | 108 ++++++++++++++++-- 4 files changed, 124 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js b/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js index a68060c2d1..13faee1536 100644 --- a/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +++ b/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js @@ -28,15 +28,31 @@ window.GOVUK.Modules = window.GOVUK.Modules || {}; if (xhr.readyState === 4) { if (xhr.status === 200) { var responseText = xhr.responseText - // if response text exists and is JSON parse-able, parse the response and get the button html + // if response text exists and is JSON parse-able, parse the response and update the button html if (responseText && this.responseIsJSON(responseText)) { - var newButton = JSON.parse(responseText).button_html - var html = document.createElement('div') - html.innerHTML = newButton - // test that the html returned contains the button component; if yes, swap the button for the updated version - var responseButtonContainer = html.querySelector('form.gem-c-single-page-notification-button') - if (responseButtonContainer) { - this.$module.parentNode.replaceChild(responseButtonContainer, this.$module) + var active = JSON.parse(responseText).active + + var customSubscribeText = this.$module.getAttribute('data-button-text-subscribe') + var customUnsubscribeText = this.$module.getAttribute('data-button-text-unsubscribe') + // Only set custom button text if both text items are provided + var customText = customSubscribeText && customUnsubscribeText + + // Append '-[button-location]' to the tracking data attribute value if data-button-location is set + var optionalButtonLocation = this.$module.getAttribute('data-button-location') ? '-' + this.$module.getAttribute('data-button-location') : '' + + // If response returns active, user has subscribed to notifications + if (active === true) { + this.$module.setAttribute('data-track-action', 'Unsubscribe-button' + optionalButtonLocation) + + if (customText) { + this.$module.querySelector('.gem-c-single-page-notication-button__text').textContent = customUnsubscribeText + } + } else { + this.$module.setAttribute('data-track-action', 'Subscribe-button' + optionalButtonLocation) + + if (customText) { + this.$module.querySelector('.gem-c-single-page-notication-button__text').textContent = customSubscribeText + } } } } diff --git a/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb b/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb index 9cb3a98ba4..7ad6ea88ec 100644 --- a/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb +++ b/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb @@ -6,7 +6,7 @@ wrapper_classes << shared_helper.get_margin_bottom %> <% button_text = capture do %> - <%= component_helper.button_text %> + <%= component_helper.button_text %> <% end %> <%= tag.div class: wrapper_classes, data: { module: "gem-track-click"} do %> <%= tag.form class: component_helper.classes, action: "/email/subscriptions/single-page/new", method: "POST", data: component_helper.data do %> diff --git a/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml b/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml index 145dbb52f1..a80419b612 100644 --- a/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +++ b/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml @@ -33,7 +33,8 @@ examples: margin_bottom: 5 with_js_enhancement: description: | - If the `js-enhancement` flag is present, the component uses JavaScript to check if the user has already subscribed to email notifications on the current page. If yes, the state of the component updates accordingly. + If the `js-enhancement` flag is present, the component uses JavaScript to check if the user has already subscribed to email notifications on the current page and accordingly updates its tracking attribute and (optionally) button text. + data: base_path: '/current-page-path' js_enhancement: true diff --git a/spec/javascripts/components/single-page-notification-button-spec.js b/spec/javascripts/components/single-page-notification-button-spec.js index 8402b64d1c..376a032db4 100644 --- a/spec/javascripts/components/single-page-notification-button-spec.js +++ b/spec/javascripts/components/single-page-notification-button-spec.js @@ -6,9 +6,9 @@ describe('Single page notification component', function () { beforeEach(function () { FIXTURE = - '
' + + '' + '' + - '' + + '' + '
' window.setFixtures(FIXTURE) jasmine.Ajax.install() @@ -27,7 +27,7 @@ describe('Single page notification component', function () { it('includes button_location in the call to the personalisation API when button_location is specified', function () { FIXTURE = - '
' + + '' + '' + '' + '
' @@ -39,17 +39,103 @@ describe('Single page notification component', function () { expect(request.method).toBe('GET') }) - it('replaces the button when the API returns button html', function () { + it('renders the button visible when API response is received', function () { + initButton() + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: '{\n "base_path": "/current-page-path",\n "active": false\n }' + }) + + var button = document.querySelector('form.gem-c-single-page-notification-button') + expect(button).toHaveClass('gem-c-single-page-notification-button--visible') + }) + + it('renders "Subscribe-button" tracking attribute value if "active" in the API response is false', function () { + initButton() + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: '{\n "base_path": "/current-page-path",\n "active": false\n }' + }) + + var buttonTrackingAttribute = document.querySelector('form.gem-c-single-page-notification-button').getAttribute('data-track-action') + expect(buttonTrackingAttribute).toBe('Subscribe-button') + }) + + it('renders "Unsubscribe-button" tracking attribute value if "active" in the API response is true', function () { + initButton() + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: '{\n "base_path": "/current-page-path",\n "active": true\n }' + }) + + var buttonTrackingAttribute = document.querySelector('form.gem-c-single-page-notification-button').getAttribute('data-track-action') + expect(buttonTrackingAttribute).toBe('Unsubscribe-button') + }) + + it('renders button location as part of the tracking attribute value when API response is received if "data-button-location" is set', function () { + FIXTURE = + '
' + + '' + + '' + + '
' + window.setFixtures(FIXTURE) + + initButton() + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: '{\n "base_path": "/current-page-path",\n "active": false\n }' + }) + + var buttonTrackingAttribute = document.querySelector('form.gem-c-single-page-notification-button').getAttribute('data-track-action') + expect(buttonTrackingAttribute).toBe('Subscribe-button-top') + }) + + it('renders custom subscribe button text when API response is received if "data-button-text-subscribe" and "data-button-text-unsubscribe" are set', function () { + FIXTURE = + '
' + + '' + + '' + + '
' + window.setFixtures(FIXTURE) + + initButton() + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: '{\n "base_path": "/current-page-path",\n "active": false\n }' + }) + + var button = document.querySelector('form.gem-c-single-page-notification-button') + expect(button).toHaveText('Start getting emails about this stuff') + }) + + it('renders custom unsubscribe button text when API response is received if "data-button-text-subscribe" and "data-button-text-unsubscribe" are set', function () { + FIXTURE = + '
' + + '' + + '' + + '
' + window.setFixtures(FIXTURE) + initButton() jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'application/json', - responseText: '{\n "base_path": "/current-page-path",\n "active": true,\n "button_html": "
\\n \\n \\n
"\n}' + responseText: '{\n "base_path": "/current-page-path",\n "active": true\n }' }) - var button = document.querySelector('form.gem-c-single-page-notification-button.new-button-for-test button') - expect(button).toHaveText('Stop getting emails about this page') + var button = document.querySelector('form.gem-c-single-page-notification-button') + expect(button).toHaveText('Stop getting emails about this stuff') }) it('should remain unchanged if the response is not JSON', function () { @@ -62,7 +148,7 @@ describe('Single page notification component', function () { responseText: responseText }) - var button = document.querySelector('form.gem-c-single-page-notification-button.old-button-for-test.gem-c-single-page-notification-button--visible button') + var button = document.querySelector('form.gem-c-single-page-notification-button.gem-c-single-page-notification-button--visible button') expect(button).toHaveText('Get emails about this page') expect(GOVUK.Modules.SinglePageNotificationButton.prototype.responseIsJSON(responseText)).toBe(false) }) @@ -77,7 +163,7 @@ describe('Single page notification component', function () { responseText: responseText }) - var button = document.querySelector('form.gem-c-single-page-notification-button.old-button-for-test.gem-c-single-page-notification-button--visible button') + var button = document.querySelector('form.gem-c-single-page-notification-button.gem-c-single-page-notification-button--visible button') expect(button).toHaveText('Get emails about this page') expect(GOVUK.Modules.SinglePageNotificationButton.prototype.responseIsJSON(responseText)).toBe(false) }) @@ -91,7 +177,7 @@ describe('Single page notification component', function () { responseText: '' }) - var button = document.querySelector('form.gem-c-single-page-notification-button.old-button-for-test.gem-c-single-page-notification-button--visible button') + var button = document.querySelector('form.gem-c-single-page-notification-button.gem-c-single-page-notification-button--visible button') expect(button).toHaveText('Get emails about this page') }) @@ -100,7 +186,7 @@ describe('Single page notification component', function () { initButton() jasmine.Ajax.requests.mostRecent().responseTimeout() - var button = document.querySelector('form.gem-c-single-page-notification-button.old-button-for-test.gem-c-single-page-notification-button--visible button') + var button = document.querySelector('form.gem-c-single-page-notification-button.gem-c-single-page-notification-button--visible button') expect(button).toHaveText('Get emails about this page') jasmine.clock().uninstall() }) From d9f2ccf779d99f1ae4d2df87a3aaac2ae32e7b87 Mon Sep 17 00:00:00 2001 From: Hanna Laakso Date: Tue, 22 Nov 2022 18:04:45 +0000 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0bec66878..ef5a67c475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Share links allow data attributes ([PR #3072](https://github.com/alphagov/govuk_publishing_components/pull/3072)) * Update to LUX 304 ([PR #3070](https://github.com/alphagov/govuk_publishing_components/pull/3070)) +* Set attributes for single page notification button based on Account API response ([PR #3071](https://github.com/alphagov/govuk_publishing_components/pull/3071)) ## 32.1.0