背景
React Testing Libraryでテストを書くとき、たまに<span>
や<div>
などrole属性が設定されていないタグを取得したい場面がある。Testing Libraryのクエリはアクセシビリティを意識したものになっているため、<div>
のようにrole属性がないタグをそのまま取得する手段は少ない。
そもそも可能な限りTesting Libraryのクエリで取得可能なHTML構成・テストケースを検討するべきだが、どうしても難しいときもある。かといってクエリを書くためだけにrole属性をつけてしまうと本当に必要な人が困ってしまう。読み上げリーダーやキーボード操作はrole属性を参照するためである。本来の意図からずれたrole属性はWebページの意図を正しく伝えることができない。よって避けたい。
取得方法
次の方法を使うことで、role属性を付与せずテストを実行できる。
- Document.querySelector()を使って
container
要素から指定のHTMLタグを取得する - jest-domのmatcherを使ってテストする
import React from "react"; import StarRating from "../StarRating"; export interface Colors { id: string; title: string; color: string; rating: number; } export default function Color({ id, title, color, rating }: Colors) { return ( <section> <h1>{title}</h1> <span>色を選ぶ</span> <div style={{ height: 50, backgroundColor: color }}></div> </section> ); }
import React from "react"; import Color from "."; import { render } from "@testing-library/react"; // 可能ならこちらの方法で取得したい it("色を選ぶテキストがレンダリングされていること", () => { const content = render(<Color id="1" title="red" color="#f00" rating={3} />); expect(content.getByText("色を選ぶ")).toBeInTheDocument(); }); // spanタグのようにrole属性が存在しないHTMLタグを取得する場合 it("spanタグの中に色を選ぶテキストがレンダリングされていること", () => { const content = render(<Color id="1" title="red" color="#f00" rating={3} />); // spanタグ要素を取得 const span = content.container.querySelector("span"); // 取得した要素の中にテキストが存在すること expect(span).toHaveTextContent("色を選ぶ"); });
説明など
@testing-library/react
のrender
関数で取得したコンテンツからRenderResult
型の要素を取得できる。
export function render( ui: React.ReactElement, options?: Omit<RenderOptions, 'queries'>, ): RenderResult
取得結果のcontainer
を見ると、Document.querySelector()が使える型で値が取得できる。
export type RenderResult< Q extends Queries = typeof queries, Container extends Element | DocumentFragment = HTMLElement, →ElementかDocumentFragmentのいずれかになる or HTMLElementが適用される BaseElement extends Element | DocumentFragment = Container, > = { container: Container // 省略 }
Document.querySelector()はid・class・任意のHTMLタグを取得できる。今回は任意のHTMLタグを取得している。
…という具合でクエリが書ける。型が変わるため、さらにTesting Libraryのクエリを書けない点は注意が必要。 また、Document.querySelector()はnullが推論される点も注意が必要。
// HTMLSpanElementとして推論されているためTesting Libraryのクエリは使えない。 expect(span).getByText("色を選ぶ");
知っていればできるが、ここに辿り着かないとなかなか書けないなと思った。
参考文献
- https://testing-library.com/docs/queries/about
- https://testing-library.com/docs/dom-testing-library/faq
- https://testing-library.com/docs/guiding-principles/
- https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span
- https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div
- https://developer.mozilla.org/ja/docs/Web/API/Document/querySelector
- https://zenn.dev/yusukehirao/articles/e3512a58df58fd