diff --git a/tests/javascripts/collapsibleCheckboxes.test.js b/tests/javascripts/collapsibleCheckboxes.test.js new file mode 100644 index 000000000..6a8e266fe --- /dev/null +++ b/tests/javascripts/collapsibleCheckboxes.test.js @@ -0,0 +1,443 @@ +const helpers = require('./support/helpers'); + +beforeAll(() => { + // set up jQuery + window.jQuery = require('jquery'); + $ = window.jQuery; + + // load module code + require('govuk_frontend_toolkit/javascripts/govuk/modules.js'); + require('../../app/assets/javascripts/collapsibleCheckboxes.js'); +}); + +afterAll(() => { + window.jQuery = null; + $ = null; + + delete window.GOVUK; +}); + + +describe('Collapsible fieldset', () => { + + let fieldset; + let checkboxes; + + beforeEach(() => { + const _checkboxes = (start, end, descendents) => { + result = ''; + + for (let num = start; num <= end; num++) { + let id = `folder-permissions-${num}`; + + if (!descendents) { descendents = ''; } + + result += `
  • + + + ${descendents} +
  • `; + } + + return result; + }; + + // set up DOM + document.body.innerHTML = + `
    +
    + + Folders this team member can see + +
    +
      + ${_checkboxes(1, 10)} +
    +
    +
    +
    `; + + formGroup = document.querySelector('.form-group'); + fieldset = formGroup.querySelector('fieldset'); + checkboxesContainer = fieldset.querySelector('.checkboxes-nested'); + checkboxes = checkboxesContainer.querySelectorAll('input[type=checkbox]'); + + }); + + afterEach(() => { + + document.body.innerHTML = ''; + + }); + + describe('when started', () => { + + beforeEach(() => { + + // start module + window.GOVUK.modules.start(); + + }); + + afterEach(() => { + + // reset checkboxes to default state + checkboxes.forEach(el => el.removeAttribute('checked')); + + }); + + test("adds a heading before the selected fieldset", () => { + + const heading = helpers.element(fieldset).getPreviousSibling( + el => (el.nodeName === 'h2') && (el.hasClass('heading-small')) + ); + + expect(heading).not.toBeNull(); + + }); + + test("has a summary added before the selected fieldset", () => { + + const summary = helpers.element(fieldset).getPreviousSibling( + el => (el.nodeName === 'p') && (el.hasClass('selection-summary')) + ); + + expect(summary).not.toBeNull(); + + }); + + test("the legend of the fieldset is visually hidden", () => { + + const legend = helpers.element(fieldset.querySelector('legend')); + + expect(legend.hasClass('visuallyhidden')).toBe(true); + + }); + + test("has a change button", () => { + + const changeButton = document.querySelector('.selection-summary .button'); + + expect(changeButton).not.toBeNull(); + expect(changeButton.textContent).toEqual('Change Folders this team member can see'); + + }); + + test("has a 'Done' button", () => { + + const nextEl = fieldset.querySelector('.button'); + + expect(helpers.element(nextEl).nodeName).toEqual('button'); + + }); + + test("has the correct aria attributes on both buttons", () => { + + const changeButton = document.querySelector('.selection-summary .button'); + const doneButton = fieldset.querySelector('.button'); + + // check change button + expect(helpers.element(changeButton).hasAttributesSetTo({ + 'aria-controls': fieldset.getAttribute('id'), + 'aria-expanded': 'false' + })).toBe(true); + + // check done button + expect(helpers.element(doneButton).hasAttributesSetTo({ + 'aria-controls': fieldset.getAttribute('id'), + 'aria-expanded': 'false' + })).toBe(true); + + }); + + test("hides the checkboxes", () => { + + expect(helpers.element(fieldset).is('hidden')).toEqual(true); + + }); + + }); + + test('has the right summary text when started with no checkboxes selected', () => { + + // start module + window.GOVUK.modules.start(); + + const summaryText = document.querySelector('.selection-summary__text'); + + // default state is for none to be selected + expect(summaryText.textContent).toEqual("No folders (only templates outside a folder)"); + + }); + + test('has the right summary text when started with some checkboxes selected', () => { + + // select the first 3 checkboxes + checkboxes.forEach((el, idx) => { + if ([0,1,2].includes(idx)) { el.setAttribute('checked', ''); } + }); + + // start module + window.GOVUK.modules.start(); + + const summaryText = document.querySelector('.selection-summary__text'); + + expect(summaryText.textContent).toEqual("3 of 10 folders"); + + }); + + test('has the right summary text when started with all checkboxes selected', () => { + + // select all the checkboxes + checkboxes.forEach(el => el.setAttribute('checked', '')); + + // start module + window.GOVUK.modules.start(); + + const summaryText = document.querySelector('.selection-summary__text'); + + expect(summaryText.textContent).toEqual("All folders"); + + }); + + describe("when 'change' is clicked", () => { + + let changeButton; + let doneButton; + + beforeEach(() => { + + // start module + window.GOVUK.modules.start(); + + doneButton = fieldset.querySelector('.button'); + changeButton = document.querySelector('.selection-summary .button'); + + helpers.triggerEvent(changeButton, 'click'); + + }); + + test("it shows the checkboxes", () => { + + expect(helpers.element(fieldset).is('hidden')).toBe(false); + + }); + test("it focuses the fieldset", () => { + + expect(document.activeElement).toBe(fieldset); + + }); + test("it uses ARIA to mark the checkboxes as expanded", () => { + + expect(changeButton.getAttribute('aria-expanded')).toEqual('true'); + expect(doneButton.getAttribute('aria-expanded')).toEqual('true'); + + }); + }); + + describe("when 'done' is clicked", () => { + + let changeButton; + let doneButton; + + beforeEach(() => { + + // start module + window.GOVUK.modules.start(); + + doneButton = fieldset.querySelector('.button'); + changeButton = document.querySelector('.selection-summary .button'); + + // show the checkboxes + helpers.triggerEvent(changeButton, 'click'); + + // click the done button + helpers.triggerEvent(doneButton, 'click'); + + }); + + test("it hides the checkboxes", () => { + + expect(helpers.element(fieldset).is('hidden')).toBe(true); + + }); + + test("it focuses the summary text", () => { + + expect(document.activeElement).toBe(document.querySelector('.selection-summary__text')); + + }); + + test("it uses ARIA to mark the checkboxes as collapsed", () => { + + expect(changeButton.getAttribute('aria-expanded')).toEqual('false'); + expect(doneButton.getAttribute('aria-expanded')).toEqual('false'); + + }); + }); + + describe("when the selection changes", () => { + + const showCheckboxes = () => { + changeButton = document.querySelector('.selection-summary .button'); + helpers.triggerEvent(changeButton, 'click'); + }; + + const checkFirstCheckbox = () => { + checkboxes[0].setAttribute('checked', ''); + checkboxes[0].checked = true; + }; + + const checkAllCheckboxes = () => { + Array.from(checkboxes).forEach(checkbox => { + checkbox.setAttribute('checked', ''); + checkbox.checked = true; + }); + }; + + const checkAllCheckboxesButTheLast = () => { + Array.from(checkboxes).forEach((checkbox, idx) => { + if (idx > 0) { + checkbox.setAttribute('checked', ''); + checkbox.checked = true; + } + }); + }; + + let changeButton; + + describe("from some to none the summary updates to reflect that", () => { + + test("if fields are called 'folders'", () => { + + formGroup.dataset.fieldLabel = 'folder'; + + checkFirstCheckbox(); + + // start module + window.GOVUK.modules.start(); + + showCheckboxes(); + + const summaryText = document.querySelector('.selection-summary__text'); + + // click the first checkbox + helpers.triggerEvent(checkboxes[0], 'click'); + + expect(summaryText.textContent).toEqual("No folders (only templates outside a folder)"); + + }); + + test("if fields are called 'team member'", () => { + + formGroup.dataset.fieldLabel = 'team member'; + + checkFirstCheckbox(); + + // start module + window.GOVUK.modules.start(); + + showCheckboxes(); + + const summaryText = document.querySelector('.selection-summary__text'); + + // click the first checkbox + helpers.triggerEvent(checkboxes[0], 'click'); + + expect(summaryText.textContent).toEqual("No team members"); + + }); + + }); + + describe("from all to some the summary updates to reflect that", () => { + + test("if fields are called 'folder'", () => { + + formGroup.dataset.fieldLabel = 'folder'; + + checkAllCheckboxes(); + + // start module + window.GOVUK.modules.start(); + + showCheckboxes(); + + const summaryText = document.querySelector('.selection-summary__text'); + + // click the first checkbox + helpers.triggerEvent(checkboxes[1], 'click'); + + expect(summaryText.textContent).toEqual("9 of 10 folders"); + + }); + + test("if fields are called 'team member'", () => { + + formGroup.dataset.fieldLabel = 'team member'; + + checkAllCheckboxes(); + + // start module + window.GOVUK.modules.start(); + + showCheckboxes(); + + const summaryText = document.querySelector('.selection-summary__text'); + + // click the first checkbox + helpers.triggerEvent(checkboxes[1], 'click'); + + expect(summaryText.textContent).toEqual("9 of 10 team members"); + + }); + + }); + + describe("from some to all the summary updates to reflect that", () => { + + test("if fields are called 'folder'", () => { + + formGroup.dataset.fieldLabel = 'folder'; + + checkAllCheckboxesButTheLast(); + + // start module + window.GOVUK.modules.start(); + + showCheckboxes(); + + const summaryText = document.querySelector('.selection-summary__text'); + + helpers.triggerEvent(checkboxes[0], 'click'); + + expect(summaryText.textContent).toEqual("All folders"); + + }); + + test("if fields are called 'team member'", () => { + + formGroup.dataset.fieldLabel = 'team member'; + + checkAllCheckboxesButTheLast(); + + // start module + window.GOVUK.modules.start(); + + showCheckboxes(); + + const summaryText = document.querySelector('.selection-summary__text'); + + helpers.triggerEvent(checkboxes[0], 'click'); + + expect(summaryText.textContent).toEqual("All team members"); + + }); + + }); + + }); + +});