Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate template tests from Cheerio to jsdom #5010

Open
9 of 38 tasks
36degrees opened this issue May 23, 2024 · 0 comments
Open
9 of 38 tasks

Migrate template tests from Cheerio to jsdom #5010

36degrees opened this issue May 23, 2024 · 0 comments
Labels
epic Epics are used in planning project boards to group related stories javascript tooling

Comments

@36degrees
Copy link
Contributor

36degrees commented May 23, 2024

What

Update the existing template tests to use jsdom and the matchers provided by @testing-library/jsdom rather than loading the HTML into a Cheerio instance.

Remove the dependency on Cheerio.

Why

We currently render the template to HTML and then load it into a Cheerio instance which we can use to check the state of the HTML by using Cheerio methods like hasClass.

However, if we instead used jsdom (through jest-environment-jsdom) we can make use of the matchers provided by @testing-library/jsdom).

Before:

    it('renders with classes', () => {
      const $ = render('button', examples.classes)

      const $component = $('.govuk-button')
      expect($component.hasClass('app-button--custom-modifier')).toBeTruthy()
    })

After:

    it('renders with classes', () => { 
      document.body.innerHTML = render('button', examples.grey)

      const $component = document.querySelector('.govuk-button')
      expect($component).toHaveClass('app-button--custom-modifier')
    })

It'd also allow us to use other more useful matchers like toHaveAccessibleDescription, toHaveName, toHaveRole which are simpler and better convey intention than checking the association as we currently do:

Before:

    it('associates the input as "described by" the hint', () => {
      const $ = render('input', examples['with hint text'])

      const $input = $('.govuk-input')
      const hintId = $('.govuk-hint').attr('id')

      const describedBy = new RegExp(
        `${WORD_BOUNDARY}${hintId}${WORD_BOUNDARY}`
      )

      expect($input.attr('aria-describedby')).toMatch(describedBy)
    })

After:

    it('associates the input as "described by" the hint', () => {
      document.body.innerHTML = render('input', examples['with hint text'])

      const $input = document.querySelector('.govuk-input')
      expect($input).toHaveAccessibleDescription(
        "It’s on your National Insurance card, benefit letter, payslip or P60. For example, ‘QQ 12 34 56 C’."
      )
    })

Finally, given we aren't using jQuery anywhere else in the codebase, this also means that we only need to remember a single syntax, rather than switching between 'vanilla JavaScript' in our JavaScript and the jQuery-esque Cheerio syntax.

Who needs to work on this

Developers

Who needs to review this

Developers

Done when

Update the template tests

Preview Give feedback

Tidy up

Preview Give feedback
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
epic Epics are used in planning project boards to group related stories javascript tooling
Projects
None yet
Development

No branches or pull requests

2 participants