<!DOCTYPE HTML> <html> <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=385434 --> <head> <title>Test for Bug 385434</title> <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=385434">Mozilla Bug 385434</a> <p id="display"></p> <div id="content"> <iframe id="frame" style="height:100px; width:100px; border:0"></iframe> <div id="status" style="display: none"></div> </div> <pre id="test"> <script type="application/javascript;version=1.7"> /** Test for Bug 385434 **/ SimpleTest.waitForExplicitFinish(); SimpleTest.requestFlakyTimeout("untriaged"); var gNumHashchanges = 0; var gCallbackOnIframeLoad = false; function statusMsg(msg) { var msgElem = document.createElement("p"); msgElem.appendChild(document.createTextNode(msg)); document.getElementById("status").appendChild(msgElem); } function longWait() { setTimeout(function() { gGen.next() }, 1000); } // onIframeHashchange, onIframeLoad, and onIframeScroll are all called by the // content we load into our iframe in order to notify the parent frame of an // event which was fired. function onIframeHashchange() { gNumHashchanges++; gGen.next(); } function onIframeLoad() { if (gCallbackOnIframeLoad) { gCallbackOnIframeLoad = false; gGen.next(); } } function onIframeScroll() { is(gNumHashchanges, 0, "onscroll should fire before onhashchange."); } function enableIframeLoadCallback() { gCallbackOnIframeLoad = true; } function noEventExpected(msg) { is(gNumHashchanges, 0, msg); // Even if there's an error, set gNumHashchanges to 0 so other tests don't // fail. gNumHashchanges = 0; } function eventExpected(msg) { is(gNumHashchanges, 1, msg); // Eat up this event, whether the test above was true or not gNumHashchanges = 0; } /* * The hashchange event is dispatched asynchronously, so if we want to observe * it, we have to yield within run_test(), transferring control back to the * event loop. * * When we're expecting our iframe to observe a hashchange event after we poke * it, we just yield and wait for onIframeHashchange() to call gGen.next() and * wake us up. * * When we're testing to ensure that the iframe doesn't dispatch a hashchange * event, we try to hook onto the iframe's load event. We call * enableIframeLoadCallback(), which causes onIframeLoad() to call gGen.next() * upon the next observed load. After we get our callback, we check that a * hashchange didn't occur. * * We can't always just wait for page load in order to observe that a * hashchange didn't happen. In these cases, we call longWait() and yield * until either a hashchange occurs or longWait's callback is scheduled. This * is something of a hack; it's entirely possible that longWait won't wait long * enough, and we won't observe what should have been a failure of the test. * But it shouldn't happen that good code will randomly *fail* this test. */ function run_test() { /* * TEST 1 tests that: * <body onhashchange = ... > works, * the event is (not) fired at the correct times */ var frame = document.getElementById("frame"); var frameCw = frame.contentWindow; enableIframeLoadCallback(); frameCw.document.location = "file_bug385434_1.html"; // Wait for the iframe to load and for our callback to fire yield undefined; noEventExpected("No hashchange expected initially."); sendMouseEvent({type: "click"}, "link1", frameCw); yield undefined; eventExpected("Clicking link1 should trigger a hashchange."); sendMouseEvent({type: "click"}, "link1", frameCw); longWait(); yield undefined; // succeed if a hashchange event wasn't triggered while we were waiting noEventExpected("Clicking link1 again should not trigger a hashchange."); sendMouseEvent({type: "click"}, "link2", frameCw); yield undefined; eventExpected("Clicking link2 should trigger a hashchange."); frameCw.history.go(-1); yield undefined; eventExpected("Going back should trigger a hashchange."); frameCw.history.go(1); yield undefined; eventExpected("Going forward should trigger a hashchange."); // window.location has a trailing '#' right now, so we append "link1", not // "#link1". frameCw.window.location = frameCw.window.location + "link1"; yield undefined; eventExpected("Assigning to window.location should trigger a hashchange."); // Set up history in the iframe which looks like: // file_bug385434_1.html#link1 // file_bug385434_2.html // file_bug385434_1.html#foo <-- current page enableIframeLoadCallback(); frameCw.window.location = "file_bug385434_2.html"; yield undefined; enableIframeLoadCallback(); frameCw.window.location = "file_bug385434_1.html#foo"; yield undefined; // Now when we do history.go(-2) on the frame, it *shouldn't* fire a // hashchange. Although the URIs differ only by their hashes, they belong to // two different Documents. frameCw.history.go(-2); longWait(); yield undefined; noEventExpected("Moving between different Documents shouldn't " + "trigger a hashchange."); /* * TEST 2 tests that: * <frameset onhashchange = ... > works, * the event is targeted at the window object * the event's cancelable, bubbles settings are correct */ enableIframeLoadCallback(); frameCw.document.location = "file_bug385434_2.html"; yield undefined; frameCw.document.location = "file_bug385434_2.html#foo"; yield undefined; eventExpected("frame onhashchange should fire events."); // iframe should set gSampleEvent is(gSampleEvent.target, frameCw, "The hashchange event should be targeted to the window."); is(gSampleEvent.type, "hashchange", "Event type should be 'hashchange'."); is(gSampleEvent.cancelable, false, "The hashchange event shouldn't be cancelable."); is(gSampleEvent.bubbles, true, "The hashchange event should bubble."); /* * TEST 3 tests that: * hashchange is dispatched if the current document readyState is * not "complete" (bug 504837). */ frameCw.document.location = "file_bug385434_3.html"; yield undefined; eventExpected("Hashchange should fire even if the document " + "hasn't finished loading."); SimpleTest.finish(); yield undefined; } var gGen = run_test(); gGen.next(); </script> </pre> </body> </html>