test_load_history_entry.html (8136B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 5 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 6 <script type="application/javascript" src="/tests/SimpleTest/SpecialPowers.js"></script> 7 <script type="application/javascript"> 8 /* 9 * Perform the following steps. 10 * 1) Go to file_load_history_entry_page_with_two_links.html, which contains two links, 'link1' and 'link2' 11 * 2) Click on 'link1' to be taken to file_load_history_entry_page_with_two_links.html#1 12 * 3) Click on 'link2' to be taken to file_load_history_entry_page_with_two_links.html#2 13 * 4) Go to file_load_history_entry_page_with_one_link.html 14 * 5) Push state to go to file_load_history_entry_page_with_one_link.html#1 15 * 16 * After each step 17 * - Check the number of session history entries 18 * - Reload the document and do the above again 19 * - Navigate back and check the correct history index 20 * - Navigate forward and check the correct history index and location 21 */ 22 async function test() { 23 let testWin; 24 var promise; 25 var previousLocation; 26 var numSHEntries = 0; 27 28 // Step 1. Open a new tab and load a document with two links inside 29 // Now we are at file_load_history_entry_page_with_two_links.html 30 numSHEntries++; 31 promise = waitForLoad(); 32 testWin = window.open("file_load_history_entry_page_with_two_links.html"); 33 await promise; 34 35 let shistory = SpecialPowers.wrap(testWin) 36 .docShell 37 .QueryInterface(SpecialPowers.Ci.nsIWebNavigation) 38 .sessionHistory; 39 40 // Step 2. Navigate the document by clicking on the 1st link 41 // Now we are at file_load_history_entry_page_with_two_links.html#1 42 numSHEntries++; 43 previousLocation = testWin.location.href; 44 await clickLink(testWin, "link1"); 45 await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation); 46 47 // Step 3. Navigate the document by clicking the 2nd link 48 // Now we are file_load_history_entry_page_with_two_links.html#2 49 numSHEntries++; 50 previousLocation = testWin.location.href; 51 await clickLink(testWin, "link2"); 52 await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation); 53 54 // Step 4. Navigate the document to a different page 55 // Now we are at file_load_history_entry_page_with_one_link.html 56 numSHEntries++; 57 previousLocation = testWin.location.href; 58 promise = waitForLoad(); 59 testWin.location = "file_load_history_entry_page_with_one_link.html"; 60 await promise; 61 await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation, 62 true /* isCrossDocumentLoad */, false /* hashChangeExpected */); 63 64 // Step 5. Push some state 65 // Now we are at file_load_history_entry_page_with_one_link.html#1 66 numSHEntries++; 67 previousLocation = testWin.location.href; 68 testWin.history.pushState({foo: "bar"}, "", "#1"); 69 is(testWin.history.length, numSHEntries, "Session history's length is correct after pushing state"); 70 is(shistory.index, numSHEntries - 1 /* we haven't switched to new history entry yet*/, 71 "Session history's index is correct after pushing state"); 72 await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation); 73 74 // We are done with the test 75 testWin.close(); 76 SimpleTest.finish(); 77 } 78 79 /** 80 * @param {Window} testWin 81 * @param {object} shistory 82 * @param {number} expectedNumSHEntries 83 * @param {?string} prevLocation 84 * If undefined, it is because there is no page to go back to. 85 * @param {boolean} [isCrossDocumentLoad] 86 * Did we just open a different document? 87 * @param {boolean} [hashChangeExpected] 88 * Would we get a hash change event if we navigated backwards and forwards in history? 89 * This is framed with respect to the previous step, e.g. in the previous step was the 90 * hash different from the location we have navigated to just before calling this function? 91 * When we navigate forwards or backwards, we need to wait for this event 92 * because clickLink() also waits for hashchange event and 93 * if this function gets called before clickLink(), sometimes hashchange 94 * events from this function will leak to clickLink. 95 */ 96 async function doAfterEachTest(testWin, shistory, expectedNumSHEntries, prevLocation, 97 isCrossDocumentLoad = false, hashChangeExpected = true) { 98 var initialLocation = testWin.location.href; 99 var initialSHIndex = shistory.index; 100 var promise; 101 is(testWin.history.length, expectedNumSHEntries, "Session history's length is correct"); 102 103 // Reload the document 104 promise = waitForLoad(); 105 testWin.location.reload(true); 106 await promise; 107 is(testWin.history.length, expectedNumSHEntries, "Session history's length is correct after reloading"); 108 109 if (prevLocation == undefined) { 110 return; 111 } 112 113 var hashChangePromise; 114 if (hashChangeExpected) { 115 hashChangePromise = new Promise(resolve => { 116 testWin.addEventListener("hashchange", resolve, {once: true}); 117 }); 118 } 119 // Navigate backwards 120 if (isCrossDocumentLoad) { 121 // Current page must have been a cross document load, so we just need to wait for 122 // document load to complete after we navigate the history back 123 // because popstate event will not be fired in this case 124 promise = waitForLoad(); 125 } else { 126 promise = waitForPopstate(testWin); 127 } 128 testWin.history.back(); 129 await promise; 130 if (hashChangeExpected) { 131 await hashChangePromise; 132 } 133 is(testWin.location.href, prevLocation, "Window location is correct after navigating back in history"); 134 is(shistory.index, initialSHIndex - 1, "Session history's index is correct after navigating back in history"); 135 136 // Navigate forwards 137 if (isCrossDocumentLoad) { 138 promise = waitForLoad(); 139 } else { 140 promise = waitForPopstate(testWin); 141 } 142 if (hashChangeExpected) { 143 hashChangePromise = new Promise(resolve => { 144 testWin.addEventListener("hashchange", resolve, {once: true}); 145 }); 146 } 147 testWin.history.forward(); 148 await promise; 149 if (hashChangeExpected) { 150 await hashChangePromise; 151 } 152 is(testWin.location.href, initialLocation, "Window location is correct after navigating forward in history"); 153 is(shistory.index, initialSHIndex, "Session history's index is correct after navigating forward in history"); 154 } 155 156 async function waitForLoad() { 157 return new Promise(resolve => { 158 window.bodyOnLoad = function() { 159 setTimeout(resolve, 0); 160 window.bodyOnLoad = undefined; 161 }; 162 }); 163 } 164 165 async function waitForPopstate(win) { 166 return new Promise(resolve => { 167 win.addEventListener("popstate", () => { 168 setTimeout(resolve, 0); 169 }, {once: true}); 170 }); 171 } 172 173 async function clickLink(win, id) { 174 var link = win.document.getElementById(id); 175 let clickPromise = new Promise(resolve => { 176 win.addEventListener("hashchange", resolve, {once: true}); 177 }); 178 link.click(); 179 await clickPromise; 180 } 181 182 </script> 183 </head> 184 185 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1539482">Bug 1539482</a> 186 <p id="display"></p> 187 <div id="content" style="display: none"> 188 </div> 189 <pre id="test"> 190 <script type="text/javascript"> 191 SimpleTest.waitForExplicitFinish(); 192 </script> 193 </pre> 194 <body onload="test()"> 195 </body> 196 </html>