test_bug385434.html (6608B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=385434 5 --> 6 <head> 7 <title>Test for Bug 385434</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <script src="/tests/SimpleTest/EventUtils.js"></script> 10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 11 </head> 12 <body> 13 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=385434">Mozilla Bug 385434</a> 14 <p id="display"></p> 15 <div id="content"> 16 <iframe id="frame" style="height:100px; width:100px; border:0"></iframe> 17 <div id="status" style="display: none"></div> 18 </div> 19 <pre id="test"> 20 <script type="application/javascript"> 21 22 /** Test for Bug 385434 */ 23 SimpleTest.waitForExplicitFinish(); 24 SimpleTest.requestFlakyTimeout("untriaged"); 25 SimpleTest.expectAssertions(0, 1); // bug 1333702 26 27 var gNumHashchanges = 0; 28 var gCallbackOnIframeLoad = false; 29 var gSampleEvent; 30 31 function statusMsg(msg) { 32 var msgElem = document.createElement("p"); 33 msgElem.appendChild(document.createTextNode(msg)); 34 35 document.getElementById("status").appendChild(msgElem); 36 } 37 38 function longWait() { 39 setTimeout(function() { gGen.next(); }, 1000); 40 } 41 42 // onIframeHashchange, onIframeLoad, and onIframeScroll are all called by the 43 // content we load into our iframe in order to notify the parent frame of an 44 // event which was fired. 45 function onIframeHashchange() { 46 gNumHashchanges++; 47 gGen.next(); 48 } 49 50 function onIframeLoad() { 51 if (gCallbackOnIframeLoad) { 52 gCallbackOnIframeLoad = false; 53 gGen.next(); 54 } 55 } 56 57 function onIframeScroll() { 58 is(gNumHashchanges, 0, "onscroll should fire before onhashchange."); 59 } 60 61 function enableIframeLoadCallback() { 62 gCallbackOnIframeLoad = true; 63 } 64 65 function noEventExpected(msg) { 66 is(gNumHashchanges, 0, msg); 67 68 // Even if there's an error, set gNumHashchanges to 0 so other tests don't 69 // fail. 70 gNumHashchanges = 0; 71 } 72 73 function eventExpected(msg) { 74 is(gNumHashchanges, 1, msg); 75 76 // Eat up this event, whether the test above was true or not 77 gNumHashchanges = 0; 78 } 79 80 /* 81 * The hashchange event is dispatched asynchronously, so if we want to observe 82 * it, we have to yield within run_test(), transferring control back to the 83 * event loop. 84 * 85 * When we're expecting our iframe to observe a hashchange event after we poke 86 * it, we just yield and wait for onIframeHashchange() to call gGen.next() and 87 * wake us up. 88 * 89 * When we're testing to ensure that the iframe doesn't dispatch a hashchange 90 * event, we try to hook onto the iframe's load event. We call 91 * enableIframeLoadCallback(), which causes onIframeLoad() to call gGen.next() 92 * upon the next observed load. After we get our callback, we check that a 93 * hashchange didn't occur. 94 * 95 * We can't always just wait for page load in order to observe that a 96 * hashchange didn't happen. In these cases, we call longWait() and yield 97 * until either a hashchange occurs or longWait's callback is scheduled. This 98 * is something of a hack; it's entirely possible that longWait won't wait long 99 * enough, and we won't observe what should have been a failure of the test. 100 * But it shouldn't happen that good code will randomly *fail* this test. 101 */ 102 function* run_test() { 103 /* 104 * TEST 1 tests that: 105 * <body onhashchange = ... > works, 106 * the event is (not) fired at the correct times 107 */ 108 var frame = document.getElementById("frame"); 109 var frameCw = frame.contentWindow; 110 111 enableIframeLoadCallback(); 112 frameCw.document.location = "file_bug385434_1.html"; 113 // Wait for the iframe to load and for our callback to fire 114 yield undefined; 115 116 noEventExpected("No hashchange expected initially."); 117 118 sendMouseEvent({type: "click"}, "link1", frameCw); 119 yield undefined; 120 eventExpected("Clicking link1 should trigger a hashchange."); 121 122 sendMouseEvent({type: "click"}, "link1", frameCw); 123 longWait(); 124 yield undefined; 125 // succeed if a hashchange event wasn't triggered while we were waiting 126 noEventExpected("Clicking link1 again should not trigger a hashchange."); 127 128 sendMouseEvent({type: "click"}, "link2", frameCw); 129 yield undefined; 130 eventExpected("Clicking link2 should trigger a hashchange."); 131 132 frameCw.history.go(-1); 133 yield undefined; 134 eventExpected("Going back should trigger a hashchange."); 135 136 frameCw.history.go(1); 137 yield undefined; 138 eventExpected("Going forward should trigger a hashchange."); 139 140 // window.location has a trailing '#' right now, so we append "link1", not 141 // "#link1". 142 frameCw.window.location = frameCw.window.location + "link1"; 143 yield undefined; 144 eventExpected("Assigning to window.location should trigger a hashchange."); 145 146 // Set up history in the iframe which looks like: 147 // file_bug385434_1.html#link1 148 // file_bug385434_2.html 149 // file_bug385434_1.html#foo <-- current page 150 enableIframeLoadCallback(); 151 frameCw.window.location = "file_bug385434_2.html"; 152 yield undefined; 153 154 enableIframeLoadCallback(); 155 frameCw.window.location = "file_bug385434_1.html#foo"; 156 yield undefined; 157 158 // Now when we do history.go(-2) on the frame, it *shouldn't* fire a 159 // hashchange. Although the URIs differ only by their hashes, they belong to 160 // two different Documents. 161 frameCw.history.go(-2); 162 longWait(); 163 yield undefined; 164 noEventExpected("Moving between different Documents shouldn't " + 165 "trigger a hashchange."); 166 167 /* 168 * TEST 2 tests that: 169 * <frameset onhashchange = ... > works, 170 * the event is targeted at the window object 171 * the event's cancelable, bubbles settings are correct 172 */ 173 174 enableIframeLoadCallback(); 175 frameCw.document.location = "file_bug385434_2.html"; 176 yield undefined; 177 178 frameCw.document.location = "file_bug385434_2.html#foo"; 179 yield undefined; 180 181 eventExpected("frame onhashchange should fire events."); 182 // iframe should set gSampleEvent 183 is(gSampleEvent.target, frameCw, 184 "The hashchange event should be targeted to the window."); 185 is(gSampleEvent.type, "hashchange", 186 "Event type should be 'hashchange'."); 187 is(gSampleEvent.cancelable, false, 188 "The hashchange event shouldn't be cancelable."); 189 is(gSampleEvent.bubbles, false, 190 "The hashchange event should not bubble."); 191 192 /* 193 * TEST 3 tests that: 194 * hashchange is dispatched if the current document readyState is 195 * not "complete" (bug 504837). 196 */ 197 frameCw.document.location = "file_bug385434_3.html"; 198 yield undefined; 199 eventExpected("Hashchange should fire even if the document " + 200 "hasn't finished loading."); 201 202 SimpleTest.finish(); 203 } 204 205 var gGen = run_test(); 206 gGen.next(); 207 208 </script> 209 </pre> 210 </body> 211 </html>