Skip to content

Commit

Permalink
Throw ElementError when conditional content target not found
Browse files Browse the repository at this point in the history
We handle these IDs internally, but in the case where somebody is coding using HTML instead of the Nunjucks macros, they still might get caught out.
  • Loading branch information
domoscargin committed Sep 20, 2023
1 parent acaea1d commit 343ffe7
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,21 @@ export class Checkboxes extends GOVUKFrontendComponent {

this.$inputs.forEach(($input) => {
const targetId = $input.getAttribute('data-aria-controls')
const targetElement = document.getElementById(targetId)

// Skip checkboxes without data-aria-controls attributes, or where the
// target element does not exist.
if (!targetId || !document.getElementById(targetId)) {
// Skip radios without data-aria-controls attributes
if (!targetId) {
return
}

// Throw if target conditional element does not exist.
if (!targetElement) {
throw new ElementError(targetElement, {
componentName: 'Checkboxes',
identifier: `.govuk-checkboxes__conditional #${targetId}`
})
}

// Promote the data-aria-controls attribute to a aria-controls attribute
// so that the relationship is exposed in the AOM
$input.setAttribute('aria-controls', targetId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,21 @@ describe('Checkboxes with multiple groups and a "None" checkbox and conditional
message: 'Checkboxes: <input type="checkbox"> not found'
})
})

it('throws when a conditional target element is not found', async () => {
await expect(
renderAndInitialise(page, 'checkboxes', {
params: examples['with conditional items'],
beforeInitialisation($module) {
$module.querySelector('.govuk-checkboxes__conditional').remove()
}
})
).rejects.toEqual({
name: 'ElementError',
message:
'Checkboxes: .govuk-checkboxes__conditional #conditional-how-contacted not found'
})
})
})
})
})
14 changes: 11 additions & 3 deletions packages/govuk-frontend/src/govuk/components/radios/radios.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,21 @@ export class Radios extends GOVUKFrontendComponent {

this.$inputs.forEach(($input) => {
const targetId = $input.getAttribute('data-aria-controls')
const targetElement = document.getElementById(targetId)

// Skip radios without data-aria-controls attributes, or where the
// target element does not exist.
if (!targetId || !document.getElementById(targetId)) {
// Skip radios without data-aria-controls attributes
if (!targetId) {
return
}

// Throw if target conditional element does not exist.
if (!targetElement) {
throw new ElementError(targetElement, {
componentName: 'Radios',
identifier: `.govuk-radios__conditional #${targetId}`
})
}

// Promote the data-aria-controls attribute to a aria-controls attribute
// so that the relationship is exposed in the AOM
$input.setAttribute('aria-controls', targetId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,5 +335,20 @@ describe('Radios', () => {
message: 'Radios: <input type="radio"> not found'
})
})

it('throws when a conditional target element is not found', async () => {
await expect(
renderAndInitialise(page, 'radios', {
params: examples['with conditional items'],
beforeInitialisation($module) {
$module.querySelector('.govuk-radios__conditional').remove()
}
})
).rejects.toEqual({
name: 'ElementError',
message:
'Radios: .govuk-radios__conditional #conditional-how-contacted not found'
})
})
})
})

0 comments on commit 343ffe7

Please sign in to comment.