Thi's avatar
HomeAboutNotesBlogTopicsToolsReading
About|My sketches |Cooking |Cafe icon Support Thi
πŸ’Œ [email protected]

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

Anh-Thi Dinh
draft
Next.jsWeb Dev
Left aside
⚠️
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

β—†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
About|My sketches |Cooking |Cafe icon Support Thi
πŸ’Œ [email protected]
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})