mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-24 00:07:02 -04:00
Merge pull request #3110 from alphagov/add-js-tests-for-update-content
Add JS tests for update content
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
(function(Modules) {
|
(function(global) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var queues = {};
|
var queues = {};
|
||||||
var dd = new diffDOM();
|
var dd = new global.diffDOM();
|
||||||
|
|
||||||
var getRenderer = $component => response => dd.apply(
|
var getRenderer = $component => response => dd.apply(
|
||||||
$component.get(0),
|
$component.get(0),
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Modules.UpdateContent = function() {
|
global.GOVUK.Modules.UpdateContent = function() {
|
||||||
|
|
||||||
this.start = component => poll(
|
this.start = component => poll(
|
||||||
getRenderer($(component)),
|
getRenderer($(component)),
|
||||||
@@ -55,4 +55,4 @@
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
})(window.GOVUK.Modules);
|
})(window);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const html = require('./helpers/html.js');
|
|||||||
const elements = require('./helpers/elements.js');
|
const elements = require('./helpers/elements.js');
|
||||||
const rendering = require('./helpers/rendering.js');
|
const rendering = require('./helpers/rendering.js');
|
||||||
const forms = require('./helpers/forms.js');
|
const forms = require('./helpers/forms.js');
|
||||||
|
const utilities = require('./helpers/utilities.js');
|
||||||
|
|
||||||
exports.triggerEvent = events.triggerEvent;
|
exports.triggerEvent = events.triggerEvent;
|
||||||
exports.clickElementWithMouse = events.clickElementWithMouse;
|
exports.clickElementWithMouse = events.clickElementWithMouse;
|
||||||
@@ -18,3 +19,4 @@ exports.element = elements.element;
|
|||||||
exports.WindowMock = rendering.WindowMock;
|
exports.WindowMock = rendering.WindowMock;
|
||||||
exports.ScreenMock = rendering.ScreenMock;
|
exports.ScreenMock = rendering.ScreenMock;
|
||||||
exports.spyOnFormSubmit = forms.spyOnFormSubmit;
|
exports.spyOnFormSubmit = forms.spyOnFormSubmit;
|
||||||
|
exports.getFormDataFromPairs = utilities.getFormDataFromPairs;
|
||||||
|
|||||||
22
tests/javascripts/support/helpers/utilities.js
Normal file
22
tests/javascripts/support/helpers/utilities.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// general helpers, not related to the DOM and usable in different contexts
|
||||||
|
|
||||||
|
// turn a list of key=value pairs (like tuples) into data that can be sent via AJAX
|
||||||
|
// taken from https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript
|
||||||
|
// but requiring an array as input rather than a hash, to preserve order of pairs
|
||||||
|
function getFormDataFromPairs (pairs) {
|
||||||
|
|
||||||
|
const urlEncodedDataPairs = [];
|
||||||
|
|
||||||
|
pairs.forEach(pair => {
|
||||||
|
|
||||||
|
urlEncodedDataPairs.push(`${window.encodeURIComponent(pair[0])}=${window.encodeURIComponent(pair[1])}`);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Combine the pairs into a single string and replace all %-encoded spaces to
|
||||||
|
// the '+' character; matches the behaviour of browser form submissions.
|
||||||
|
return urlEncodedDataPairs.join('&').replace(/%20/g, '+');
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getFormDataFromPairs = getFormDataFromPairs;
|
||||||
225
tests/javascripts/updateContent.test.js
Normal file
225
tests/javascripts/updateContent.test.js
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
const helpers = require('./support/helpers.js');
|
||||||
|
|
||||||
|
const serviceNumber = '6658542f-0cad-491f-bec8-ab8457700ead';
|
||||||
|
const resourceURL = `/services/${serviceNumber}/notifications/email.json?status=sending%2Cdelivered%2Cfailed`;
|
||||||
|
const updateKey = 'counts';
|
||||||
|
|
||||||
|
let responseObj = {};
|
||||||
|
let jqueryAJAXReturnObj;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
|
||||||
|
// ensure all timers go through Jest
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
// mock the bits of jQuery used
|
||||||
|
jest.spyOn(window.$, 'ajax');
|
||||||
|
|
||||||
|
// set up the object returned from $.ajax so it responds with whatever responseObj is set to
|
||||||
|
jqueryAJAXReturnObj = {
|
||||||
|
done: callback => {
|
||||||
|
callback(responseObj);
|
||||||
|
return jqueryAJAXReturnObj;
|
||||||
|
},
|
||||||
|
fail: () => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.ajax.mockImplementation(() => jqueryAJAXReturnObj);
|
||||||
|
|
||||||
|
// because we're running in node, diffDOM executes as a module
|
||||||
|
// in the normal browser environment it will attach to window so we replicate that here
|
||||||
|
window.diffDOM = require('../../node_modules/diff-dom/diffDOM.js');
|
||||||
|
require('../../app/assets/javascripts/updateContent.js');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
require('./support/teardown.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Update content', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
// store HTML in string to allow use in AJAX responses
|
||||||
|
HTMLString = `
|
||||||
|
<div data-module="update-content" data-resource="${resourceURL}" data-key="${updateKey}" aria-live="polite">
|
||||||
|
<div class="bottom-gutter ajax-block-container">
|
||||||
|
<ul role="tablist" class="pill">
|
||||||
|
<li aria-selected="true" role="tab">
|
||||||
|
<div class="pill-selected-item" tabindex="0">
|
||||||
|
<div class="big-number-smaller">
|
||||||
|
<div class="big-number-number">0</div>
|
||||||
|
</div>
|
||||||
|
<div class="pill-label">total</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li aria-selected="false" role="tab">
|
||||||
|
<a href="/services/6658542f-0cad-491f-bec8-ab8457700ead/notifications/email?status=sending">
|
||||||
|
<div class="big-number-smaller">
|
||||||
|
<div class="big-number-number">0</div>
|
||||||
|
</div>
|
||||||
|
<div class="pill-label">sending</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li aria-selected="false" role="tab">
|
||||||
|
<a href="/services/6658542f-0cad-491f-bec8-ab8457700ead/notifications/email?status=delivered">
|
||||||
|
<div class="big-number-smaller">
|
||||||
|
<div class="big-number-number">0</div>
|
||||||
|
</div>
|
||||||
|
<div class="pill-label">delivered</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li aria-selected="false" role="tab">
|
||||||
|
<a href="/services/6658542f-0cad-491f-bec8-ab8457700ead/notifications/email?status=failed">
|
||||||
|
<div class="big-number-smaller">
|
||||||
|
<div class="big-number-number">0</div>
|
||||||
|
</div>
|
||||||
|
<div class="pill-label">failed</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
document.body.innerHTML = HTMLString;
|
||||||
|
|
||||||
|
// default the response to match the existing content
|
||||||
|
responseObj[updateKey] = HTMLString;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
|
||||||
|
document.body.innerHTML = '';
|
||||||
|
|
||||||
|
// tidy up record of mocked AJAX calls
|
||||||
|
$.ajax.mockClear();
|
||||||
|
|
||||||
|
// ensure any timers set by continually starting the module are cleared
|
||||||
|
jest.clearAllTimers();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("It should make requests to the URL specified in the data-resource attribute", () => {
|
||||||
|
|
||||||
|
// start the module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
expect($.ajax.mock.calls[0][0]).toEqual(resourceURL);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("If the response contains no changes, the DOM should stay the same", () => {
|
||||||
|
|
||||||
|
// send the done callback a response with updates included
|
||||||
|
responseObj[updateKey] = HTMLString;
|
||||||
|
|
||||||
|
// start the module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
// check the right DOM node is updated
|
||||||
|
expect(document.querySelectorAll('.big-number-number')[0].textContent.trim()).toEqual("0");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("If the response contains changes, it should update the DOM with them", () => {
|
||||||
|
|
||||||
|
// send the done callback a response with updates included
|
||||||
|
responseObj[updateKey] = HTMLString.replace(/<div class="big-number-number">0<\/div>{1}/, '<div class="big-number-number">1</div>');
|
||||||
|
|
||||||
|
// start the module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
// check the right DOM node is updated
|
||||||
|
expect(document.querySelectorAll('.big-number-number')[0].textContent.trim()).toEqual("1");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("If an interval between requests is specified, using the data-interval-seconds attribute, requests should happen at that frequency", () => {
|
||||||
|
|
||||||
|
document.querySelector('[data-module=update-content]').setAttribute('data-interval-seconds', '0.5');
|
||||||
|
|
||||||
|
// start the module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
expect($.ajax).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
// units are milliseconds
|
||||||
|
jest.advanceTimersByTime(500);
|
||||||
|
jest.advanceTimersByTime(500);
|
||||||
|
jest.advanceTimersByTime(500);
|
||||||
|
|
||||||
|
expect($.ajax).toHaveBeenCalledTimes(4);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("By default", () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
// start the module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("It should use the GET HTTP method", () => {
|
||||||
|
|
||||||
|
expect($.ajax.mock.calls[0][1].method).toEqual('get');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("It shouldn't send any data as part of the requests", () => {
|
||||||
|
|
||||||
|
expect($.ajax.mock.calls[0][1].data).toEqual({});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("It should request updates every 1.5 seconds", () => {
|
||||||
|
|
||||||
|
expect($.ajax).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
// units are milliseconds
|
||||||
|
jest.advanceTimersByTime(1500);
|
||||||
|
|
||||||
|
expect($.ajax).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("If a form is used as a source for data, referenced in the data-form attribute", () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
document.body.innerHTML += `
|
||||||
|
<form method="post" id="service">
|
||||||
|
<input type="hidden" name="serviceName" value="Buckhurst surgery" />
|
||||||
|
<input type="hidden" name="serviceNumber" value="${serviceNumber}" />
|
||||||
|
</form>`;
|
||||||
|
|
||||||
|
document.querySelector('[data-module=update-content]').setAttribute('data-form', 'service');
|
||||||
|
|
||||||
|
// start the module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("requests should use the same HTTP method as the form", () => {
|
||||||
|
|
||||||
|
expect($.ajax.mock.calls[0][1].method).toEqual('post');
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
test("requests should use the data from the form", () => {
|
||||||
|
|
||||||
|
expect($.ajax.mock.calls[0][1].data).toEqual(helpers.getFormDataFromPairs([
|
||||||
|
['serviceName', 'Buckhurst surgery'],
|
||||||
|
['serviceNumber', serviceNumber]
|
||||||
|
]));
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user