2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vitest】TestingLibraryElementError: Found multiple elements with the text: が発生

2
Posted at

はじめに

改修中の学習記録アプリを、Vitestを使用してテストしたところ、エラーに遭遇しました。

問題

学習内容と、学習時間を入力後に登録ボタンを押下して一覧に記録されるかテストコードを書いてテストをすると、タイトルのエラーが発生した。

・問題のテストコード

test("学習内容と時間を入力して登録ボタンを押すと新たに記録が追加することが出来る", async () => {
    render(<LearnLog />);

    await waitForElementToBeRemoved(() => screen.getByText("ロード中..."));

    const inputTitle = await screen.getByText("");
    const inputTime = await screen.getByText("0");
    const addButton = await screen.getByRole("button", {name: "登録"});

    fireEvent.change(inputTitle, { target: { value: "テスト"}});
    fireEvent.change(inputTime, { target: { value: "10"}});
    fireEvent.click(addButton);

    const list = screen.getByRole("list");
    expect(within(list).getByText("テスト")).toBeInTheDocument();
    expect(within(list).getByText("10")).toBeInTheDocument();
   
  });

・エラー内容(長いので中略します)

 FAIL  src/tests/LearnLog.test.jsx > 学習記録アプリのテスト > 学習内容と時間を入力して登録ボタンを押すと新たに記録が追加することが出来る
TestingLibraryElementError: Found multiple elements with the text:

Here are the matching elements:

Ignored nodes: comments, script, style
<body>
  <div>
    <h1>
      学習記録一覧
    </h1>
    <ul>
      <div>
        学習内容
        <input
          type="text"
          value=""
        />
      </div>
      <div>
        学習時間
        <input
          type="number"
          value="0"
        />
        時間
      </div>
      <div>
        入力されている学習内容:
        <label />
      </div>
      <div>
        入力されている学習時間:
        <label>
          0
        </label>
        時間
      </div>
      <li>
        <label>
          英語

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          数学

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          React

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <li>
        <label>
          テスト

          10
          時間
        </label>
        <button>
          削除
        </button>
      </li>
      <button>
        登録
      </button>
      <div />
      <div>
        合計時間:
        110
        /1000(h)
      </div>
    </ul>
  </div>
</body>

Ignored nodes: comments, script, style
<div>
  <h1>
    学習記録一覧
  </h1>
  <ul>
    <div>
      学習内容
      <input
        type="text"
        value=""
      />
    </div>
    <div>
      学習時間
      <input
        type="number"
        value="0"
      />
      時間
    </div>
    <div>
      入力されている学習内容:
      <label />
    </div>
    <div>
      入力されている学習時間:
      <label>
        0
      </label>
      時間
    </div>
    <li>
      <label>
        英語

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        数学

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        React

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        テスト

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        テスト

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        テスト

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        テスト

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        テスト

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        テスト

        10
        時間
      </label>
      <button>
        削除
      </button>
    </li>
    <li>
      <label>
        テスト
(中略)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 ❯ Object.getElementError node_modules/@testing-library/dom/dist/config.js:37:19
 ❯ getElementError node_modules/@testing-library/dom/dist/query-helpers.js:20:35
 ❯ getMultipleElementsFoundError node_modules/@testing-library/dom/dist/query-helpers.js:23:10
 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:55:13
 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:95:19
 ❯ src/tests/LearnLog.test.jsx:35:37
     33|     await waitForElementToBeRemoved(() => screen.getByText("ロード中..."));
     34|
     35|     const inputTitle = await screen.getByText("");
       |                                     ^
     36|     const inputTime = await screen.getByText("0");
     37|     const addButton = await screen.getByRole("button", {name: "登録"});

学習内容テキストボックス内の要素を取得したかった為、以下のgetByTextを使用しました。初期値は空文字の為、引数も空文字にしました。

しかし、input要素が発見されないようで、うまくいきませんでした。

const inputTitle = await screen.getByText("");

解決方法

getByText→getByDisplayValueに修正すると、テストがPassされました。こうすると、input要素を的確に拾ってきてくれるようです。

test("学習内容と時間を入力して登録ボタンを押すと新たに記録が追加することが出来る", async () => {
    render(<LearnLog />);

    await waitForElementToBeRemoved(() => screen.getByText("ロード中..."));

    const inputTitle = screen.getByDisplayValue(""); 
    const inputTime = screen.getByDisplayValue("0");
    const addButton = screen.getByRole("button", {name: "登録"});

    fireEvent.change(inputTitle, { target: { value: "テスト"}});
    fireEvent.change(inputTime, { target: { value: "10"}});
    fireEvent.click(addButton);

    const list = screen.getByRole("list");
    expect(await within(list).findByText("テスト")).toBeInTheDocument();
    expect(await within(list).findByText("10")).toBeInTheDocument();
  });
 ✓ src/tests/LearnLog.test.jsx (2 tests) 1100ms
   ✓ 学習記録アプリのテスト (2)
     ✓ タイトルが表示されている  832ms
     ✓ 学習内容と時間を入力して登録ボタンを押すと新たに記録が追加することが出来る 264ms

 Test Files  1 passed (1)
      Tests  2 passed (2)
   Start at  16:42:10
   Duration  1.45s

 PASS  Waiting for file changes...
       press h to show help, press q to quit

おわりに

テストコードは中々難しく感じますが、徐々に慣れていきたいと思います。

参考

2
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?