Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="application/javascript" src="/tests/SimpleTest/SpecialPowers.js"></script>
<script type="application/javascript">
/*
* Perform the following steps.
* 1) Go to file_load_history_entry_page_with_two_links.html, which contains two links, 'link1' and 'link2'
* 2) Click on 'link1' to be taken to file_load_history_entry_page_with_two_links.html#1
* 3) Click on 'link2' to be taken to file_load_history_entry_page_with_two_links.html#2
* 4) Go to file_load_history_entry_page_with_one_link.html
* 5) Push state to go to file_load_history_entry_page_with_one_link.html#1
*
* After each step
* - Check the number of session history entries
* - Reload the document and do the above again
* - Navigate back and check the correct history index
* - Navigate forward and check the correct history index and location
*/
async function test() {
let testWin;
var promise;
var previousLocation;
var numSHEntries = 0;
// Step 1. Open a new tab and load a document with two links inside
// Now we are at file_load_history_entry_page_with_two_links.html
numSHEntries++;
promise = waitForLoad();
testWin = window.open("file_load_history_entry_page_with_two_links.html");
await promise;
let shistory = SpecialPowers.wrap(testWin)
.docShell
.QueryInterface(SpecialPowers.Ci.nsIWebNavigation)
.sessionHistory;
// Step 2. Navigate the document by clicking on the 1st link
// Now we are at file_load_history_entry_page_with_two_links.html#1
numSHEntries++;
previousLocation = testWin.location.href;
await clickLink(testWin, "link1");
await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation);
// Step 3. Navigate the document by clicking the 2nd link
// Now we are file_load_history_entry_page_with_two_links.html#2
numSHEntries++;
previousLocation = testWin.location.href;
await clickLink(testWin, "link2");
await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation);
// Step 4. Navigate the document to a different page
// Now we are at file_load_history_entry_page_with_one_link.html
numSHEntries++;
previousLocation = testWin.location.href;
promise = waitForLoad();
testWin.location = "file_load_history_entry_page_with_one_link.html";
await promise;
await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation,
true /* isCrossDocumentLoad */, false /* hashChangeExpected */);
// Step 5. Push some state
// Now we are at file_load_history_entry_page_with_one_link.html#1
numSHEntries++;
previousLocation = testWin.location.href;
testWin.history.pushState({foo: "bar"}, "", "#1");
is(testWin.history.length, numSHEntries, "Session history's length is correct after pushing state");
is(shistory.index, numSHEntries - 1 /* we haven't switched to new history entry yet*/,
"Session history's index is correct after pushing state");
await doAfterEachTest(testWin, shistory, numSHEntries, previousLocation);
// We are done with the test
testWin.close();
SimpleTest.finish();
}
/*
* @prevLocation
* if undefined, it is because there is no page to go back to
*
* @isCrossDocumentLoad
* did we just open a different document
* @hashChangeExpected
* Would we get a hash change event if we navigated backwards and forwards in history?
* This is framed with respect to the previous step, e.g. in the previous step was the
* hash different from the location we have navigated to just before calling this function?
* When we navigate forwards or backwards, we need to wait for this event
* because clickLink() also waits for hashchange event and
* if this function gets called before clickLink(), sometimes hashchange
* events from this function will leak to clickLink.
*/
async function doAfterEachTest(testWin, shistory, expectedNumSHEntries, prevLocation,
isCrossDocumentLoad = false, hashChangeExpected = true) {
var initialLocation = testWin.location.href;
var initialSHIndex = shistory.index;
var promise;
is(testWin.history.length, expectedNumSHEntries, "Session history's length is correct");
// Reload the document
promise = waitForLoad();
testWin.location.reload(true);
await promise;
is(testWin.history.length, expectedNumSHEntries, "Session history's length is correct after reloading");
if (prevLocation == undefined) {
return;
}
var hashChangePromise;
if (hashChangeExpected) {
hashChangePromise = new Promise(resolve => {
testWin.addEventListener("hashchange", resolve, {once: true});
});
}
// Navigate backwards
if (isCrossDocumentLoad) {
// Current page must have been a cross document load, so we just need to wait for
// document load to complete after we navigate the history back
// because popstate event will not be fired in this case
promise = waitForLoad();
} else {
promise = waitForPopstate(testWin);
}
testWin.history.back();
await promise;
if (hashChangeExpected) {
await hashChangePromise;
}
is(testWin.location.href, prevLocation, "Window location is correct after navigating back in history");
is(shistory.index, initialSHIndex - 1, "Session history's index is correct after navigating back in history");
// Navigate forwards
if (isCrossDocumentLoad) {
promise = waitForLoad();
} else {
promise = waitForPopstate(testWin);
}
if (hashChangeExpected) {
hashChangePromise = new Promise(resolve => {
testWin.addEventListener("hashchange", resolve, {once: true});
});
}
testWin.history.forward();
await promise;
if (hashChangeExpected) {
await hashChangePromise;
}
is(testWin.location.href, initialLocation, "Window location is correct after navigating forward in history");
is(shistory.index, initialSHIndex, "Session history's index is correct after navigating forward in history");
}
async function waitForLoad() {
return new Promise(resolve => {
window.bodyOnLoad = function() {
setTimeout(resolve, 0);
window.bodyOnLoad = undefined;
};
});
}
async function waitForPopstate(win) {
return new Promise(resolve => {
win.addEventListener("popstate", () => {
setTimeout(resolve, 0);
}, {once: true});
});
}
async function clickLink(win, id) {
var link = win.document.getElementById(id);
let clickPromise = new Promise(resolve => {
win.addEventListener("hashchange", resolve, {once: true});
});
link.click();
await clickPromise;
}
</script>
</head>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<body onload="test()">
</body>
</html>