mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-20 14:29:51 -04:00
Merge pull request #3106 from alphagov/add-js-tests-for-preview-pane
Add js tests for preview pane
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
(function () {
|
(function (global) {
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const root = this,
|
$ = global.jQuery;
|
||||||
$ = this.jQuery;
|
|
||||||
|
|
||||||
let branding_style = $('.multiple-choice input[name="branding_style"]:checked');
|
let branding_style = $('.multiple-choice input[name="branding_style"]:checked');
|
||||||
|
|
||||||
@@ -34,4 +33,4 @@
|
|||||||
$form.find('button[type="submit"]').text('Save');
|
$form.find('button[type="submit"]').text('Save');
|
||||||
|
|
||||||
$('fieldset').on('change', 'input[name="branding_style"]', setPreviewPane);
|
$('fieldset').on('change', 'input[name="branding_style"]', setPreviewPane);
|
||||||
})();
|
})(window);
|
||||||
|
|||||||
234
tests/javascripts/previewPane.test.js
Normal file
234
tests/javascripts/previewPane.test.js
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
const helpers = require('./support/helpers.js');
|
||||||
|
|
||||||
|
const emailPageURL = '/services/6658542f-0cad-491f-bec8-ab8457700ead/service-settings/set-email-branding';
|
||||||
|
const emailPreviewConfirmationURL = '/services/6658542f-0cad-491f-bec8-ab8457700ead/service-settings/preview-email-branding';
|
||||||
|
const letterPageURL = '/services/6658542f-0cad-491f-bec8-ab8457700ead/service-settings/set-letter-branding';
|
||||||
|
const letterPreviewConfirmationURL = '/services/6658542f-0cad-491f-bec8-ab8457700ead/service-settings/preview-letter-branding';
|
||||||
|
|
||||||
|
let locationMock;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
|
||||||
|
// mock calls to window.location
|
||||||
|
// default to the email page, the pathname can be changed inside specific tests
|
||||||
|
locationMock = new helpers.LocationMock(emailPageURL);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
|
||||||
|
// reset window.location to its original state
|
||||||
|
locationMock.reset();
|
||||||
|
require('./support/teardown.js');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Preview pane', () => {
|
||||||
|
|
||||||
|
let form;
|
||||||
|
let radios;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
const brands = {
|
||||||
|
"name": "branding_style",
|
||||||
|
"label": "Branding style",
|
||||||
|
"cssClasses": [],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"label": "Department for Education",
|
||||||
|
"value": "dfe",
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Home Office",
|
||||||
|
"value": "ho",
|
||||||
|
"checked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Her Majesty's Revenue and Customs",
|
||||||
|
"value": "hmrc",
|
||||||
|
"checked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Department for Work and Pensions",
|
||||||
|
"value": "dwp",
|
||||||
|
"checked": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// set up DOM
|
||||||
|
document.body.innerHTML =
|
||||||
|
`<form method="post" action="${emailPageURL}" autocomplete="off" data-preview-type="email" novalidate>
|
||||||
|
<div class="grid-row"></div>
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="column-full">
|
||||||
|
<div data-module="autofocus">
|
||||||
|
<div class="live-search js-header" data-module="live-search" data-targets=".multiple-choice">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="search">
|
||||||
|
Search branding styles by name
|
||||||
|
</label>
|
||||||
|
<input autocomplete="off" class="form-control form-control-1-1 " id="search" name="search" required="" rows="8" type="search" value="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="page-footer">
|
||||||
|
<button type="submit" class="button">Preview</button>
|
||||||
|
</div>
|
||||||
|
</form>`;
|
||||||
|
|
||||||
|
document.querySelector('.column-full').appendChild(helpers.getRadioGroup(brands));
|
||||||
|
form = document.querySelector('form');
|
||||||
|
radios = form.querySelector('fieldset');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
|
||||||
|
document.body.innerHTML = '';
|
||||||
|
|
||||||
|
// we run the previewPane.js script every test
|
||||||
|
// the module cache needs resetting each time for the script to execute
|
||||||
|
jest.resetModules();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("If the page type is 'email'", () => {
|
||||||
|
|
||||||
|
describe("When the page loads", () => {
|
||||||
|
|
||||||
|
test("it should add the preview pane", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
expect(document.querySelector('iframe')).not.toBeNull();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it should change the form to submit the selection instead of posting to a preview page", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
expect(form.getAttribute('action')).toEqual(emailPreviewConfirmationURL);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("the preview pane should show the page for the selected brand", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
const selectedValue = Array.from(radios.querySelectorAll('input[type=radio]')).filter(radio => radio.checked)[0].value;
|
||||||
|
|
||||||
|
expect(document.querySelector('iframe').getAttribute('src')).toEqual(`/_email?branding_style=${selectedValue}`);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("the submit button should change from 'Preview' to 'Save'", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
expect(document.querySelector('button[type=submit]').textContent).toEqual('Save');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("If the selection changes", () => {
|
||||||
|
|
||||||
|
test("the page shown should match the selected brand", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
const newSelection = radios.querySelectorAll('input[type=radio]')[1];
|
||||||
|
|
||||||
|
helpers.moveSelectionToRadio(newSelection);
|
||||||
|
|
||||||
|
expect(document.querySelector('iframe').getAttribute('src')).toEqual(`/_email?branding_style=${newSelection.value}`);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("If the page type is 'letter'", () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
// set page URL and page type to 'letter'
|
||||||
|
window.location.pathname = letterPreviewConfirmationURL;
|
||||||
|
form.setAttribute('data-preview-type', 'letter');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("When the page loads", () => {
|
||||||
|
|
||||||
|
test("it should add the preview pane", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
expect(document.querySelector('iframe')).not.toBeNull();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it should change the form to submit the selection instead of posting to a preview page", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
expect(form.getAttribute('action')).toEqual(letterPreviewConfirmationURL);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("the preview pane should show the page for the selected brand", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
const selectedValue = Array.from(radios.querySelectorAll('input[type=radio]')).filter(radio => radio.checked)[0].value;
|
||||||
|
|
||||||
|
expect(document.querySelector('iframe').getAttribute('src')).toEqual(`/_letter?branding_style=${selectedValue}`);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("the submit button should change from 'Preview' to 'Save'", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
expect(document.querySelector('button[type=submit]').textContent).toEqual('Save');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("If the selection changes", () => {
|
||||||
|
|
||||||
|
test("the page shown should match the selected brand", () => {
|
||||||
|
|
||||||
|
// run preview pane script
|
||||||
|
require('../../app/assets/javascripts/previewPane.js');
|
||||||
|
|
||||||
|
const newSelection = radios.querySelectorAll('input[type=radio]')[1];
|
||||||
|
|
||||||
|
helpers.moveSelectionToRadio(newSelection);
|
||||||
|
|
||||||
|
expect(document.querySelector('iframe').getAttribute('src')).toEqual(`/_letter?branding_style=${newSelection.value}`);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -472,8 +472,8 @@ describe("Stick to top/bottom of window when scrolling", () => {
|
|||||||
// add another sticky element before the form footer
|
// add another sticky element before the form footer
|
||||||
radios = helpers.getRadioGroup({
|
radios = helpers.getRadioGroup({
|
||||||
cssClasses: ['js-stick-at-top-when-scrolling'],
|
cssClasses: ['js-stick-at-top-when-scrolling'],
|
||||||
name: 'send-time',
|
name: 'choose-send-time',
|
||||||
label: 'send time',
|
label: 'Choose send time',
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: 'Now',
|
label: 'Now',
|
||||||
@@ -604,7 +604,7 @@ describe("Stick to top/bottom of window when scrolling", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
radios.querySelector('fieldset').insertAdjacentHTML('beforeend', helpers.getRadios(fields));
|
radios.querySelector('fieldset').insertAdjacentHTML('beforeend', helpers.getRadios(fields, 'days'));
|
||||||
|
|
||||||
radios.offsetHeight = 475;
|
radios.offsetHeight = 475;
|
||||||
|
|
||||||
@@ -1146,8 +1146,8 @@ describe("Stick to top/bottom of window when scrolling", () => {
|
|||||||
// add another sticky element before the form footer
|
// add another sticky element before the form footer
|
||||||
radios = helpers.getRadioGroup({
|
radios = helpers.getRadioGroup({
|
||||||
cssClasses: ['js-stick-at-bottom-when-scrolling'],
|
cssClasses: ['js-stick-at-bottom-when-scrolling'],
|
||||||
name: 'send-time',
|
name: 'choose-send-time',
|
||||||
label: 'Send time',
|
label: 'Choose send time',
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: 'Now',
|
label: 'Now',
|
||||||
@@ -1280,7 +1280,7 @@ describe("Stick to top/bottom of window when scrolling", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
radios.querySelector('fieldset').insertAdjacentHTML('beforeend', helpers.getRadios(fields));
|
radios.querySelector('fieldset').insertAdjacentHTML('beforeend', helpers.getRadios(fields, 'days'));
|
||||||
|
|
||||||
radios.offsetHeight = 475;
|
radios.offsetHeight = 475;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const globals = require('./helpers/globals.js');
|
||||||
const events = require('./helpers/events.js');
|
const events = require('./helpers/events.js');
|
||||||
const domInterfaces = require('./helpers/dom_interfaces.js');
|
const domInterfaces = require('./helpers/dom_interfaces.js');
|
||||||
const html = require('./helpers/html.js');
|
const html = require('./helpers/html.js');
|
||||||
@@ -6,6 +7,7 @@ const rendering = require('./helpers/rendering.js');
|
|||||||
const forms = require('./helpers/forms.js');
|
const forms = require('./helpers/forms.js');
|
||||||
const utilities = require('./helpers/utilities.js');
|
const utilities = require('./helpers/utilities.js');
|
||||||
|
|
||||||
|
exports.LocationMock = globals.LocationMock;
|
||||||
exports.triggerEvent = events.triggerEvent;
|
exports.triggerEvent = events.triggerEvent;
|
||||||
exports.clickElementWithMouse = events.clickElementWithMouse;
|
exports.clickElementWithMouse = events.clickElementWithMouse;
|
||||||
exports.moveSelectionToRadio = events.moveSelectionToRadio;
|
exports.moveSelectionToRadio = events.moveSelectionToRadio;
|
||||||
|
|||||||
89
tests/javascripts/support/helpers/globals.js
Normal file
89
tests/javascripts/support/helpers/globals.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// helpers for mocking objects attached to the global space as properties, ie. window.location
|
||||||
|
|
||||||
|
class LocationMock {
|
||||||
|
|
||||||
|
constructor (URL) {
|
||||||
|
|
||||||
|
this._location = window.location;
|
||||||
|
|
||||||
|
// setting href sets all sub-properties
|
||||||
|
this.href = URL;
|
||||||
|
|
||||||
|
// JSDOM sets window.location as non-configurable
|
||||||
|
// the only way to mock it, currently, is to replace it completely
|
||||||
|
delete window.location;
|
||||||
|
window.location = this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get href () {
|
||||||
|
|
||||||
|
return `${this.protocol}://${this.host}${this.pathname}${this.search}${this.hash}`
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
set href (value) {
|
||||||
|
|
||||||
|
const partNames = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash'];
|
||||||
|
|
||||||
|
const protocol = '(https:|http:)';
|
||||||
|
const hostname = '[^\\/]+';
|
||||||
|
const port = '(:\\d)';
|
||||||
|
const pathname = '([^?]+)';
|
||||||
|
const search = '([^#])';
|
||||||
|
const hash = '(#[\\x00-\\x7F])'; // match any ASCII character
|
||||||
|
|
||||||
|
const re = new RegExp(`^${protocol}{0,1}(?:\\/\\/){0,1}(${hostname}${port}{0,1}){0,1}${pathname}{0,1}${search}{0,1}${hash}{0,1}$`);
|
||||||
|
const match = value.match(re)
|
||||||
|
|
||||||
|
if (match === null) { throw Error(`${value} is not a valid URL`); }
|
||||||
|
|
||||||
|
match.forEach((part, idx) => {
|
||||||
|
|
||||||
|
let partName;
|
||||||
|
|
||||||
|
// 0 index is whole match, we want the groups
|
||||||
|
if (idx > 0) {
|
||||||
|
partName = partNames[idx - 1];
|
||||||
|
|
||||||
|
if (part !== undefined) {
|
||||||
|
this[partName] = part;
|
||||||
|
} else if (!(partName in this)) { // only get value from window.location if property not set
|
||||||
|
this[partName] = this._location[partName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get host () {
|
||||||
|
|
||||||
|
return `${this.hostname}:${this.port}`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
set host (value) {
|
||||||
|
|
||||||
|
const parts = value.split(':');
|
||||||
|
|
||||||
|
this.hostname = parts[0];
|
||||||
|
this.protocol = parts[1];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// origin is read-only
|
||||||
|
get origin () {
|
||||||
|
|
||||||
|
return `${this.protol}://${this.hostname}`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
reset () {
|
||||||
|
|
||||||
|
window.location = this._location;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.LocationMock = LocationMock;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// helpers for generating patterns of HTML
|
// helpers for generating patterns of HTML
|
||||||
|
|
||||||
function getRadios (fields) {
|
function getRadios (fields, name) {
|
||||||
const result = '';
|
const result = '';
|
||||||
|
|
||||||
return fields.map((field, idx) => {
|
return fields.map((field, idx) => {
|
||||||
@@ -8,8 +8,8 @@ function getRadios (fields) {
|
|||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="multiple-choice">
|
<div class="multiple-choice">
|
||||||
<input id="choose-${field.name}-1" name="choose-${field.name}-1" type="radio" value="${field.value}" ${field.checked ? 'checked' : ''}>
|
<input id="${name}-1" name="${name}" type="radio" value="${field.value}" ${field.checked ? 'checked' : ''}>
|
||||||
<label class="block-label" for="choose-${field.name}-1">
|
<label class="block-label" for="${name}-1">
|
||||||
${field.label}
|
${field.label}
|
||||||
</label>
|
</label>
|
||||||
</div>`;
|
</div>`;
|
||||||
@@ -22,11 +22,11 @@ function getRadioGroup (data) {
|
|||||||
data.cssClasses.forEach(cssClass => radioGroup.classList.add(cssClass));
|
data.cssClasses.forEach(cssClass => radioGroup.classList.add(cssClass));
|
||||||
radioGroup.innerHTML = `
|
radioGroup.innerHTML = `
|
||||||
<div class="form-group ">
|
<div class="form-group ">
|
||||||
<fieldset id="choose-${data.name}">
|
<fieldset id="${data.name}">
|
||||||
<legend class="form-label">
|
<legend class="form-label">
|
||||||
Choose ${data.label}
|
${data.label}
|
||||||
</legend>
|
</legend>
|
||||||
${getRadios(data.fields)}
|
${getRadios(data.fields, data.name)}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user