d
Amit DhamuSoftware Engineer
 

Spying on localStorage in Jest

2 minute read 00000 views

Take a really simple button component as below.

const Button = () => (
  <button
    onClick={() => {
      window.localStorage.setItem('clicked', 'yes')
    }}
  >
    Click Me
  </button>
)

We want to write a test that asserts the interaction with localStorage when the button is clicked. To do this is pretty simple.

Setting up the test file

import * as React from 'react'
import Button from './Button'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

describe('Button', () => {
  jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem')
  Object.setPrototypeOf(window.localStorage.setItem, jest.fn())
})

As you can see, the first thing we do is add a Jest spy function which will watch the setItem method of localStorage.

In addition, it then mocks this to a jest.fn() so we can use it in an assertion later.

Writing the test

import * as React from 'react'
import Button from './Button'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

describe('Button', () => {
  jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem')
  Object.setPrototypeOf(window.localStorage.setItem, jest.fn())

  it('calls localStorage.setItem when clicked', () => {
    render(<Button />)

    userEvent.click(screen.getByRole('button', { name: 'Click Me' }))

    expect(window.localStorage.setItem).toHaveBeenCalledWith('clicked', 'yes')
  })
})

Explanation

As we are using @testing-library/react, we first render the component, then click the Button using userEvent which then allows us to assert the localStorage call.