v13, v14の使用方法の違い

v13の場合

test('click', () => {
  render(<MyButton />);

  userEvent.click(screen.getByRole('button'));
  // ...
})

v14の場合

test('click', async () => {
  **const user = userEvent.setup(); // まずsetup**
  render(<MyButton />)

  **await** user.click(screen.getByRole('button'));
  // ...
})

※ユーザーイベントでstateを変更する場合は、user.click()の前にawaitはつけずに、次のテスト(state変更後に実施したいテスト)にawaitをつける&そのテストをwaitFor()でラップしてあげる必要あり。詳しくは以下を参照

stateを変更するならactで囲め!とエラーが出た場合

setupを共通関数化して使いやすく

基本の書き方だと、テストケースを書く度にconst user = userEvent.setup(); しないといけなくて面倒なので、共通関数化してしまうと楽になる

  1. 以下のようにuserEventのsetupと、コンポーネントのrenderを行う関数を用意する

    ファイル名はuserEvent.tsとかだと分かりやすいんじゃないかな

    export function setup(jsx: JSX.Element) {
      return {
        user: userEvent.setup(),
        ...render(jsx),
      }
    }
    
  2. 各テストファイル内で上記をインポートして使う

    例)

    import React from 'react';
    import { screen } from '@testing-library/react';
    **import { setup } from '../userEvent';**
    
    test('click', async () => {
      **const {user} = setup(<MyButton />);**
    
      **await user**.click(screen.getByRole('button'));
      // ...
    })
    

参考

【Testing Library】userEvent v14の破壊的変更(BREAKING CHANGE)

Introduction | Testing Library