diff --git a/packages/govuk-frontend/src/govuk/components/breadcrumbs/breadcrumbs.yaml b/packages/govuk-frontend/src/govuk/components/breadcrumbs/breadcrumbs.yaml
index 934691dced..012a5703bd 100644
--- a/packages/govuk-frontend/src/govuk/components/breadcrumbs/breadcrumbs.yaml
+++ b/packages/govuk-frontend/src/govuk/components/breadcrumbs/breadcrumbs.yaml
@@ -124,10 +124,12 @@ examples:
options:
items:
- text: Section 1
+ href: /section-1
+ - text: Section 2
- name: html
hidden: true
options:
items:
- html: Section 1
+ href: /section-1
- html: Section 2
- href: /section-2
diff --git a/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.jsdom.test.js b/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.jsdom.test.js
new file mode 100644
index 0000000000..12e9a02f04
--- /dev/null
+++ b/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.jsdom.test.js
@@ -0,0 +1,158 @@
+const { getExamples, render } = require('@govuk-frontend/lib/components')
+
+describe('Breadcrumbs', () => {
+ let examples
+
+ beforeAll(async () => {
+ examples = await getExamples('breadcrumbs')
+ })
+
+ describe('default example', () => {
+ let $component, $list, $listItems
+
+ beforeAll(() => {
+ document.body.innerHTML = render('breadcrumbs', examples.default)
+
+ $component = document.querySelector('.govuk-breadcrumbs')
+ $list = document.querySelector('ol.govuk-breadcrumbs__list')
+ $listItems = document.querySelectorAll('li.govuk-breadcrumbs__list-item')
+ })
+
+ it('includes an ordered list', () => {
+ expect($component).toContainElement($list)
+ })
+
+ it('includes 2 list items within the list', () => {
+ expect($listItems).toHaveLength(2)
+ })
+
+ describe.each([
+ { index: 0, expectedText: 'Section', expectedHref: '/section' },
+ {
+ index: 1,
+ expectedText: 'Sub-section',
+ expectedHref: '/section/sub-section'
+ }
+ ])(
+ 'the "$expectedText" breadcrumb',
+ ({ index, expectedText, expectedHref }) => {
+ it(`includes the text "${expectedText}"`, () => {
+ expect($listItems[index]).toHaveTextContent(expectedText)
+ })
+
+ it(`includes a link with the class govuk-breadcrumbs__link`, () => {
+ expect($listItems[index].querySelector('a')).toHaveClass(
+ 'govuk-breadcrumbs__link'
+ )
+ })
+
+ it(`includes a link with the href "${expectedHref}"`, () => {
+ expect($listItems[index].querySelector('a')).toHaveAttribute(
+ 'href',
+ expectedHref
+ )
+ })
+ }
+ )
+ })
+
+ describe('when the last breadcrumb is the current page', () => {
+ let $lastItem
+
+ beforeAll(() => {
+ document.body.innerHTML = render(
+ 'breadcrumbs',
+ examples['with last breadcrumb as current page']
+ )
+
+ $lastItem = document.querySelector(
+ '.govuk-breadcrumbs__list-item:last-child'
+ )
+ })
+
+ it('includes the current page as the last list item', () => {
+ expect($lastItem).toHaveTextContent('Travel abroad')
+ })
+
+ it('does not link the last list item', () => {
+ expect($lastItem.querySelector('a')).toBeNull()
+ })
+
+ it('sets the aria-current attribute to "page"', () => {
+ expect($lastItem).toHaveAttribute('aria-current', 'page')
+ })
+ })
+
+ describe('custom options', () => {
+ it('escapes HTML when using the `text` option', () => {
+ document.body.innerHTML = render('breadcrumbs', examples['html as text'])
+ const $item = document.querySelector('.govuk-breadcrumbs__list-item')
+
+ expect($item).toHaveTextContent('Section 1')
+ })
+
+ it('escapes HTML when using the `text` option without a link', () => {
+ document.body.innerHTML = render('breadcrumbs', examples['html as text'])
+ const $item = document.querySelector(
+ '.govuk-breadcrumbs__list-item:nth-child(2)'
+ )
+
+ expect($item).toHaveTextContent('Section 2')
+ })
+
+ it('does not escape HTML when using the `html` option', () => {
+ document.body.innerHTML = render('breadcrumbs', examples.html)
+ const $item = document.querySelector('.govuk-breadcrumbs__list-item')
+
+ expect($item).toContainHTML('Section 1')
+ })
+
+ it('does not escape HTML when using the `html` option without a link', () => {
+ document.body.innerHTML = render('breadcrumbs', examples.html)
+ const $item = document.querySelector(
+ '.govuk-breadcrumbs__list-item:nth-child(2)'
+ )
+
+ expect($item).toContainHTML('Section 2')
+ })
+
+ it('sets any additional attributes on the link based on the `item.attributes` option', () => {
+ document.body.innerHTML = render(
+ 'breadcrumbs',
+ examples['item attributes']
+ )
+ const $breadcrumbLink = document.querySelector('.govuk-breadcrumbs__link')
+
+ expect($breadcrumbLink).toHaveAttribute('data-attribute', 'my-attribute')
+ expect($breadcrumbLink).toHaveAttribute(
+ 'data-attribute-2',
+ 'my-attribute-2'
+ )
+ })
+
+ it('includes additional classes from the `classes` option', () => {
+ document.body.innerHTML = render('breadcrumbs', examples.classes)
+
+ const $component = document.querySelector('.govuk-breadcrumbs')
+ expect($component).toHaveClass('app-breadcrumbs--custom-modifier')
+ })
+
+ it('adds the `--collapse-on-mobile` modifier class if `collapseOnMobile` is true', () => {
+ document.body.innerHTML = render(
+ 'breadcrumbs',
+ examples['with collapse on mobile']
+ )
+
+ const $component = document.querySelector('.govuk-breadcrumbs')
+ expect($component).toHaveClass('govuk-breadcrumbs--collapse-on-mobile')
+ })
+
+ it('sets any additional attributes based on the `attributes` option', () => {
+ document.body.innerHTML = render('breadcrumbs', examples.attributes)
+
+ const $component = document.querySelector('.govuk-breadcrumbs')
+ expect($component).toHaveAttribute('id', 'my-navigation')
+ expect($component).toHaveAttribute('role', 'navigation')
+ })
+ })
+})
diff --git a/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.test.js b/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.test.js
deleted file mode 100644
index 9ac6ad2a2b..0000000000
--- a/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.test.js
+++ /dev/null
@@ -1,109 +0,0 @@
-const { render } = require('@govuk-frontend/helpers/nunjucks')
-const { getExamples } = require('@govuk-frontend/lib/components')
-
-describe('Breadcrumbs', () => {
- let examples
-
- beforeAll(async () => {
- examples = await getExamples('breadcrumbs')
- })
-
- describe('default example', () => {
- it('renders with items', () => {
- const $ = render('breadcrumbs', examples.default)
-
- const $items = $('.govuk-breadcrumbs__list-item')
- expect($items).toHaveLength(2)
- })
-
- it('renders 2 items', () => {
- const $ = render('breadcrumbs', examples.default)
- const $items = $('.govuk-breadcrumbs__list-item')
- expect($items).toHaveLength(2)
- })
-
- it('renders item with anchor', () => {
- const $ = render('breadcrumbs', examples.default)
-
- const $anchor = $('.govuk-breadcrumbs__list-item a').first()
- expect($anchor.get(0).tagName).toBe('a')
- expect($anchor.attr('class')).toBe('govuk-breadcrumbs__link')
- expect($anchor.attr('href')).toBe('/section')
- expect($anchor.text()).toBe('Section')
- })
- })
-
- describe('custom options', () => {
- it('renders item with text', () => {
- const $ = render(
- 'breadcrumbs',
- examples['with last breadcrumb as current page']
- )
-
- const $item = $('.govuk-breadcrumbs__list-item').last()
- expect($item.text()).toBe('Travel abroad')
- })
-
- it('renders item with escaped entities in text', () => {
- const $ = render('breadcrumbs', examples['html as text'])
-
- const $item = $('.govuk-breadcrumbs__list-item')
- expect($item.html()).toBe('<span>Section 1</span>')
- })
-
- it('renders item with html', () => {
- const $ = render('breadcrumbs', examples.html)
-
- const $item = $('.govuk-breadcrumbs__list-item').first()
- expect($item.html()).toBe('Section 1')
- })
-
- it('renders item with html inside anchor', () => {
- const $ = render('breadcrumbs', examples.html)
-
- const $anchor = $('.govuk-breadcrumbs__list-item a').last()
- expect($anchor.html()).toBe('Section 2')
- })
-
- it('renders item anchor with attributes', () => {
- const $ = render('breadcrumbs', examples['item attributes'])
-
- const $breadcrumbLink = $('.govuk-breadcrumbs__link')
- expect($breadcrumbLink.attr('data-attribute')).toBe('my-attribute')
- expect($breadcrumbLink.attr('data-attribute-2')).toBe('my-attribute-2')
- })
-
- it('renders with classes', () => {
- const $ = render('breadcrumbs', examples.classes)
-
- const $component = $('.govuk-breadcrumbs')
- expect(
- $component.hasClass('app-breadcrumbs--custom-modifier')
- ).toBeTruthy()
- })
-
- it('renders with attributes', () => {
- const $ = render('breadcrumbs', examples.attributes)
-
- const $component = $('.govuk-breadcrumbs')
- expect($component.attr('id')).toBe('my-navigation')
- expect($component.attr('role')).toBe('navigation')
- })
-
- it('renders item as collapse on mobile if specified', () => {
- const $ = render('breadcrumbs', examples['with collapse on mobile'])
-
- const $component = $('.govuk-breadcrumbs')
- expect(
- $component.hasClass('govuk-breadcrumbs--collapse-on-mobile')
- ).toBeTruthy()
- })
-
- it('renders with inverted colours if specified', () => {
- const $ = render('breadcrumbs', examples.inverse)
-
- const $component = $('.govuk-breadcrumbs')
- expect($component.hasClass('govuk-breadcrumbs--inverse')).toBeTruthy()
- })
- })
-})