はじめに
タイトルの通り input タグで入力フォームを作る際の readonly 属性のテストにつまずくことがあったので、解決方法を共有できればなと思います。
環境
{
"react": "^18.2.0",
"@mui/material": "5.14.13",
"@testing-library/react": "14.0.0",
"typescript": "^5.2.2",
"vite": "^4.4.9",
"vitest": "0.29.8"
}
テストフレームワークに vitest
と react-testing-library
を使用しています。
テストコード
一番最初に readonly
属性のテスト時の検証方法から述べます。
readonly属性がある(trueの)場合
render(
<input label="入力フォーム" readonly />
);
// HTML要素を取得する
const input = screen.getByRole("textbox");
// HTML要素に`readonly`属性が付与されていることを期待する
expect(input).toHaveAttribute("readonly");
上記のテストコードで <input readonly />
のように readonly
属性がある場合、テストが通ります。
readonly属性がない(falseの)場合
screen.debug()
を使って readonly
属性が true
の場合と false
の場合を見てみます。
render(
<input label="入力フォーム" readonly />
);
screen.debug();
render(
<input label="入力フォーム" readonly={false} />
);
screen.debug();
readonly
属性がある場合、 readonly=""
となり、 readonly
が false
の場合、そもそも readonly
属性が存在しないこととみなされます。
なので expect(input.getAttribute("readonly")).toBeFalsy()
というように真偽値で取得できません。 .not.toHaveAttribute("readonly")
を使うことで readonly=false
のテストできます。
MUIのを使う場合
MUI の TextField を使う場合、<TextField />
に readonly
属性を渡しても入力不可能な状態にはなりません。
render(<TextField label="input" readOnly={true} />);
screen.debug();
input タグのや要素の div タグに readonly
属性が付与され、 input タグには存在していません。
解決するには <TextField />
の inputProps
に readOnly
を加えて渡せば OK です。
<TextField label="入力フォーム" inputProps={{ readOnly: true }} />
この場合も input タグと同様のテストで検証できます。
test("readOnly:true", () => {
render(<TextField label="input" inputProps={{ readOnly: true }} />);
const input = screen.getByRole("textbox");
expect(input).toHaveAttribute("readonly");
});