mirror of
https://github.com/GSA/notifications-admin.git
synced 2025-12-16 01:53:56 -05:00
897 lines
28 KiB
JavaScript
897 lines
28 KiB
JavaScript
const helpers = require('./support/helpers');
|
|
|
|
function setFixtures (hierarchy, newTemplateDataModules = "") {
|
|
|
|
const foldersCheckboxesHTML = function (filter) {
|
|
let count = 0;
|
|
|
|
// use closure to give all calls access to count
|
|
return function (nodes) {
|
|
let result = '';
|
|
|
|
nodes
|
|
.filter(node => node.type === 'folder')
|
|
.forEach(node => {
|
|
result += `<li class="multiple-choice">
|
|
<input id="node-${count}" name="move_to" type="radio" value="node-${count}">
|
|
<label class="usa-label" for="node-${count}">
|
|
${node.label}
|
|
</label>
|
|
${node.children ? foldersCheckboxesHTML(node.children) : ''}
|
|
</li>`;
|
|
count++;
|
|
});
|
|
|
|
return `<ul>${result}</ul>`;
|
|
};
|
|
|
|
}();
|
|
|
|
function controlsHTML (newTemplateDataModules) {
|
|
|
|
return `<div id="sticky_template_forms">
|
|
<button type="submit" name="operation" value="unknown" hidden=""></button>
|
|
<div id="move_to_folder_radios" class="sticky-template-form" role="region" aria-label="Choose the folder to move selected items to">
|
|
<div class="js-will-stick-at-bottom-when-scrolling">
|
|
<div class="form-group ">
|
|
<fieldset id="move_to">
|
|
<legend class="form-label">
|
|
Choose a folder
|
|
</legend>
|
|
<div class="radios-nested">
|
|
${foldersCheckboxesHTML(hierarchy)}
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
</div>
|
|
<div class="js-will-stick-at-bottom-when-scrolling">
|
|
<div class="page-footer">
|
|
<button type="submit" class="usa-button" name="operation" value="move-to-existing-folder">Move</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="move_to_new_folder_form" class="sticky-template-form" role="region" aria-label="Enter name of the new folder to move selected items to">
|
|
<div class="js-will-stick-at-bottom-when-scrolling">
|
|
<div class="usa-form-group">
|
|
<label class="usa-label" for="move_to_new_folder_name">
|
|
Folder name
|
|
</label>
|
|
<input class="usa-input " id="move_to_new_folder_name" name="move_to_new_folder_name" type="text">
|
|
</div>
|
|
<div class="page-footer">
|
|
<button type="submit" class="usa-button" name="operation" value="move-to-new-folder">Add to new folder</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="add_new_folder_form" class="sticky-template-form" role="region" aria-label="Enter name of the new folder">
|
|
<div class="js-will-stick-at-bottom-when-scrolling">
|
|
<div class="usa-form-group">
|
|
<label class="usa-label" for="add_new_folder_name">
|
|
Folder name
|
|
</label>
|
|
<input class="usa-input " id="add_new_folder_name" name="add_new_folder_name" type="text">
|
|
</div>
|
|
<div class="page-footer">
|
|
<button type="submit" class="usa-button page-footer__button" name="operation" value="add-new-folder">Add new folder</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="add_new_template_form" class="sticky-template-form" role="region" aria-label="Choose template type" ${newTemplateDataModules}>
|
|
<div class="js-will-stick-at-bottom-when-scrolling">
|
|
<div class="form-group ">
|
|
<fieldset id="add_template_by_template_type">
|
|
<legend class="form-label">
|
|
New template
|
|
</legend>
|
|
<div class="multiple-choice">
|
|
<input id="add_template_by_template_type-0" name="add_template_by_template_type" type="radio" value="email">
|
|
<label class="usa-label" for="add_template_by_template_type-0">
|
|
Email
|
|
</label>
|
|
</div>
|
|
<div class="multiple-choice">
|
|
<input id="add_template_by_template_type-1" name="add_template_by_template_type" type="radio" value="sms">
|
|
<label class="usa-label" for="add_template_by_template_type-1">
|
|
Text message
|
|
</label>
|
|
</div>
|
|
<div class="multiple-choice">
|
|
<input id="add_template_by_template_type-2" name="add_template_by_template_type" type="radio" value="letter">
|
|
<label class="usa-label" for="add_template_by_template_type-2">
|
|
Letter
|
|
</label>
|
|
</div>
|
|
<div class="multiple-choice">
|
|
<input id="add_template_by_template_type-3" name="add_template_by_template_type" type="radio" value="copy-existing">
|
|
<label class="usa-label" for="add_template_by_template_type-3">
|
|
Copy an existing template
|
|
</label>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
</div>
|
|
<div class="js-will-stick-at-bottom-when-scrolling">
|
|
<div class="page-footer">
|
|
<button type="submit" class="usa-button page-footer__button" name="operation" value="add-new-template">Continue</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="selection-counter visuallyhidden" role="status" aria-live="polite">
|
|
Nothing selected
|
|
</div>
|
|
</div>`
|
|
};
|
|
|
|
document.body.innerHTML = `
|
|
<form method="post" data-module="template-folder-form">
|
|
${helpers.templatesAndFoldersCheckboxes(hierarchy)}
|
|
${controlsHTML(newTemplateDataModules)}
|
|
</form>`;
|
|
|
|
};
|
|
|
|
function resetStickyMocks () {
|
|
|
|
GOVUK.stickAtBottomWhenScrolling.recalculate.mockClear();
|
|
GOVUK.stickAtBottomWhenScrolling.setMode.mockClear();
|
|
|
|
};
|
|
|
|
beforeAll(() => {
|
|
require('../../app/assets/javascripts/templateFolderForm.js');
|
|
|
|
// plug JSDOM's lack of support for window.scrollTo
|
|
window.scrollTo = () => {};
|
|
});
|
|
|
|
afterAll(() => {
|
|
require('./support/teardown.js');
|
|
|
|
// tidy up
|
|
delete window.scrollTo;
|
|
});
|
|
|
|
describe('TemplateFolderForm', () => {
|
|
|
|
const hierarchy = [
|
|
{
|
|
'label': 'Folder 1',
|
|
'type': 'folder',
|
|
'meta': '1 template, 1 folder',
|
|
'children': [
|
|
{
|
|
'label': 'Template 3',
|
|
'type': 'template',
|
|
'meta': 'Email template'
|
|
},
|
|
{
|
|
'label': 'Folder 2',
|
|
'type': 'folder',
|
|
'meta': 'Empty',
|
|
'children': []
|
|
}
|
|
]
|
|
},
|
|
{
|
|
'label': 'Template 1',
|
|
'type': 'Email template',
|
|
'meta': 'Email template'
|
|
},
|
|
{
|
|
'label': 'Template 2',
|
|
'type': 'template',
|
|
'meta': 'Email template'
|
|
}
|
|
];
|
|
|
|
let templateFolderForm;
|
|
let formControls;
|
|
let visibleCounter;
|
|
let hiddenCounter;
|
|
|
|
beforeAll(() => {
|
|
|
|
// stub out calls to sticky JS
|
|
GOVUK.stickAtBottomWhenScrolling = {
|
|
setMode: jest.fn(),
|
|
recalculate: jest.fn()
|
|
};
|
|
|
|
});
|
|
|
|
afterAll(() => {
|
|
|
|
GOVUK.stickAtBottomWhenScrolling = undefined;
|
|
|
|
});
|
|
|
|
beforeEach(() => {
|
|
|
|
setFixtures(hierarchy);
|
|
|
|
templateFolderForm = document.querySelector('form[data-module=template-folder-form]');
|
|
|
|
});
|
|
|
|
afterEach(() => {
|
|
|
|
document.body.innerHTML = '';
|
|
|
|
});
|
|
|
|
function getTemplateFolderCheckboxes () {
|
|
return templateFolderForm.querySelectorAll('.usa-checkbox__label');
|
|
};
|
|
|
|
function getVisibleCounter () {
|
|
return formControls.querySelector('.template-list-selected-counter__count');
|
|
};
|
|
|
|
function getHiddenCounter () {
|
|
return formControls.querySelector('[role=status]');
|
|
};
|
|
|
|
describe("Before the module starts", () => {
|
|
|
|
// We need parts of the module to be made sticky, but by the module code,
|
|
// not the sticky JS code that operates on the HTML at page load.
|
|
// Because of this, they will need to be marked with classes
|
|
test("the HTML for the module should contain placeholder classes on each part that needs to be sticky", () => {
|
|
|
|
expect(templateFolderForm.querySelectorAll('#move_to_folder_radios > .js-will-stick-at-bottom-when-scrolling').length).toEqual(2);
|
|
expect(templateFolderForm.querySelector('#move_to_new_folder_form > .js-will-stick-at-bottom-when-scrolling')).not.toBeNull();
|
|
expect(templateFolderForm.querySelector('#add_new_folder_form > .js-will-stick-at-bottom-when-scrolling')).not.toBeNull();
|
|
expect(templateFolderForm.querySelectorAll('#add_new_template_form > .js-will-stick-at-bottom-when-scrolling').length).toEqual(2);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("When the module starts", () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
// start module
|
|
window.GOVUK.modules.start();
|
|
|
|
formControls = templateFolderForm.querySelector('#sticky_template_forms');
|
|
visibleCounter = getVisibleCounter();
|
|
|
|
});
|
|
|
|
afterEach(() => resetStickyMocks());
|
|
|
|
test("the default controls and the counter should be showing", () => {
|
|
|
|
expect(document.querySelector('button[value=add-new-template]')).not.toBeNull();
|
|
expect(document.querySelector('button[value=add-new-folder]')).not.toBeNull();
|
|
expect(document.querySelector('button[value=add-new-template]').getAttribute('aria-expanded')).toEqual('false');
|
|
expect(document.querySelector('button[value=add-new-folder]').getAttribute('aria-expanded')).toEqual('false');
|
|
expect(visibleCounter).not.toBeNull();
|
|
|
|
});
|
|
|
|
// Our counter needs to be wrapped in an ARIA live region so changes to its content are
|
|
// communicated to assistive tech'.
|
|
// ARIA live regions need to be in the HTML before JS loads.
|
|
// Because of this, we have a counter, in a live region, in the page when it loads, and
|
|
// a duplicate, visible, one in the HTML the module adds to the page.
|
|
// We hide the one in the live region to avoid duplication of it's content.
|
|
describe("Selection counter", () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
hiddenCounter = getHiddenCounter();
|
|
|
|
})
|
|
|
|
test("the visible counter should be hidden from assistive tech", () => {
|
|
|
|
expect(visibleCounter.getAttribute('aria-hidden')).toEqual("true");
|
|
|
|
});
|
|
|
|
test("the content of both visible and hidden counters should match", () => {
|
|
|
|
expect(visibleCounter.textContent.trim()).toEqual(hiddenCounter.textContent.trim());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Click 'New template' for single channel service", () => {
|
|
test("should redirect to new template page", () => {
|
|
setFixtures(hierarchy, "data-channel='sms' data-service='123'")
|
|
templateFolderForm = document.querySelector('form[data-module=template-folder-form]');
|
|
|
|
// start module
|
|
window.GOVUK.modules.start();
|
|
|
|
formControls = templateFolderForm.querySelector('#sticky_template_forms');
|
|
|
|
// reset sticky JS mocks called when the module starts
|
|
resetStickyMocks();
|
|
// add listener for url change
|
|
const descriptor1 = Object.getOwnPropertyDescriptor(window, 'location');
|
|
delete window.location
|
|
|
|
const mockCallback = jest.fn(x => {});
|
|
|
|
Object.defineProperty(window, 'location', {
|
|
set: mockCallback
|
|
});
|
|
// click
|
|
helpers.triggerEvent(formControls.querySelector('[value=add-new-template]'), 'click');
|
|
// expect url to change
|
|
expect(mockCallback).toHaveBeenCalledWith("/services/123/templates/add-sms")
|
|
|
|
setFixtures(hierarchy)
|
|
resetStickyMocks()
|
|
});
|
|
})
|
|
|
|
describe("Clicking 'New template'", () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
// start module
|
|
window.GOVUK.modules.start();
|
|
|
|
formControls = templateFolderForm.querySelector('#sticky_template_forms');
|
|
|
|
// reset sticky JS mocks called when the module starts
|
|
resetStickyMocks();
|
|
|
|
helpers.triggerEvent(formControls.querySelector('[value=add-new-template]'), 'click');
|
|
|
|
});
|
|
|
|
afterEach(() => resetStickyMocks());
|
|
|
|
describe("Should show a region", () => {
|
|
|
|
test("with options for all the types of template", () => {
|
|
|
|
const options = [
|
|
'Email', 'Text message', 'Letter', 'Copy an existing template'
|
|
];
|
|
|
|
const labels = Array.from(formControls.querySelectorAll('label'));
|
|
const radios = Array.from(formControls.querySelectorAll('input[type=radio]'));
|
|
|
|
options.forEach(option => {
|
|
let matchingLabels = labels.filter(label => label.textContent.trim() === option);
|
|
|
|
expect(matchingLabels.length > 0).toBe(true);
|
|
|
|
let matchingRadio = formControls.querySelector(`#${matchingLabels[0].getAttribute('for')}`)
|
|
|
|
expect(matchingRadio).not.toBeNull();
|
|
});
|
|
|
|
});
|
|
|
|
test("with a 'Cancel' link", () => {
|
|
|
|
const cancelLink = formControls.querySelector('.js-cancel');
|
|
|
|
expect(cancelLink).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only')).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only').textContent.trim()).toEqual('new template');
|
|
|
|
});
|
|
|
|
test("with an accessible role, name and description", () => {
|
|
|
|
let id, description;
|
|
const region = document.querySelector('#add_new_template_form');
|
|
expect(region.hasAttribute('role')).toBe(true);
|
|
expect(region.getAttribute('role')).toEqual('region');
|
|
expect(region.hasAttribute('aria-label')).toBe(true);
|
|
expect(region.getAttribute('aria-label')).toEqual('Choose template type');
|
|
expect(region.hasAttribute('aria-describedby')).toBe(true);
|
|
id = region.getAttribute('aria-describedby');
|
|
description = document.getElementById(id);
|
|
expect(description).not.toBeNull();
|
|
expect(description.textContent.trim()).toEqual('Press continue to confirm selection or cancel to close');
|
|
|
|
});
|
|
|
|
test("and focus it", () => {
|
|
|
|
expect(document.activeElement).toBe(formControls.querySelector('#add_new_template_form'));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("When the 'Cancel' link is clicked after choosing to add a new template", () => {
|
|
|
|
let addNewTemplateButton;
|
|
|
|
beforeEach(() => {
|
|
|
|
// reset sticky JS mocks called when the new template state loaded
|
|
resetStickyMocks();
|
|
|
|
helpers.triggerEvent(formControls.querySelector('.js-cancel'), 'click');
|
|
|
|
addNewTemplateButton = formControls.querySelector('[value=add-new-template]');
|
|
|
|
});
|
|
|
|
test("the controls should reset", () => {
|
|
|
|
expect(addNewTemplateButton).not.toBeNull();
|
|
|
|
});
|
|
|
|
test("the add new template control should be focused", () => {
|
|
|
|
expect(document.activeElement).toBe(addNewTemplateButton);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Clicking 'New folder'", () => {
|
|
|
|
let textbox;
|
|
|
|
afterEach(() => resetStickyMocks());
|
|
|
|
beforeEach(() => {
|
|
|
|
// start module
|
|
window.GOVUK.modules.start();
|
|
|
|
formControls = templateFolderForm.querySelector('#sticky_template_forms');
|
|
|
|
// reset sticky JS mocks called when the module starts
|
|
resetStickyMocks();
|
|
|
|
helpers.triggerEvent(formControls.querySelector('[value=add-new-folder]'), 'click');
|
|
|
|
textbox = formControls.querySelector('input[type=text]');
|
|
|
|
});
|
|
|
|
describe("should show a parent region", () => {
|
|
|
|
test("with an accessible role, name and description", () => {
|
|
|
|
let id, description;
|
|
const region = document.querySelector('#add_new_folder_form');
|
|
expect(region.hasAttribute('role')).toBe(true);
|
|
expect(region.getAttribute('role')).toEqual('region');
|
|
expect(region.hasAttribute('aria-label')).toBe(true);
|
|
expect(region.getAttribute('aria-label')).toEqual('Enter name of the new folder');
|
|
expect(region.hasAttribute('aria-describedby')).toBe(true);
|
|
id = region.getAttribute('aria-describedby');
|
|
description = document.getElementById(id);
|
|
expect(description).not.toBeNull();
|
|
expect(description.textContent.trim()).toEqual('Press add new folder to confirm name or cancel to close');
|
|
|
|
});
|
|
|
|
test("with a textbox for the folder name", () => {
|
|
|
|
expect(textbox).not.toBeNull();
|
|
|
|
// check textbox has a label
|
|
expect(formControls.querySelector(`label[for=${textbox.getAttribute('id')}]`)).not.toBeNull();
|
|
|
|
});
|
|
|
|
test("with a 'Cancel' link", () => {
|
|
|
|
const cancelLink = formControls.querySelector('.js-cancel');
|
|
|
|
expect(cancelLink).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only')).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only').textContent.trim()).toEqual('new folder');
|
|
|
|
});
|
|
|
|
test("and focus it", () => {
|
|
|
|
expect(document.activeElement).toBe(formControls.querySelector('#add_new_folder_form'));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
test("", () => {
|
|
|
|
// the class the sticky JS hooks into should be present
|
|
expect(formControls.querySelector('#add_new_folder_form .js-stick-at-bottom-when-scrolling')).not.toBeNull();
|
|
|
|
// .recalculate should have been called so the sticky JS picks up the controls
|
|
expect(GOVUK.stickAtBottomWhenScrolling.recalculate.mock.calls.length).toEqual(0);
|
|
|
|
});
|
|
|
|
describe("When the 'Cancel' link is clicked after choosing to add a new folder", () => {
|
|
|
|
let addNewFolderButton;
|
|
|
|
beforeEach(() => {
|
|
|
|
helpers.triggerEvent(formControls.querySelector('.js-cancel'), 'click');
|
|
|
|
addNewFolderButton = formControls.querySelector('button[value=add-new-folder]');
|
|
|
|
});
|
|
|
|
test("the controls should reset", () => {
|
|
|
|
expect(addNewFolderButton).not.toBeNull();
|
|
|
|
});
|
|
|
|
test("the control for adding a new folder should be focused", () => {
|
|
|
|
expect(document.activeElement).toBe(addNewFolderButton);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("When some templates/folders are selected", () => {
|
|
|
|
let templateFolderCheckboxes;
|
|
|
|
beforeEach(() => {
|
|
|
|
// start module
|
|
window.GOVUK.modules.start();
|
|
|
|
templateFolderCheckboxes = getTemplateFolderCheckboxes();
|
|
|
|
formControls = templateFolderForm.querySelector('#sticky_template_forms');
|
|
|
|
// reset sticky JS mocks called when the module starts
|
|
resetStickyMocks();
|
|
|
|
helpers.triggerEvent(templateFolderCheckboxes[0], 'click');
|
|
helpers.triggerEvent(templateFolderCheckboxes[2], 'click');
|
|
|
|
});
|
|
|
|
afterEach(() => resetStickyMocks());
|
|
|
|
test("the buttons for moving to a new or existing folder are showing", () => {
|
|
|
|
expect(formControls.querySelector('button[value=move-to-new-folder]')).not.toBeNull();
|
|
expect(formControls.querySelector('button[value=move-to-existing-folder]')).not.toBeNull();
|
|
expect(formControls.querySelector('button[value=move-to-new-folder]').getAttribute('aria-expanded')).toEqual('false');
|
|
expect(formControls.querySelector('button[value=move-to-existing-folder]').getAttribute('aria-expanded')).toEqual('false');
|
|
|
|
});
|
|
|
|
describe("'Clear selection' link", () => {
|
|
|
|
let clearLink;
|
|
|
|
beforeEach(() => {
|
|
|
|
clearLink = formControls.querySelector('.js-cancel');
|
|
|
|
});
|
|
|
|
test("the link has been added with the right text", () => {
|
|
|
|
expect(clearLink).not.toBeNull();
|
|
expect(clearLink.textContent.trim()).toEqual('Clear selection');
|
|
|
|
});
|
|
|
|
test("clicking the link clears the selection", () => {
|
|
|
|
helpers.triggerEvent(clearLink, 'click');
|
|
|
|
const checkedCheckboxes = Array.from(templateFolderCheckboxes).filter(checkbox => checkbox.checked);
|
|
|
|
expect(checkedCheckboxes.length === 0).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Selection counter", () => {
|
|
|
|
let visibleCounterText;
|
|
let hiddenCounterText;
|
|
|
|
beforeEach(() => {
|
|
|
|
visibleCounterText = getVisibleCounter().textContent.trim();
|
|
hiddenCounterText = getHiddenCounter().textContent.trim();
|
|
|
|
});
|
|
|
|
test("the content of both visible and hidden counters should match", () => {
|
|
|
|
expect(visibleCounterText).toEqual(hiddenCounterText);
|
|
|
|
});
|
|
|
|
test("the content of the counter should reflect the selection", () => {
|
|
|
|
expect(visibleCounterText).toEqual('1 template, 1 folder selected');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Clicking the 'Move' button", () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
// reset sticky JS mocks called when a selection was made
|
|
resetStickyMocks();
|
|
|
|
helpers.triggerEvent(formControls.querySelector('[value=move-to-existing-folder]'), 'click');
|
|
|
|
});
|
|
|
|
describe("Should show a region", () => {
|
|
|
|
test("with an accessible role, name and description", () => {
|
|
|
|
let id, description;
|
|
const region = document.querySelector('#move_to_folder_radios');
|
|
expect(region.hasAttribute('role')).toBe(true);
|
|
expect(region.getAttribute('role')).toEqual('region');
|
|
expect(region.hasAttribute('aria-label')).toBe(true);
|
|
expect(region.getAttribute('aria-label')).toEqual('Choose the folder to move selected items to');
|
|
expect(region.hasAttribute('aria-describedby')).toBe(true);
|
|
id = region.getAttribute('aria-describedby');
|
|
description = document.getElementById(id);
|
|
expect(description).not.toBeNull();
|
|
expect(description.textContent.trim()).toEqual('Press move to confirm or cancel to close');
|
|
|
|
});
|
|
|
|
test("with radios for all the folders in the hierarchy", () => {
|
|
|
|
const foldersInHierarchy = [];
|
|
|
|
function getFolders (nodes) {
|
|
|
|
nodes.forEach(node => {
|
|
if (node.type === 'folder') {
|
|
|
|
foldersInHierarchy.push(node.label);
|
|
if (node.children.length) { getFolders(node.children) }
|
|
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
getFolders(hierarchy);
|
|
|
|
const folderLabels = Array.from(formControls.querySelectorAll('#move_to label'))
|
|
.filter(label => label.textContent.trim() !== 'Templates');
|
|
|
|
expect(folderLabels.map(label => label.textContent.trim())).toEqual(foldersInHierarchy);
|
|
|
|
const radiosForLabels = folderLabels
|
|
.map(label => formControls.querySelector(`#${label.getAttribute('for')}`))
|
|
.filter(radio => radio !== null);
|
|
|
|
expect(radiosForLabels.length).toEqual(foldersInHierarchy.length);
|
|
|
|
});
|
|
|
|
test("with a 'Cancel' link", () => {
|
|
|
|
const cancelLink = formControls.querySelector('.js-cancel');
|
|
|
|
expect(cancelLink).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only')).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only').textContent.trim()).toEqual('move to folder');
|
|
|
|
});
|
|
|
|
test("and focus it", () => {
|
|
|
|
expect(document.activeElement).toBe(formControls.querySelector('#move_to_folder_radios'));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("When the 'Cancel' link is clicked after choosing to move a template or folder", () => {
|
|
|
|
let moveToFolderButton;
|
|
|
|
beforeEach(() => {
|
|
|
|
helpers.triggerEvent(formControls.querySelector('.js-cancel'), 'click');
|
|
|
|
moveToFolderButton = formControls.querySelector('button[value=move-to-existing-folder]');
|
|
|
|
});
|
|
|
|
test("the controls should reset", () => {
|
|
|
|
expect(moveToFolderButton).not.toBeNull();
|
|
|
|
});
|
|
|
|
test("the control for moving to an existing folder should be focused", () => {
|
|
|
|
expect(document.activeElement).toBe(moveToFolderButton);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Clicking the 'Add to new folder' button", () => {
|
|
|
|
let textbox;
|
|
|
|
beforeEach(() => {
|
|
|
|
// reset sticky JS mocks called when a selection was made
|
|
resetStickyMocks();
|
|
|
|
helpers.triggerEvent(formControls.querySelector('[value=move-to-new-folder]'), 'click');
|
|
|
|
textbox = formControls.querySelector('input[type=text]');
|
|
|
|
});
|
|
|
|
describe("Should show a region", () => {
|
|
|
|
test("with an accessible role, name and description", () => {
|
|
|
|
let id, description;
|
|
const region = document.querySelector('#move_to_new_folder_form');
|
|
expect(region.hasAttribute('role')).toBe(true);
|
|
expect(region.getAttribute('role')).toEqual('region');
|
|
expect(region.hasAttribute('aria-label')).toBe(true);
|
|
expect(region.getAttribute('aria-label')).toEqual('Enter name of the new folder to move selected items to');
|
|
expect(region.hasAttribute('aria-describedby')).toBe(true);
|
|
id = region.getAttribute('aria-describedby');
|
|
description = document.getElementById(id);
|
|
expect(description).not.toBeNull();
|
|
expect(description.textContent.trim()).toEqual('Press add to new folder to confirm name or cancel to close');
|
|
|
|
});
|
|
|
|
test("with a textbox for the folder name", () => {
|
|
|
|
expect(textbox).not.toBeNull();
|
|
|
|
// check textbox has a label
|
|
expect(formControls.querySelector(`label[for=${textbox.getAttribute('id')}]`)).not.toBeNull();
|
|
|
|
});
|
|
|
|
test("with a 'Cancel' link", () => {
|
|
|
|
const cancelLink = formControls.querySelector('.js-cancel');
|
|
|
|
expect(cancelLink).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only')).not.toBeNull();
|
|
expect(cancelLink.querySelector('.usa-sr-only').textContent.trim()).toEqual('move to new folder');
|
|
|
|
});
|
|
|
|
test("and focus it", () => {
|
|
|
|
expect(document.activeElement).toBe(formControls.querySelector('#move_to_new_folder_form'));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("When the 'Cancel' link is clicked after choosing to add a template or folder to a new folder", () => {
|
|
|
|
let moveToNewFolderButton;
|
|
|
|
beforeEach(() => {
|
|
|
|
helpers.triggerEvent(formControls.querySelector('.js-cancel'), 'click');
|
|
|
|
moveToNewFolderButton = formControls.querySelector('button[value=move-to-new-folder]');
|
|
|
|
});
|
|
|
|
test("the controls should reset", () => {
|
|
|
|
expect(moveToNewFolderButton).not.toBeNull();
|
|
|
|
});
|
|
|
|
test("the control for adding a new folder should be focused", () => {
|
|
|
|
expect(document.activeElement).toBe(moveToNewFolderButton);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Additional selection counter scenarios", () => {
|
|
|
|
let templateFolderCheckboxes;
|
|
|
|
beforeEach(() => {
|
|
|
|
// start module
|
|
window.GOVUK.modules.start();
|
|
|
|
templateFolderCheckboxes = getTemplateFolderCheckboxes();
|
|
visibleCounterText = getVisibleCounter().textContent.trim();
|
|
hiddenCounterText = getHiddenCounter().textContent.trim();
|
|
|
|
formControls = templateFolderForm.querySelector('#sticky_template_forms');
|
|
|
|
// reset sticky JS mocks called when the module starts
|
|
resetStickyMocks();
|
|
|
|
});
|
|
|
|
afterEach(() => resetStickyMocks());
|
|
|
|
describe("When just templates are selected", () => {
|
|
|
|
test("the content of both visible and hidden counters should match", () => {
|
|
|
|
helpers.triggerEvent(templateFolderCheckboxes[1], 'click');
|
|
helpers.triggerEvent(templateFolderCheckboxes[2], 'click');
|
|
|
|
expect(visibleCounterText).toEqual(hiddenCounterText);
|
|
|
|
});
|
|
|
|
test("the content of the counter should reflect the selection", () => {
|
|
|
|
helpers.triggerEvent(templateFolderCheckboxes[1], 'click');
|
|
helpers.triggerEvent(templateFolderCheckboxes[2], 'click');
|
|
|
|
expect(visibleCounterText).toEqual('2 templates selected');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("When just folders are selected", () => {
|
|
|
|
test("the content of both visible and hidden counters should match", () => {
|
|
|
|
helpers.triggerEvent(templateFolderCheckboxes[0], 'click');
|
|
|
|
expect(visibleCounterText).toEqual(hiddenCounterText);
|
|
|
|
});
|
|
|
|
test("the content of the counter should reflect the selection", () => {
|
|
|
|
helpers.triggerEvent(templateFolderCheckboxes[0], 'click');
|
|
|
|
expect(visibleCounterText).toEqual('1 folder selected');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|