はじめに
Reactでformタグを使用しているときenterを押すとでformが送信されページがリロードしてしまうのを
防ぎたくてformのonSubmitでe.preventDefault()を実行することでデフォルト動作をキャンセルさせましたが
テストの書き方にだいぶ苦労したのでまとめておきます。
テストはtesting/Libraryとjestを使って記述しています。
実装
export function TaskAddInput() {
const handleSubmit = (e:FormEvent<HTMLFormElement>) => {
e.preventDefault()
};
return (
<div>
<form onSubmit={handleSubmit} data-testid="form1">
<input type="text" placeholder="add a text"/>
</form>
</div>
);
}
上記の実装に対して
formにsubmitイベントを発火させた際
preventDefaultが正しく実行されていることを確認するテストを書きます。
テスト
it('submitイベント発火時preventDefaultが実行されていること', () => {
const formEvent = new Event('submit', { bubbles: true })// ①
Object.assign(formEvent,{preventDefault:jest.fn()})// ②
render(<TaskAddInput/>)
const form = screen.getByTestId("form1")
fireEvent(form ,formEvent )// ③
expect(formEvent.preventDefault).toHaveBeenCalledTimes(1)// ④
})
順番に解説していきます。
①submitのイベントオブジェクトを作成します。オプションで { bubbles: true }を指定してイベントを親要素に伝搬します。
②Object.assignでオブジェクトのマージを行います。①で作成したformEventに
preventDefaultをキーにjest.fn()をvalueに持つオブジェクトをマージさせます。
これでpreventDefaultはjest.fn()に置き換えられました。
③fireEventを使ってformにformEventを渡してsubmitイベントを発火させます。
④preventDefaultが1回呼び出されたことを確認しています。
まとめ
このテストがなかなか書けずにかなりの時間を浪費したので
同じような方の役に立てば幸いです。
間違い等ありましたらご指摘お願いします。