Router: Testing: Mock `navigate` with jest

Created on 13 Jun 2018  路  1Comment  路  Source: reach/router

I'm trying to mock navigate with jest to assert on invocations afterwards.

This is a simplified version of my test file:

import React from 'react'
import { render, Simulate } from 'react-testing-library'
import LogoutButton from './LogoutButton'

const mockNavigate = jest.fn()
jest.mock('@reach/router', () => ({
  navigate: mockNavigate,
}))

describe('<LogoutButton />', () => {
  it('handles logout on click', () => {
    const { getByText } = render(<LogoutButton />)
    Simulate.click(getByText(/logout/i))
    expect(mockNavigate).toHaveBeenCalledTimes(1)
    expect(mockNavigate).toHaveBeenCalledWith('/login')
  })
})

And a simplified version of the component under test:

import { navigate } from '@reach/router'
import React from 'react'

const LogoutButton = () =>(
  <button onClick={() => navigate('/login')}>Logout</button>
)

export default LogoutButton 

Simulate.click leads to TypeError: router_1.navigate is not a function.

At the moment, this doesn't seem to work and i'm not sure if it's me misunderstanding jest mocking or a problem with this lib. How would you mock navigate?

Most helpful comment

It was a misunderstanding of jest mocking. jest.mock calls are hoisted to the top, so mockNavigate in was undefined inside of jest.mock in the previous example.

This test works:

import { navigate } from '@reach/router'
import * as React from 'react'
import { render, Simulate } from 'react-testing-library'
import LogoutButton from './LogoutButton'

jest.mock('@reach/router', () => ({
  navigate: jest.fn(),
}))

describe('<LogoutButton />', () => {
  it('handles logout on click', () => {
    const { getByText } = render(<LogoutButton />)
    Simulate.click(getByText(/logout/i))
    expect(navigate).toHaveBeenCalledTimes(1)
    expect(navigate).toHaveBeenCalledWith('/login')
  })
})

>All comments

It was a misunderstanding of jest mocking. jest.mock calls are hoisted to the top, so mockNavigate in was undefined inside of jest.mock in the previous example.

This test works:

import { navigate } from '@reach/router'
import * as React from 'react'
import { render, Simulate } from 'react-testing-library'
import LogoutButton from './LogoutButton'

jest.mock('@reach/router', () => ({
  navigate: jest.fn(),
}))

describe('<LogoutButton />', () => {
  it('handles logout on click', () => {
    const { getByText } = render(<LogoutButton />)
    Simulate.click(getByText(/logout/i))
    expect(navigate).toHaveBeenCalledTimes(1)
    expect(navigate).toHaveBeenCalledWith('/login')
  })
})
Was this page helpful?
0 / 5 - 0 ratings

Related issues

benwiley4000 picture benwiley4000  路  4Comments

maieonbrix picture maieonbrix  路  4Comments

alexluong picture alexluong  路  3Comments

artoodeeto picture artoodeeto  路  4Comments

ricardobrandao picture ricardobrandao  路  5Comments