Skip to content

Commit

Permalink
Merge pull request #4177 from alphagov/bk-skip-link-error
Browse files Browse the repository at this point in the history
Add MissingElementError and use it within the Skip Link
  • Loading branch information
domoscargin committed Sep 7, 2023
2 parents 432c8fc + e1eff14 commit 1d1fb0a
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MissingElementError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
Expand All @@ -20,6 +21,7 @@ export class SkipLink extends GOVUKFrontendComponent {

/**
* @param {Element} $module - HTML element to use for skip link
* @throws {MissingElementError} If the element with the specified ID is not found
*/
constructor($module) {
super()
Expand All @@ -31,28 +33,43 @@ export class SkipLink extends GOVUKFrontendComponent {
this.$module = $module

// Check for linked element
const $linkedElement = this.getLinkedElement()
if (!$linkedElement) {
return
try {
const $linkedElement = this.getLinkedElement()
this.$linkedElement = $linkedElement
} catch (error) {
throw new MissingElementError(
`Skip link: ${
error instanceof Error ? error.message : 'Linked element not found'
}`
)
}

this.$linkedElement = $linkedElement
this.$module.addEventListener('click', () => this.focusLinkedElement())
}

/**
* Get linked element
*
* @private
* @returns {HTMLElement | null} $linkedElement - DOM element linked to from the skip link
* @throws {Error} If the "href" attribute does not contain a hash
* @throws {TypeError} If the element with the specified ID is not found
* @returns {HTMLElement} $linkedElement - DOM element linked to from the skip link
*/
getLinkedElement() {
const linkedElementId = this.getFragmentFromUrl()
if (!linkedElementId) {
return null
throw new Error(`$module "href" attribute does not contain a hash`)
}

const linkedElement = document.getElementById(linkedElementId)

if (!linkedElement) {
throw new TypeError(
`Linked element selector "#${linkedElementId}" not found`
)
}

return document.getElementById(linkedElementId)
return linkedElement
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,34 @@ describe('Skip Link', () => {
message: 'GOV.UK Frontend is not supported in this browser'
})
})

it('throws when the linked element is missing', async () => {
await expect(
renderAndInitialise(page, 'skip-link', {
params: {
text: 'Skip to main content',
href: '#this-element-does-not-exist'
}
})
).rejects.toEqual({
name: 'MissingElementError',
message:
'Skip link: Linked element selector "#this-element-does-not-exist" not found'
})
})

it('throws when the href does not contain a hash', async () => {
await expect(
renderAndInitialise(page, 'skip-link', {
params: {
text: 'Skip to main content',
href: 'this-element-does-not-exist'
}
})
).rejects.toEqual({
name: 'MissingElementError',
message: 'Skip link: $module "href" attribute does not contain a hash'
})
})
})
})
7 changes: 7 additions & 0 deletions packages/govuk-frontend/src/govuk/errors/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ export class GOVUKFrontendError extends Error {
name = 'GOVUKFrontendError'
}

/**
* Indicates that a Component's required HTML element is missing
*/
export class MissingElementError extends GOVUKFrontendError {
name = 'MissingElementError'
}

/**
* Indicates that GOV.UK Frontend is not supported
*/
Expand Down

0 comments on commit 1d1fb0a

Please sign in to comment.