Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<meta charset="utf-8">
<title>beforeunload return value cancelation behavior</title>
<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#the-event-handler-processing-algorithm">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
"use strict";
promise_test(t => {
let onbeforeunloadHappened = false;
window.onbeforeunload = t.step_func(() => {
onbeforeunloadHappened = true;
return "cancel me";
});
const eventWatcher = new EventWatcher(t, window, "beforeunload");
const promise = eventWatcher.wait_for("beforeunload").then(e => {
assert_true(onbeforeunloadHappened, "CustomEvent must be able to trigger the event handler");
assert_false(e.defaultPrevented, "The event must not have been canceled");
window.onbeforeunload = null;
});
window.dispatchEvent(new CustomEvent("beforeunload"));
return promise;
}, "Returning a string must not cancel the event: CustomEvent, non-cancelable");
promise_test(t => {
let onbeforeunloadHappened = false;
window.onbeforeunload = t.step_func(() => {
onbeforeunloadHappened = true;
return "cancel me";
});
const eventWatcher = new EventWatcher(t, window, "beforeunload");
const promise = eventWatcher.wait_for("beforeunload").then(e => {
assert_true(onbeforeunloadHappened, "CustomEvent must be able to trigger the event handler");
assert_false(e.defaultPrevented, "The event must not have been canceled");
window.onbeforeunload = null;
t.done();
});
window.dispatchEvent(new CustomEvent("beforeunload", { cancelable: true }));
return promise;
}, "Returning a string must not cancel the event: CustomEvent, cancelable");
promise_test(t => {
let onbeforeunloadHappened = false;
window.onbeforeunload = t.step_func(() => {
onbeforeunloadHappened = true;
return false;
});
const eventWatcher = new EventWatcher(t, window, "beforeunload");
const promise = eventWatcher.wait_for("beforeunload").then(e => {
assert_true(onbeforeunloadHappened, "CustomEvent must be able to trigger the event handler");
assert_false(e.defaultPrevented, "The event must not have been canceled");
window.onbeforeunload = null;
t.done();
});
window.dispatchEvent(new CustomEvent("beforeunload", { cancelable: true }));
return promise;
}, "Returning false must not cancel the event, because it's coerced to the DOMString \"false\" which does not cancel " +
"CustomEvents: CustomEvent, cancelable");
// This test can be removed if we update the DOM Standard to disallow createEvent("BeforeUnloadEvent"). Browser support
promise_test(t => {
const eventWatcher = new EventWatcher(t, window, "click");
const promise = eventWatcher.wait_for("click").then(e => {
assert_false(e.defaultPrevented, "The event must not have been canceled");
window.onbeforeunload = null;
t.done();
});
const ev = document.createEvent("BeforeUnloadEvent");
ev.initEvent("click", false, true);
window.dispatchEvent(ev);
return promise;
}, "Returning a string must not cancel the event: BeforeUnloadEvent with type \"click\", cancelable");
const testCases = [
{
valueToReturn: null,
expectCancelation: false,
expectedReturnValue: ""
},
{
valueToReturn: undefined,
expectCancelation: false,
expectedReturnValue: ""
},
{
valueToReturn: "",
expectCancelation: true,
expectedReturnValue: ""
},
{
valueToReturn: false,
expectCancelation: true,
expectedReturnValue: "false"
},
{
valueToReturn: true,
expectCancelation: true,
expectedReturnValue: "true"
},
{
valueToReturn: 0,
expectCancelation: true,
expectedReturnValue: "0"
},
{
valueToReturn: null,
expectCancelation: false,
setReturnValue: "foo",
expectedReturnValue: "foo"
},
{
valueToReturn: undefined,
expectCancelation: false,
setReturnValue: "foo",
expectedReturnValue: "foo"
},
{
valueToReturn: "",
expectCancelation: true,
setReturnValue: "foo",
expectedReturnValue: "foo"
},
{
valueToReturn: false,
expectCancelation: true,
setReturnValue: "foo",
expectedReturnValue: "foo"
},
{
valueToReturn: true,
expectCancelation: true,
setReturnValue: "foo",
expectedReturnValue: "foo"
},
{
valueToReturn: 0,
expectCancelation: true,
setReturnValue: "foo",
expectedReturnValue: "foo"
},
{
setReturnValue: "",
expectedReturnValue: "",
expectCancelation: false,
},
{
expectCancelation: true,
expectedReturnValue: "",
cancel: true
},
{
setReturnValue: "foo",
expectCancelation: true,
expectedReturnValue: "foo",
cancel: true
},
{
valueToReturn: "foo",
expectedReturnValue: "foo",
expectCancelation: true,
cancel: true
},
{
valueToReturn: "foo",
setReturnValue: "foo",
expectedReturnValue: "foo",
expectCancelation: true,
cancel: true
},
{
valueToReturn: true,
setReturnValue: "",
expectedReturnValue: "true",
expectCancelation: true,
cancel: true
}
];
var testCaseIndex = 0;
function runNextTest() {
const testCase = testCases[testCaseIndex];
const labelAboutReturnValue = testCase.setReturnValue === undefined ? "" :
`; setting returnValue to ${testCase.setReturnValue}`;
const labelAboutCancel = testCase.cancel === undefined ? "" :
"; calling preventDefault()";
const suffixLabels = labelAboutReturnValue + labelAboutCancel;
async_test(t => {
const iframe = document.createElement("iframe");
iframe.onload = t.step_func(() => {
iframe.contentWindow.runTest(t, testCase);
if (++testCaseIndex < testCases.length)
runNextTest();
});
iframe.src = "beforeunload-canceling-1.html";
document.body.appendChild(iframe);
}, `Returning ${testCase.valueToReturn} with a real iframe unloading${suffixLabels}`);
}
runNextTest();
</script>