Jest Video Tutorial


In this video I propose you to discover the test framework Jest. It has the advantage of working simply (no / little configuration needed) and quickly thanks to its ability to run tests in parallel.

The installation

The installation is done simply using your packages. You can also install the declaration files to help your publisher.

yarn add -D jest @ types / jest

You can also take the opportunity to create a configuration file automatically with the command.

npx jest --init

To start the tests you just need to use the command jest or use the script test (if you chose to add it to your package.json)

npx jest

This command will search for files ending with .test.js or in the folder __tests__ and try to execute them.

Basic structure

Contrary to other test frameworks that we have seen so far. Jest integrates all the functions necessary for the tests.

  • describe () to define a scenario
  • it () or test() to describe a test
  • expect () to handle assertions

It is interesting to note that Jest supports default asynchronous tests. Simply declare the callback as an asynchronous function for this kind of situation.

describe ('Timer', function () {

  it.concurrent ('should wait 3 seconds', async function () {
    const t = Date.now ()
    await sleep (3)
    expect (Date.now () - t) .toBeGreaterThanOrEqual (3000)
  })

  it.concurrent ('should wait 2 seconds', async function () {
    const t = Date.now ()
    await sleep (2)
    expect (Date.now () - t) .toBeGreaterThanOrEqual (2000)
  })

})

Mocker to better test

You can also create mock to test your functions without relying on third-party components. For example, if you want to test a function of your bot discord you have to be able to simulate operations.

To create a mock just use the function Jest.fn (), this function returns a mock which is a function that returns undefined if called. It is then possible to inspect the calls and modify the return values ​​if necessary.

import {ping} from '../src/discord.js'

describe ('Discord', function () {

  it ('should dm the user', async function () {
    const channelMock = {
      send: jest.fn ()
    }
    const createDMMock = jest.fn (). mockResolvedValue (channelMock)
    const message = {
      delete: jest.fn (). mockResolvedValue ({}),
      reply: jest.fn (),
      author: {
        createDM: createDMMock
      }
    }
    await ping (message)
    expect (message.delete) .toHaveBeenCalled ()
    expect (channelMock.send) .toHaveBeenCalledWith ( 'Pong')
  })

  it ('should reply to the user if dm are deactivated', async function () {
    const createDMMock = jest.fn (). mockRejectedValue ({})
    const message = {
      delete: jest.fn (). mockResolvedValue ({}),
      reply: jest.fn (),
      author: {
        createDM: createDMMock
      }
    }
    await ping (message)
    expect (message.delete) .toHaveBeenCalled ()
    expect (message.reply) .toHaveBeenCalledWith ( 'Pong')
  })

})

On the other hand, sometimes the script to be tested uses a dependency that is not exposed from outside (like axios for example). It's still possible to test things with Jest.
For this we will use the method jest.mock () which will replace the addiction with a mock when it is requested (it will be necessary to think about cleaning the mock before each test).

import Users from '../src/users.js'
import axios from 'axios'

jest.mock ( 'axios')

describe ('Users', function () {

  beforeEach (() => {
    axios.mockClear ()
  })

  const fakeResponse = ({name: 'John Doe'})

  it ('should return last user', async () => {
    axios.get.mockResolvedValue ({data: fakeResponse})
    expect (await Users.getLastUserName ()). toBe ('John Doe')
  })

})

If your code targets browsers and you use fetch () you can still mock it using the package jest-fetch-mock.

Test the DOM without browser via JSDOM

Finally if your library handles the DOM it is possible to test it without necessarily using a browser. For that Jest integrates jsdom which implements several standard web directly on NodeJS.

test ('displays content after click', function () {

  document.body.innerHTML = `
here is my hidden content
`   require ( '../ src / spoiler.js')   const spoilerButton = document.querySelector ('. spoiler button')   const spoilerText = document.querySelector ('. spoiler span')   expect (spoilerButton) .not.toBeNull ()   expect (spoilerText) .not.toBeNull ()   expect (spoilerText) .not.toHaveClass ( 'visible')   spoilerButton.click ()   expect (spoilerText) .toHaveClass ( 'visible') })