beforeunload イベントはウインドウがアンロードされる直前に発生します。アンロードとはブラウザのダブを閉じたり、リロードしたときなどが含まれます。イベントハンドラーで preventDefault()
を呼び出すことにより、以下のような確認ダイアログを表示できます。ユーザーが「キャンセル」をクリックするとページ遷移をキャンセルし、そうでない場合ンはブラウザは新しいページへ遷移します。
beforeunload
イベントのよくある使い道として、ユーザーがフォームを入力している最中に誤ってブラウザを閉じてしまい、入力内容が消失することを防ぐために使用されます。下記のフォームになにか入力してから更新を試してください。
この例ではフォームが変更された場合(=isDirty
が true
)のみ beforeunload
イベントの preventDefault()
を呼び出してユーザーがページ遷移するのを防ごうとしています。この仕様をテストしたのですが、どのようにユーザーがアンロードしたことをシミュレーションすればよいのでしょうか?
beforeunload
イベントのようにユーザーの挙動をシミュレーターするのが難しいイベントは window.dispatchEvent() を使用するとよいでしょう。 window.dispatchEvent()
Event オブジェクトを引数に受け取り特定のイベントを実行できます。
ここでは new Event("beforeunload")
で beforeunload
イベントを作成して引数に渡すことで呼び出すことができます。
window.dispatchEvent(new Event('beforeunlaod'));
さらに確認ダイアログが表示されるかどうかは preventDefault()
が呼び出されているかどうかで確認できるので、モック関数を仕込んで渡すこで検査できます。
// beforeunloadEvent を作成する
const beforeUnloadEvent = new Event("beforeunload");
beforeUnloadEvent.preventDefault = jest.fn();
// フォームになにか入力して確認ダイアログが表示される条件を満たす
render(<Form initialValues={{ name: "" }} />);
const input = screen.getByLabelText("Name");
userEvent.type(input, "John Doe");
// beforeunload イベントをプログラム的に発行する
window.dispatchEvent(beforeUnloadEvent);
// 確認ダイアログを表示するため preventDefault が呼ばれるはず
expect(beforeUnloadEvent.preventDefault).toHaveBeenCalled();
全体のコードは次のようになります。