React Testing Libraryを使ってみた(イベント編)

はじめに

前回はコンポーネントに文字が表示されている事をテストするだけの簡単なものでした。
今回のイベント編ではボタン押下のイベントをテストしてみます。

テスト

テスト対象コンポーネント

今回のテスト対象のコンポーネントです。
ボタンをクリックすると「a」をコンソールに出力します。

import React from "react";
 
const Event = () => {
  return (
    <div>
      <button onClick={() => console.log('a')}>button</button>
    </div>
  );
};
 
export default Event;

テストコード

import React from 'react'
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
 
import Event from './Event'
 
describe('ボタンクリックイベント', () => {
  const mockedConsole = console.log = jest.fn();
 
  it('buttonをクリックするとコンソールにaが出力される事', () => {
    render(<Event />)
 
    userEvent.click(screen.getByRole('button'));
    expect(mockedConsole.mock.calls[0][0]).toEqual('a');
  })
})

console.logをモックにしています。

const mockedConsole = console.log = jest.fn();

screen.getByRole('button’)でボタンを取得し、それをuserEvent.click()に渡す事でボタンをクリックしています。

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

ボタンをクリックした結果、「a」がコンソールに出力された事をテストしています。

expect(mockedConsole.mock.calls[0][0]).toEqual('a');

補足

ボタンが2個ある場合

const Event = () => {
  return (
    <div>
      <button onClick={() => console.log('a')}>button1</button>
      <button onClick={() => console.log('b')}>button2</button>
    </div>
  );
};

ボタンが複数ある場合、 screen.getByRole('button’)だとエラーになります。
screen.getAllByRole('button’)を使用する事で以下のように書けます。

it('button1をクリックするとコンソールにaが出力される事', () => {
  render(<Event />)
 
  const button = screen.getAllByRole('button')[0];
  userEvent.click(button);
  expect(mockedConsole.mock.calls[0][0]).toEqual('a')
})
 
it('button2をクリックするとコンソールにbが出力される事', () => {
  render(<Event />)
  
  const button = screen.getAllByRole('button')[1];
  userEvent.click(button);
  expect(mockedConsole.mock.calls[0][0]).toEqual('b')
})

今回は「button1」「button2」というテキストが付いているので、以下の方法もあります。

it('button1をクリックするとコンソールにaが出力される事', () => {
  render(<Event />)
 
  const button = screen.getByRole((role, element) => role === 'button' && element.textContent === 'button1');
  userEvent.click(button);
  expect(mockedConsole.mock.calls[0][0]).toEqual('a')
})
 
it('button2をクリックするとコンソールにbが出力される事', () => {
  render(<Event />)
  
  const button = screen.getByRole((role, element) => role === 'button' && element.textContent === 'button2');
  userEvent.click(button);
  expect(mockedConsole.mock.calls[0][0]).toEqual('b')
})