2
1

問題

React Testing Libraryを使用してテストを実装している中で、screen.getByText('XXXX');を使用すると以下のエラーが発生する。

 Unable to find an element with the text: XXX 

やったこと

まずは該当のコードをwaitFor関数で囲みます。

こうすることで非同期操作が完了するまで、テキストを取ってくるのを待ってくれるようになります。

以下が修正コードです。

await waitFor(() => {
const contentElement = screen.getByText('XXXX');
const timeElement = screen.getByText('10');

expect(contentElement).toBeInTheDocument();
expect(timeElement).toBeInTheDocument();
});

まだ同じエラーが出ましたが補足分がついてきました。

Unable to find an element with the text: XXX 
This could be because the text is broken up by multiple elements.
In this case, you can provide a function for your text matcher 
to make your matcher more flexible.

「取得したい要素が複数の要素の可能性があるため、もう少し柔軟なマッチャーを使用してみて」と言われています。

ここでカスタムマッチャーを使ってみて独自の条件を指定することにしました。
カスタムマッチャーを使用することで、より広範囲でテキスト合致を検索をすることができます。

await waitFor(() => {
const contentElement = screen.getByText((content, element) => {
return element.textContent.includes('XXXX');
});

const timeElement = screen.getByText((content, element) => {
return element.textContent.includes('10');
});

expect(contentElement).toBeInTheDocument();
expect(timeElement).toBeInTheDocument();

});

ここで、Unable to find an element with the text: XXXのエラーが出なくなりました。

代わりに以下のエラーが発生しました。

(If this is intentional, then use the `*AllBy*` variant of the query
(like `queryAllByText`, `getAllByText`, or `findAllByText`))

中身を読むと「Allby〜」を使ってくださいと言われています。

言う通りに、getAllbyTextを使用することにしました。以下が変更後のコードです。

await waitFor(() => {
    const contentElements = screen.getAllByText((content, element) => {
      return element.textContent.includes("テスト学習内容");
    });
    const timeElements = screen.getAllByText((content, element) => {
      return element.textContent.includes("10時間");
    });

    expect(contentElements.length).toBeGreaterThan(0);
    expect(timeElements.length).toBeGreaterThan(0);

    contentElements.forEach((element) => {
      expect(element).toBeInTheDocument();
    });
    timeElements.forEach((element) => {
      expect(element).toBeInTheDocument();
    });

上記のコードでエラーが発生しなくなり、無事解決をすることができました。

getByTextとgetAllByTextの違い

それぞれの違いを知っていないと使う時にエラーの原因になってしまうので、要点を記載します。

getByText

使用目的:DOM内の指定されたテキストを含む要素を1つだけ取得

結果の型:単一の要素

getAllByText

使用目的:DOM内の指定されたテキストを含むすべての要素を取得

結果の型:要素の配列


上記の通り、getAllByTextは結果が配列として返ってくるので要素の取り出しにはforEachなどを使用するようにしてください。

おわりに

今回はエラーに続くエラーで解消が大変でしたが、getAllByTextについて学ぶいい機会となりました。

2
1
0

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
1