diff --git a/tests/javascripts/radioSelect.test.js b/tests/javascripts/radioSelect.test.js new file mode 100644 index 000000000..1e93de4e6 --- /dev/null +++ b/tests/javascripts/radioSelect.test.js @@ -0,0 +1,278 @@ +const helpers = require('./support/helpers'); + +beforeAll(() => { + window.Hogan = require('hogan.js'); + require('../../app/assets/javascripts/radioSelect.js'); +}); + +afterAll(() => { + require('./support/teardown.js'); +}); + +describe('RadioSelect', () => { + const CATEGORIES = [ + 'Later today', + 'Tomorrow', + 'Friday', + 'Saturday' + ]; + const HOURS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + let originalOptionsForAllCategories; + + const getDataFromOption = (option) => { + return { + value: option.querySelector('input').getAttribute('value'), + label: option.querySelector('label').textContent.trim() + }; + }; + + const clickButtonForCategory = (category) => { + + // click the button for this category + const categoryButton = document.querySelector(`.radio-select-column:nth-child(2) input[value="${category}"]`); + helpers.triggerEvent(categoryButton, 'click'); + + }; + + beforeEach(() => { + const options = () => { + let result = ''; + + const getHourLabel = (hour) => { + let label = hour; + + if (hour === 12) { + return 'midday'; + } + + if (hour === 24) { + return 'midnight'; + } + + return `${hour}${hour > 12 ? 'am' : 'pm'}`; + }; + + const hours = (day, start) => { + let result = ''; + let hours = HOURS; + let dayAsNumber = { + 'Later today': 22, + 'Tomorrow': 23, + 'Friday': 24, + 'Saturday': 25 + }[day]; + + if (start !== undefined) { + hours = hours.slice(start - 1); + } + + hours.forEach((hour, idx) => { + const hourLabel = getHourLabel(hour); + + result += + `
+ + +
`; + }); + + return result; + }; + + CATEGORIES.forEach((day, idx) => { + if (idx === 0) { + result += hours(day, 11); + } else { + result += hours(day); + } + + return result; + }); + + return result; + }; + + document.body.innerHTML = ` +
+ + When should Notify send these messages? + +
+
+
+ + +
+
+
+ ${options()} +
+
+
`; + + originalOptionsForAllCategories = Array.from(document.querySelector('.radio-select-column:nth-child(2) .multiple-choice')) + .map(option => getDataFromOption(option)); + }); + + afterEach(() => { + document.body.innerHTML = ''; + }); + + describe("when the page has loaded it should have a button for each category", () => { + + let categoryButtons; + + beforeEach(() => { + + // start module + window.GOVUK.modules.start(); + + categoryButtons = document.querySelectorAll('.radio-select-column:nth-child(2) .js-category-button'); + + }); + + test("the number of buttons should match the categories", () => { + + expect(categoryButtons.length).toBe(CATEGORIES.length); + + }); + + test("each button's text should match their category", () => { + + // check the buttons have the right text + CATEGORIES.forEach((category, idx) => { + expect(categoryButtons[idx].getAttribute('value')).toEqual(category); + }); + + }); + + }); + + describe("category buttons", () => { + + CATEGORIES.forEach((category, idx) => { + + test(`clicking the button for ${category} should show the options for it, with the right label and value`, () => { + + // get all the options in the original page for this category + originalOptionsForCategory = originalOptionsForAllCategories.filter(option => option.label === category); + + // start module + window.GOVUK.modules.start(); + + clickButtonForCategory(category); + + // check options this reveals against those originally in the page for this category + const options = document.querySelector('.radio-select-column:nth-child(2) .multiple-choice'); + + const optionsThatMatchOriginals = Array.from(options).filter((option, idx) => { + const optionData = getDataFromOption(option); + const originalOption = originalOptionsForCategory[idx]; + + return optionData.value === originalOption.value && optionData.label === originalOption.label; + }); + + expect(optionsThatMatchOriginals.length).toEqual(originalOptionsForCategory.length); + + }); + + }); + + test(`clicking the button for a category should add a 'Done' button below its options`, () => { + + // start module + window.GOVUK.modules.start(); + + clickButtonForCategory(CATEGORIES[0]); + + const button = document.querySelector('.radio-select-column:nth-child(2) input[type=button]'); + + expect(button).not.toBeNull(); + expect(button.getAttribute('value')).toEqual('Done'); + + }); + + }); + + describe("after clicking the button to select that category", () => { + + beforeEach(() => { + + // start module + window.GOVUK.modules.start(); + + clickButtonForCategory(CATEGORIES[0]); + + }); + + test("clicking the 'Done' button should reset the module to its initial state, showing the category buttons again", () => { + + const doneButton = document.querySelector('.radio-select-column:nth-child(2) input[type=button]'); + + helpers.triggerEvent(doneButton, 'click'); + + }); + + describe("clicking on an option should", () => { + + let optionsColumn; + let firstOptionLabel; + + beforeEach(() => { + + optionsColumn = document.querySelector('.radio-select-column:nth-child(2)'); + + const firstOption = optionsColumn.querySelector('input[type=radio]'); + firstOptionLabel = firstOption.parentNode.querySelector('label').textContent.trim(); + + helpers.triggerEvent(firstOption, 'click'); + + }); + + test("remove all the other options", () => { + + // module replaces the column node so this needs querying again + optionsColumn = document.querySelector('.radio-select-column:nth-child(2)'); + + expect(optionsColumn.querySelectorAll('input[type=radio]').length).toEqual(1); + expect(optionsColumn.querySelector('label').textContent.trim()).toEqual(firstOptionLabel); + + }); + + test("add a button for choosing a different time", () => { + + const button = document.querySelector('.radio-select-column:nth-child(3) input[type=button]'); + + expect(button).not.toBeNull(); + expect(button.getAttribute('value')).toEqual('Choose a different time'); + + }) + + }); + + describe("after selecting an option", () => { + + test("clicking the 'Choose a different time' button should reset the module", () => { + + // select the first option + const firstOption = document.querySelector('.radio-select-column:nth-child(2) input[type=radio]'); + helpers.triggerEvent(firstOption, 'click'); + + // click the 'Choose a different time' button + const resetButton = document.querySelector('.radio-select-column:nth-child(3) input[type=button]'); + helpers.triggerEvent(resetButton, 'click'); + + categoryButtons = document.querySelectorAll('.radio-select-column:nth-child(2) .js-category-button'); + + expect(categoryButtons.length).toEqual(CATEGORIES.length); + + }); + }); + + }); + +});