Skip to content

Commit

Permalink
Unit tests for header.js (#900)
Browse files Browse the repository at this point in the history
* Add unit tests for header.js

---------

Co-authored-by: Mayank Patel <[email protected]>
  • Loading branch information
diana-nita and mayank1211 authored Nov 13, 2023
1 parent d1cfb58 commit 1cfec68
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 4 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# NHS.UK frontend Changelog

## 8.0.2 - 019 October 2023
## 8.0.3 - 13 November 2023

:wrench: **Fixes**

- Updated header component unit tests ([PR 900](https://github.com/nhsuk/nhsuk-frontend/pull/900)).

## 8.0.2 - 19 October 2023

:wrench: **Fixes**

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nhsuk-frontend",
"version": "8.0.2",
"version": "8.0.3",
"description": "NHS.UK frontend contains the code you need to start building user interfaces for NHS websites and services.",
"scripts": {
"prepare": "gulp bundle",
Expand Down
171 changes: 171 additions & 0 deletions tests/integration/jsdom/header.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import Header from '../../../packages/components/header/header.js'

describe('Header class', () => {
beforeEach(() => {
document.body.innerHTML = `
<div class="nhsuk-navigation"></div>
<div class="nhsuk-header__navigation-list">
<li style="width: 50px;">Health A-Z</li>
<li style="width: 75px;">NHS services</li>
<li style="width: 100px;">Live Well</li>
<li style="width: 125px;">Mental health</li>
<li style="width: 150px;">Care and support</li>
<li style="width: 275px;">Pregnancy</li>
<li style="width: 200px;">Home</li>
<li style="width: 225px;">More</li>
</div>
<div class="nhsuk-header__menu-toggle"></div>
<div class="nhsuk-mobile-menu-container"></div>
<div class="nhsuk-header__menu-toggle"></div>
`
})

it('Should create navigation elements in the DOM', async () => {
// Call the Header initialization function
await Header()

// Ensure the navigation elements are created in the DOM
expect(document.querySelector('.nhsuk-navigation')).not.toBeNull()
})

it('Should toggle mobile menu visibility', async () => {
const toggleButton = document.querySelector('.nhsuk-header__menu-toggle')
let mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')
// Call the Header initialization function
await Header()

mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')
// Initially, the menu should be closed
expect(mobileMenuList.classList.contains('nhsuk-header__drop-down--hidden')).toBe(true)

// Open the mobile menu
toggleButton.click()

expect(mobileMenuList.classList.contains('nhsuk-header__drop-down--hidden')).toBe(false)

// Close the mobile menu
toggleButton.click()

expect(mobileMenuList.classList.contains('nhsuk-header__drop-down--hidden')).toBe(true)
})

it('Should close menu when escape key is pressed', async () => {
//define a event for the escape key
const escapeKeyEvent = new KeyboardEvent('keydown', {
key: 'Escape',
code: 'Escape',
keyCode: 27,
which: 27,
charCode: 27
})
const toggleButton = document.querySelector('.nhsuk-header__menu-toggle')

await Header()

//Expect the menu to be hidden initially
expect(
document.querySelector('.nhsuk-header__drop-down').classList.contains('nhsuk-header__drop-down--hidden')
).toBe(true)

//Toogle the menu - open it
toggleButton.click()
expect(
document.querySelector('.nhsuk-header__drop-down').classList.contains('nhsuk-header__drop-down--hidden')
).toBe(false)

//Press the escape key to close it
document.dispatchEvent(escapeKeyEvent)
expect(
document.querySelector('.nhsuk-header__drop-down').classList.contains('nhsuk-header__drop-down--hidden')
).toBe(true)
})

it('Should setup the Mobile Menu Container during initialization', async () => {
const mobileMenuContainer = document.querySelector('.nhsuk-mobile-menu-container')
expect(mobileMenuContainer.childElementCount).toBe(0)
await Header()
expect(mobileMenuContainer.childElementCount).toBeGreaterThan(0)
})

it('Should setup the Mobile Menu List during initialization', async () => {
//Initially there won't be any ul elements inside the container- it gets added in the setupMobileMenu method
let mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')

//So we expect that to be null until it gets created
expect(mobileMenuList).toBe(null)

// Call the Header initialization function
await Header()

//We update the variable to hold the ul element from the container that has been created
mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')

expect(mobileMenuList).not.toBeNull()
expect(mobileMenuList.classList).toContain('nhsuk-header__drop-down')
expect(mobileMenuList.classList).toContain('nhsuk-header__drop-down--hidden')
})

it('Should not update navigation when the available space is enough for all elements', async () => {
const mobileMenuToggleButton = document.querySelector('.nhsuk-header__menu-toggle')
const mobileMenuContainer = document.querySelector('.nhsuk-mobile-menu-container')
const navigationElement = document.querySelector('.nhsuk-navigation')
const navigationList = document.querySelector('.nhsuk-header__navigation-list')
let mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')

// Spy on offsetWidth property for navigation element
const navigationOffsetWidthSpy = jest.spyOn(HTMLElement.prototype, 'offsetWidth', 'get')
// Mock offsetWidth for navigation element
navigationOffsetWidthSpy.mockImplementation(function () {
if (this === navigationElement) {
return 1000 // Mock navigation element offsetWidth
}
return 50 // Mock children offsetWidth
})

await Header()

// breakpoints will be [50,100,150,200,250,300,350,400]
// the available space - navigation offsetWidth - will be greater than the last element from the breakpoints array
// meaning we don't need the mobile menu to get any items from the navigation
expect(mobileMenuToggleButton.classList.contains('nhsuk-header__menu-toggle--visible')).toBe(false)
expect(mobileMenuContainer.classList.contains('nhsuk-mobile-menu-container--visible')).toBe(false)

mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')
expect(mobileMenuList.children).toHaveLength(0)
expect(navigationList.children).toHaveLength(8)

navigationOffsetWidthSpy.mockRestore()
})

it('Should update navigation when the available space is not enough for all elements', async () => {
const mobileMenuToggleButton = document.querySelector('.nhsuk-header__menu-toggle')
const mobileMenuContainer = document.querySelector('.nhsuk-mobile-menu-container')
const navigationElement = document.querySelector('.nhsuk-navigation')
const navigationList = document.querySelector('.nhsuk-header__navigation-list')
let mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')

// Spy on offsetWidth property for navigation element
const navigationOffsetWidthSpy = jest.spyOn(HTMLElement.prototype, 'offsetWidth', 'get')
// Mock offsetWidth for navigation element
navigationOffsetWidthSpy.mockImplementation(function () {
if (this === navigationElement) {
return 700 // Mock navigation element offsetWidth
}
return 100 // Mock children offsetWidth
})

await Header()

// breakpoints will be [100,200,300,400,500,600,700,800]
// the available space - navigation offsetWidth - will be smaller than the last element from the breakpoints array
// meaning we need the mobile menu to get 1 item from the navigation
expect(mobileMenuToggleButton.classList.contains('nhsuk-header__menu-toggle--visible')).toBe(true)
expect(mobileMenuContainer.classList.contains('nhsuk-mobile-menu-container--visible')).toBe(true)

mobileMenuList = document.querySelector('.nhsuk-mobile-menu-container ul')
expect(mobileMenuList.children).toHaveLength(1)
expect(navigationList.children).toHaveLength(7)

navigationOffsetWidthSpy.mockRestore()
})
})

0 comments on commit 1cfec68

Please sign in to comment.