はじめに
エラー文が出力されてるかのテストができた!!って思ったんですが、検証する文章を変更しても通ってしますということがありました。
問題
問題のコードとテストコードです。
<Field.Root>
<Field.Label htmlFor="name">お名前</Field.Label>
<Input data-testid="register-name" id="name" {...register('name', { required: 'お名前は必須です' })} />
{errors.name && (
<Text role="alert" aria-live="polite" data-testid="register-error-name" style={{ color: 'red' }} textStyle="sm">
{errors.name.message}
</Text>
)}
</Field.Root>
test('名前がないときにエラーメッセージがでる', async () => {
const user = userEvent.setup();
renderPage();
const submitButton = await screen.findByTestId('register-submit-button');
await user.click(submitButton);
waitFor(() => {
expect(screen.getByTestId('register-error-name')).toHaveTextContent('お名前は必須です');
});
});
このコードだと、文字列を変えてもテストが通ってしまします。
解決方法
test('名前がないときにエラーメッセージがでる', async () => {
const user = userEvent.setup();
renderPage();
const submitButton = await screen.findByTestId('register-submit-button');
await user.click(submitButton);
+ await waitFor(() => {
expect(screen.getByTestId('register-error-name')).toHaveTextContent('お名前は必須です');
});
});
waitFor(()の前にawaitを入れれば解決です!
おわりに
waitForはPromise(あとで完了する約束)を返す非同期関数です。awaitしないと、waitFor がリトライして検証を終える前にテストが終了してしまい、expect の失敗がテスト結果に反映されないことがある。だから await waitFor(...) として、検証が完了するまでテストを待たせる必要がある。