From f942ba9e6ea535af57b7fd0a52a647479cb05a86 Mon Sep 17 00:00:00 2001 From: rmccar <42928680+rmccar@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:13:51 +0000 Subject: [PATCH] Fix single inputs not clearing for mutually exclusive fields (#3091) --- .../multiple-input-fields/_macro.njk | 12 +- .../mutually-exclusive.date.spec.js | 128 +++++++++++++++++- .../mutually-exclusive.duration.spec.js | 121 +++++++++++++++++ 3 files changed, 248 insertions(+), 13 deletions(-) diff --git a/src/components/multiple-input-fields/_macro.njk b/src/components/multiple-input-fields/_macro.njk index aeae347571..55a2837402 100644 --- a/src/components/multiple-input-fields/_macro.njk +++ b/src/components/multiple-input-fields/_macro.njk @@ -2,15 +2,15 @@ {% from "components/fieldset/_macro.njk" import onsFieldset %} {% macro onsMultipleInputFields(params) %} - {% if params.numberOfFields > 1 %} - {% set fields %} + {% set fields %} + {% if params.numberOfFields > 1 %}
{{ params.fields | safe }}
- {% endset %} - {% else %} - {{ params.fields | safe }} - {% endif %} + {% else %} + {{ params.fields | safe }} + {% endif %} + {% endset %} {% if params.mutuallyExclusive %} {% call onsMutuallyExclusive({ diff --git a/src/components/mutually-exclusive/mutually-exclusive.date.spec.js b/src/components/mutually-exclusive/mutually-exclusive.date.spec.js index b6708612ca..7646133196 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.date.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.date.spec.js @@ -31,7 +31,35 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DATE_PARAMS = { deselectExclusiveOptionAdjective: 'deselected', exclusiveOptions: [ { - id: 'date-exclusive-exclusive-option', + id: 'date-exclusive-option', + name: 'no-paid-job', + value: 'no-paid-job', + label: { + text: 'I have never had a paid job', + }, + }, + ], + }, +}; + +const EXAMPLE_MUTUALLY_EXCLUSIVE_DATE_SINGLE_PARAMS = { + id: 'date-mutually-exclusive', + legendOrLabel: 'What year was your last MOT?', + description: 'For example, 2018', + year: { + label: { + text: 'Year', + }, + name: 'year-exclusive', + }, + mutuallyExclusive: { + or: 'Or', + deselectMessage: 'Selecting this will clear the date if one has been inputted', + deselectGroupAdjective: 'cleared', + deselectExclusiveOptionAdjective: 'deselected', + exclusiveOptions: [ + { + id: 'date-exclusive-option', name: 'no-paid-job', value: 'no-paid-job', label: { @@ -57,11 +85,11 @@ describe('script: mutually-exclusive', () => { describe('when the user clicks the mutually exclusive option', () => { beforeEach(async () => { - await page.click('#date-exclusive-exclusive-option'); + await page.click('#date-exclusive-option'); }); it('then the mutually exclusive option should be checked', async () => { - const isChecked = await page.$eval('#date-exclusive-exclusive-option', (node) => node.checked); + const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked); expect(isChecked).toBe(true); }); @@ -85,7 +113,7 @@ describe('script: mutually-exclusive', () => { describe('Given the user has checked the mutually exclusive exclusive option', () => { beforeEach(async () => { - await page.click('#date-exclusive-exclusive-option'); + await page.click('#date-exclusive-option'); }); describe('when the user populates the dateInput', () => { @@ -95,8 +123,8 @@ describe('script: mutually-exclusive', () => { await page.type('#date-mutually-exclusive-year', '2018'); }); - it('then the mutually exclusive option should be checked', async () => { - const isChecked = await page.$eval('#date-exclusive-exclusive-option', (node) => node.checked); + it('then the mutually exclusive option should be unchecked', async () => { + const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked); expect(isChecked).toBe(false); }); @@ -127,7 +155,93 @@ describe('script: mutually-exclusive', () => { describe('when the user clicks the mutually exclusive option', () => { beforeEach(async () => { - await page.click('#date-exclusive-exclusive-option'); + await page.click('#date-exclusive-option'); + }); + + it('then the aria alert shouldnt say anything', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe(''); + }); + }); + }); + }); + describe('date-year', () => { + beforeEach(async () => { + await setTestPage('/test', renderComponent('date-input', EXAMPLE_MUTUALLY_EXCLUSIVE_DATE_SINGLE_PARAMS)); + }); + + describe('Given the user populated the date input', () => { + beforeEach(async () => { + await page.type('#date-mutually-exclusive-year', '2018'); + }); + + describe('when the user clicks the mutually exclusive option', () => { + beforeEach(async () => { + await page.click('#date-exclusive-option'); + }); + + it('then the mutually exclusive option should be checked', async () => { + const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked); + expect(isChecked).toBe(true); + }); + + it('then the date input should be cleared', async () => { + const yearValue = await page.$eval('#date-mutually-exclusive-year', (node) => node.value); + expect(yearValue).toBe(''); + }); + + it('then the aria alert should tell the user that the date input has been cleared', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe('What year was your last MOT? cleared.'); + }); + }); + }); + + describe('Given the user has checked the mutually exclusive exclusive option', () => { + beforeEach(async () => { + await page.click('#date-exclusive-option'); + }); + + describe('when the user populates the dateInput', () => { + beforeEach(async () => { + await page.type('#date-mutually-exclusive-year', '2018'); + }); + + it('then the mutually exclusive option should be unchecked', async () => { + const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked); + expect(isChecked).toBe(false); + }); + + it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe('I have never had a paid job deselected.'); + }); + }); + }); + + describe('Given the user has not populated the date input or checked the exclusive option', () => { + describe('when the user populates the date input', () => { + beforeEach(async () => { + await page.type('#date-mutually-exclusive-year', '2018'); + }); + + it('then the aria alert shouldnt say anything', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe(''); + }); + }); + + describe('when the user clicks the mutually exclusive option', () => { + beforeEach(async () => { + await page.click('#date-exclusive-option'); }); it('then the aria alert shouldnt say anything', async () => { diff --git a/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js b/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js index eb1ab785ff..d2981a8129 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js @@ -48,6 +48,40 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_PARAMS = { }, }; +const EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_SINGLE_PARAMS = { + id: 'address-duration', + legendOrLabel: 'How long have you lived at this address?', + description: 'If you have lived at this address for less than a year then enter 0 into the year input.', + field1: { + id: 'address-duration-years', + name: 'address-duration-years', + suffix: { + text: 'Years', + id: 'address-duration-years-suffix', + }, + attributes: { + min: 0, + max: 100, + }, + }, + mutuallyExclusive: { + or: 'Or', + deselectMessage: 'Selecting this will clear the date if one has been inputted', + deselectGroupAdjective: 'cleared', + deselectExclusiveOptionAdjective: 'deselected', + exclusiveOptions: [ + { + id: 'duration-exclusive-option', + name: 'no-duration', + value: 'no-duration', + label: { + text: 'I have not moved in to this address yet', + }, + }, + ], + }, +}; + describe('script: mutually-exclusive', () => { describe('duration', () => { beforeEach(async () => { @@ -140,4 +174,91 @@ describe('script: mutually-exclusive', () => { }); }); }); + + describe('duration-single', () => { + beforeEach(async () => { + await setTestPage('/test', renderComponent('duration', EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_SINGLE_PARAMS)); + }); + + describe('Given the user populated the duration', () => { + beforeEach(async () => { + await page.type('#address-duration-years', '2'); + }); + + describe('when the user clicks the mutually exclusive option', () => { + beforeEach(async () => { + await page.click('#duration-exclusive-option'); + }); + + it('then the mutually exclusive option should be checked', async () => { + const isChecked = await page.$eval('#duration-exclusive-option', (node) => node.checked); + expect(isChecked).toBe(true); + }); + + it('then the inputs should be cleared', async () => { + const yearsValue = await page.$eval('#address-duration-years', (node) => node.value); + expect(yearsValue).toBe(''); + }); + + it('then the aria alert should tell the user that the inputs have been cleared', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe('How long have you lived at this address? cleared.'); + }); + }); + }); + + describe('Given the user has checked the mutually exclusive exclusive option', () => { + beforeEach(async () => { + await page.click('#duration-exclusive-option'); + }); + + describe('when the user populates the duration fields', () => { + beforeEach(async () => { + await page.type('#address-duration-years', '2'); + }); + + it('then the exclusive option should be unchecked', async () => { + const isChecked = await page.$eval('#duration-exclusive-option', (node) => node.checked); + expect(isChecked).toBe(false); + }); + + it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe('I have not moved in to this address yet deselected.'); + }); + }); + }); + + describe('Given the user has not populated the duration inputs or checked the exclusive option', () => { + describe('when the user populates the duration inputs', () => { + beforeEach(async () => { + await page.type('#address-duration-years', '2'); + }); + + it('then the aria alert shouldnt say anything', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe(''); + }); + }); + + describe('when the user clicks the mutually exclusive option', () => { + beforeEach(async () => { + await page.click('#duration-exclusive-option'); + }); + + it('then the aria alert shouldnt say anything', async () => { + await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + + const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); + expect(alertText).toBe(''); + }); + }); + }); + }); });