React Testing Libraryにチャレンジ 2 (現在進行形)

3 min read読了の目安(約3100字

前回はこちら

https://zenn.dev/k_matsumoto/articles/1ca53997a1df5f

Youtubeやってます。
チャンネル登録よろしくお願いします。

https://youtu.be/3ZLQL2jrkow

テストを書く動機になれば幸いです

https://www.youtube.com/watch?v=m5BXbUubDlE

今回はformやbuttonのテストになるかと思います。

afterEachとcleanup()

なんかテストを実行すると前のテスト結果が残っている状態があるので
さらにしてからテストする必要があります。

afterEach(() => cleanup());

getByPlaceholderText

テキストエリアとかに初期値として文字を記載できるかと思います。
そのplaceholderがなんなのか?をテストできるかと思います。

expect(screen.getByRole("button")).toBeTruthy();
expect(screen.getByPlaceholderText("Enter")).toBeTruthy();

こんな感じですね。

<input
 type="text"
 placeholder="Enter"
 value={input}
 onChange={updateValue}
/>

userEvent.type

テストをするとき仮の入力値を設定したいなとかあるじゃないですか?
そんな時はこのuserEvent.typeがいいかと

まずはuserEventをインポートします
次にinputValueを定義します。この時はplacehoderがenterの部分をinputValueに代入しました。
userEvent.typeで第一引数にその要素、第二引数に値を入れます。

そうするとinputValue.valueの中身はtestになるので
expectのテストが通る仕掛けになっています。

ここで覚えておきたいのは
inputのテストをするときは
userEvent.type(inputの要素, 値)
expect(inputの要素.value).toBe(値);

この流れかと思います。

import userEvent from "@testing-library/user-event";

it("Should update input value correctly", () => {
    render(<RenderInput />);
    const inputValue = screen.getByPlaceholderText("Enter");
    userEvent.type(inputValue, "test");
    expect(inputValue.value).toBe("test");
  });

入力値がある時に動作するボタンのテスト

次はこのようにプロパティを受け渡すことのできるものとします
buttonを押すとoutputValueの関数が実行されます。
ただし、このoutputValueはinputがfalseだと実行されない仕様になっています。
そこでupdateValueを使用してinputタグの中に入力されるとsetInput関数でinputに値をセットしていきます。

といった流れになります。

import React from "react";

const RenderInput = ({ outputConsole }) => {
  const [input, setInput] = React.useState("");

  const outputValue = () => {
    if (input) {
      outputConsole(input);
    }
  };

  const updateValue = (e) => {
    setInput(e.target.value);
  };
  return (
    <div>
      <input
        type="text"
        placeholder="Enter"
        value={input}
        onChange={updateValue}
      />
      <button onClick={outputValue}>Console</button>
    </div>
  );
};

export default RenderInput;

これは2つのテストを実行しました
1 入力値がない時のテスト
2 入力値がある時のテスト
551か!!

Should not trigger output functionがない時です
Should trigger output functionがある時です。
renderするときにoutputConsoleを渡しています。
この時にjest.fn()とすることでモック関数なるものを作るみたいです。

.not

そうでない。

.toHabeBeenCalled

関数が呼ばれた

.toHaveBeenCalledTimes(回数)

関数が呼ばれた回数

どういう時に使うのか?

想定通りの挙動になっているか?
これはテストの意味合いが強いかなと。

  it("Should not trigger output function", () => {
    const outputConsole = jest.fn();
    render(<RenderInput outputConsole={outputConsole} />);
    userEvent.click(screen.getByRole("button"));
    expect(outputConsole).not.toHaveBeenCalled();
  });
  it("Should trigger output function", () => {
    const outputConsole = jest.fn();
    render(<RenderInput outputConsole={outputConsole} />);
    const inputValue = screen.getByPlaceholderText("Enter");
    userEvent.type(inputValue, "test");
    userEvent.click(screen.getByRole("button"));
    expect(outputConsole).toHaveBeenCalledTimes(1);
  });

・・・続く