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