beforeunload-canceling.html (6173B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>beforeunload return value cancelation behavior</title> 4 <link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#the-event-handler-processing-algorithm"> 5 <link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 9 <div id="log"></div> 10 11 <script> 12 "use strict"; 13 14 promise_test(t => { 15 let onbeforeunloadHappened = false; 16 window.onbeforeunload = t.step_func(() => { 17 onbeforeunloadHappened = true; 18 return "cancel me"; 19 }); 20 21 const eventWatcher = new EventWatcher(t, window, "beforeunload"); 22 const promise = eventWatcher.wait_for("beforeunload").then(e => { 23 assert_true(onbeforeunloadHappened, "CustomEvent must be able to trigger the event handler"); 24 assert_false(e.defaultPrevented, "The event must not have been canceled"); 25 window.onbeforeunload = null; 26 }); 27 28 window.dispatchEvent(new CustomEvent("beforeunload")); 29 30 return promise; 31 }, "Returning a string must not cancel the event: CustomEvent, non-cancelable"); 32 33 promise_test(t => { 34 let onbeforeunloadHappened = false; 35 window.onbeforeunload = t.step_func(() => { 36 onbeforeunloadHappened = true; 37 return "cancel me"; 38 }); 39 40 const eventWatcher = new EventWatcher(t, window, "beforeunload"); 41 const promise = eventWatcher.wait_for("beforeunload").then(e => { 42 assert_true(onbeforeunloadHappened, "CustomEvent must be able to trigger the event handler"); 43 assert_false(e.defaultPrevented, "The event must not have been canceled"); 44 window.onbeforeunload = null; 45 t.done(); 46 }); 47 48 window.dispatchEvent(new CustomEvent("beforeunload", { cancelable: true })); 49 50 return promise; 51 }, "Returning a string must not cancel the event: CustomEvent, cancelable"); 52 53 promise_test(t => { 54 let onbeforeunloadHappened = false; 55 window.onbeforeunload = t.step_func(() => { 56 onbeforeunloadHappened = true; 57 return false; 58 }); 59 60 const eventWatcher = new EventWatcher(t, window, "beforeunload"); 61 const promise = eventWatcher.wait_for("beforeunload").then(e => { 62 assert_true(onbeforeunloadHappened, "CustomEvent must be able to trigger the event handler"); 63 assert_false(e.defaultPrevented, "The event must not have been canceled"); 64 window.onbeforeunload = null; 65 t.done(); 66 }); 67 68 window.dispatchEvent(new CustomEvent("beforeunload", { cancelable: true })); 69 70 return promise; 71 }, "Returning false must not cancel the event, because it's coerced to the DOMString \"false\" which does not cancel " + 72 "CustomEvents: CustomEvent, cancelable"); 73 74 // This test can be removed if we update the DOM Standard to disallow createEvent("BeforeUnloadEvent"). Browser support 75 // is inconsistent. https://github.com/whatwg/dom/issues/362 76 promise_test(t => { 77 const eventWatcher = new EventWatcher(t, window, "click"); 78 const promise = eventWatcher.wait_for("click").then(e => { 79 assert_false(e.defaultPrevented, "The event must not have been canceled"); 80 window.onbeforeunload = null; 81 t.done(); 82 }); 83 84 const ev = document.createEvent("BeforeUnloadEvent"); 85 ev.initEvent("click", false, true); 86 window.dispatchEvent(ev); 87 88 return promise; 89 }, "Returning a string must not cancel the event: BeforeUnloadEvent with type \"click\", cancelable"); 90 91 const testCases = [ 92 { 93 valueToReturn: null, 94 expectCancelation: false, 95 expectedReturnValue: "" 96 }, 97 { 98 valueToReturn: undefined, 99 expectCancelation: false, 100 expectedReturnValue: "" 101 }, 102 { 103 valueToReturn: "", 104 expectCancelation: true, 105 expectedReturnValue: "" 106 }, 107 { 108 valueToReturn: false, 109 expectCancelation: true, 110 expectedReturnValue: "false" 111 }, 112 { 113 valueToReturn: true, 114 expectCancelation: true, 115 expectedReturnValue: "true" 116 }, 117 { 118 valueToReturn: 0, 119 expectCancelation: true, 120 expectedReturnValue: "0" 121 }, 122 { 123 valueToReturn: null, 124 expectCancelation: false, 125 setReturnValue: "foo", 126 expectedReturnValue: "foo" 127 }, 128 { 129 valueToReturn: undefined, 130 expectCancelation: false, 131 setReturnValue: "foo", 132 expectedReturnValue: "foo" 133 }, 134 { 135 valueToReturn: "", 136 expectCancelation: true, 137 setReturnValue: "foo", 138 expectedReturnValue: "foo" 139 }, 140 { 141 valueToReturn: false, 142 expectCancelation: true, 143 setReturnValue: "foo", 144 expectedReturnValue: "foo" 145 }, 146 { 147 valueToReturn: true, 148 expectCancelation: true, 149 setReturnValue: "foo", 150 expectedReturnValue: "foo" 151 }, 152 { 153 valueToReturn: 0, 154 expectCancelation: true, 155 setReturnValue: "foo", 156 expectedReturnValue: "foo" 157 }, 158 { 159 setReturnValue: "", 160 expectedReturnValue: "", 161 expectCancelation: false, 162 }, 163 { 164 expectCancelation: true, 165 expectedReturnValue: "", 166 cancel: true 167 }, 168 { 169 setReturnValue: "foo", 170 expectCancelation: true, 171 expectedReturnValue: "foo", 172 cancel: true 173 }, 174 { 175 valueToReturn: "foo", 176 expectedReturnValue: "foo", 177 expectCancelation: true, 178 cancel: true 179 }, 180 { 181 valueToReturn: "foo", 182 setReturnValue: "foo", 183 expectedReturnValue: "foo", 184 expectCancelation: true, 185 cancel: true 186 }, 187 { 188 valueToReturn: true, 189 setReturnValue: "", 190 expectedReturnValue: "true", 191 expectCancelation: true, 192 cancel: true 193 } 194 ]; 195 196 var testCaseIndex = 0; 197 function runNextTest() { 198 const testCase = testCases[testCaseIndex]; 199 200 const labelAboutReturnValue = testCase.setReturnValue === undefined ? "" : 201 `; setting returnValue to ${testCase.setReturnValue}`; 202 203 const labelAboutCancel = testCase.cancel === undefined ? "" : 204 "; calling preventDefault()"; 205 206 const suffixLabels = labelAboutReturnValue + labelAboutCancel; 207 208 async_test(t => { 209 const iframe = document.createElement("iframe"); 210 iframe.onload = t.step_func(() => { 211 iframe.contentWindow.runTest(t, testCase); 212 if (++testCaseIndex < testCases.length) 213 runNextTest(); 214 }); 215 216 iframe.src = "beforeunload-canceling-1.html"; 217 document.body.appendChild(iframe); 218 }, `Returning ${testCase.valueToReturn} with a real iframe unloading${suffixLabels}`); 219 } 220 221 runNextTest(); 222 </script>