Thi Notes
AboutNotesBlogTopicsToolsReading
About|Sketches |Cooking |Cafe icon Support Thi

Next.js Testing with Jest and Testing Library (working note)

Next.js Testing with Jest and Testing Library (working note)

Anh-Thi Dinh
draft
Next.js
Web Dev
⚠️
This is a quick & dirty draft, for me only!

References

  • Testing Library | Testing Library
  • Testing Playground
  • About Queries | Testing Library ← understand types of queries like getBy, findBy, queryBy,…
  • Cheatsheet | Testing Library

Basic

☝
You should find your elements in the test the same way users will find them! For example, testing-library doesn’t have getById for an input because users don’t care about an id of an element, they find that element by its placeholder text instead.
Use data-testid and .getByTestId().

Watch test only 1 file

yarn test (jest --watch in package.json) then press p to filter based on file name regex.

Expect to be / not to be in document

  • Expect not to be in the document → queryBy instead of findBy because queryBy returns a null (no error) whereas findBy throws an error instead!
  • Expect to be in the docyment → can use either queryBy or findBy!

Find an element

  • Find an image → getByAltText
  • Find an input
    • Or using ByPlacehoderText
  • Dropdown options → check this SO.
    • Idea: Add data-testid to options, then get the options by getAllByTestId, then check the sected option.
    • Can use getByDisplayValue for selected option.

Mocking

Check more in Unit Testing with JestJS

Mocking fetch

 

Mocking an external library

Check more in Unit Testing with JestJS

Troubleshooting

In this post
◆References◆Basic○Watch test only 1 file◆Expect to be / not to be in document◆Find an element◆Mocking○Mocking fetch○Mocking an external library◆Troubleshooting
1// .tsx
2<input
3  data-testid="ulid-input"
4/>
1// .test.tsx
2const input = screen.getByTestId('ulid-input')
1const nameInput = screen.queryByPlaceholderText('Enter name...')
2expect(nameInput).not.toBeInTheDocument()
1<label htmlFor="abc">Text Input</label>
2<input id="abc" ... />
1import {screen} from '@testing-library/dom'
2const inputNode = screen.getByLabelText('Text Input')
1<option data-testid="select-option" key={item.key} value={item.key}>
2  {item.label}
3</option>
4
5// in test
6// 
7const options = getAllByTestId(container, 'select-option')
8expect(options[0].selected).toBeFalsy();
9expect(options[1].selected).toBeTruthy();
1global.fetch = jest.fn()
2
3it('...', async () => {
4	jest.spyOn(global, 'fetch').mockImplementation(() =>
5    Promise.resolve({
6      status: 401,
7      json: () => Promise.resolve({ message: 'Invalid API key' })
8    } as Response)
9  )
10})
1// main
2import {
3  NIL as NIL_UUID,
4  validate as uuidValidate,
5  v1 as uuidv1,
6  v3 as uuidv3,
7  v4 as uuidv4,
8  v5 as uuidv5
9} from 'uuid'
1// globally
2jest.mock('uuid', () => ({
3  NIL: '00000000-0000-0000-0000-000000000000',
4  validate: jest.fn(),
5  v1: jest.fn().mockReturnValue('b1d82820-866b-11ee-b7d9-7f085416ca4d'),
6  v3: jest.fn().mockReturnValue('c87ee674-4ddc-3efe-a74e-dfe25da5d7b3'),
7  v4: jest.fn().mockReturnValue('4dc3ae1d-a39e-49f3-b73e-e0cf2e3ca6ce'),
8  v5: jest.fn().mockReturnValue('4ebd0208-8328-5d69-8c44-ec50939c0967')
9}))
1// locally
2import uuid from 'uuid'
3
4jest.mock('uuid', () => ({
5  NIL: '00000000-0000-0000-0000-000000000000',
6  validate: jest.fn(),
7  v1: jest.fn(),
8  v3: jest.fn(),
9  v4: jest.fn(),
10  v5: jest.fn()
11}))
12
13it('....', () => {
14	jest.spyOn(uuid, 'validate').mockReturnValueOnce(false)
15})