2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Jestで"Found a label with the text of: **, however no form control was found associated to that label."のエラーが出る

Posted at

はじめに

next.js×TypeScriptで作成したアプリに対して、Jestでテスト実行したところ、下記のようなエラーが出ました。
和訳すると「ラベルのテキスト(タイトル)は見つかったけど、そのラベルに関連付けられたフォームコントロールが見つからない。」とのことです。

TestingLibraryElementError: Found a label with the text of: タイトル, however no form control was found associated to that label. Make sure you're using the "for" attribute or "aria-labelledby" attribute correctly.

テスト時にはgetByLabelTextを使ってタイトルを取得しようとしています。

page.test.tsx
  it("フォームが正しく表示されること", () => {
    render(<Page />);

    expect(screen.queryByText("投稿作成")).toBeInTheDocument();
    expect(screen.getByLabelText("タイトル")).toBeInTheDocument();
    expect(screen.getByLabelText("内容")).toBeInTheDocument();
    expect(screen.getByLabelText("ユーザー名")).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "投稿" })).toBeInTheDocument();
  });

テスト対象コードはこちら

page.tsx
        <div>
          <label className="block mb-2 text-indigo-500">
           タイトル
         </label>
          <input
            className="w-full p-2 mb-2 text-indigo-700 border-b-2 border-indigo-500 outline-none focus:bg-gray-300"
            type="text"
            {...register("title")}
          />
          {errors.title && (
            <p className="text-red-500">{errors.title.message}</p>
          )}{" "}
        </div>

原因

私がgetByLabelTextの用法をいまいち理解しないまま使っていました。

公式ドキュメントにある通り、getByLabelTextは下記のように設定されたDOM構造の入力ノードを検索します。
つまり、<input>要素にid属性を追加し、<label>for属性と一致させる必要があります

tsx
// `username`を検索する例
<label for="username-input">Username</label>
<input id="username-input" />

上記のほかにも複数例載っています。

解決方法

上記の修正を適用して、<input>要素にid="title"を追加し、<label>要素にもidと同じ値 htmlFor="title"を付与しました
これで無事にテストが通りました。

page.tsx
        <div>
          <label htmlFor="title" className="block mb-2 text-indigo-500">
            タイトル
          </label>
          <input
            id="title"
            className="w-full p-2 mb-2 text-indigo-700 border-b-2 border-indigo-500 outline-none focus:bg-gray-300"
            type="text"
            {...register("title")}
          />
          {errors.title && (
            <p className="text-red-500">{errors.title.message}</p>
          )}{" "}
        </div>

おわりに

公式ドキュメントでは、使用するクエリの優先順位なんかも定義されています。
自分の知っているクエリだけを使いまわすんじゃなくて、しっかりと各クエリの用法を理解しながら適切な選択をしていきたいです。

2
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?