diff options
Diffstat (limited to 'testing/web-platform/tests/navigation-api/navigation-methods/return-value')
74 files changed, 1843 insertions, 0 deletions
diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-204-205-download.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-204-205-download.html new file mode 100644 index 0000000000..5bedbf21e8 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-204-205-download.html @@ -0,0 +1,52 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> +<script src="/common/utils.js"></script> + +<body> +<script> +const tests = [ + ["204s", "204"], + ["205s", "205"], + ["Content-Disposition: attachment responses", "download"] +]; + +for (const [description, action] of tests) { + promise_test(async t => { + const id = token(); + + const i = document.createElement("iframe"); + i.src = `resources/204-205-download-on-second-visit.py?id=${id}`; + document.body.append(i); + await new Promise(r => i.onload = r); + + // Configure it to return a 204 on the next visit + await fetch(i.src + `&action=${action}`, { method: "POST" }); + + // Now navigate elsewhere + i.contentWindow.location.href = "/common/blank.html"; + await new Promise(r => i.onload = r); + + // Now try going back. It should do nothing (and not tell us about the result). + + const indexBefore = i.contentWindow.navigation.currentEntry.index; + + // One might be surprised that navigate does not fire. (It does fire for the + // corresponding tests of navigation.navigate(), i.e., this is + // traversal-specific behavior.) See https://github.com/WICG/navigation-api/issues/207 + // for some discussion. + i.contentWindow.navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + const result = i.contentWindow.navigation.back(); + + assertNeverSettles(t, result, i.contentWindow); + + await new Promise(resolve => t.step_timeout(resolve, 50)); + assert_equals(i.contentWindow.navigation.currentEntry.index, indexBefore); + assert_equals(i.contentWindow.navigation.transition, null); + }, `back() promises to ${description} never settle`); +} +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-already-detached.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-already-detached.html new file mode 100644 index 0000000000..f9ff04f923 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-already-detached.html @@ -0,0 +1,30 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + i.contentWindow.navigation.navigate("?1"); + await new Promise(resolve => i.onload = resolve); + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[1]); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + i.remove(); + + await assertBothRejectDOM(t, iWindow.navigation.back(), "InvalidStateError", iWindow, iDOMException); +}, "back() in a detached window"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-beforeunload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-beforeunload.html new file mode 100644 index 0000000000..82c1f589cc --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-beforeunload.html @@ -0,0 +1,42 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + i.contentWindow.navigation.navigate("?1"); + await new Promise(resolve => i.onload = resolve); + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[1]); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.back(), "InvalidStateError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, "back() inside onbeforeunload"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-initial-about-blank.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-initial-about-blank.html new file mode 100644 index 0000000000..dfdb6611ab --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-initial-about-blank.html @@ -0,0 +1,25 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<body> +<script> +promise_test(async t => { + let i = document.createElement("iframe"); + document.body.append(i); + + i.contentWindow.navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + // Since there's no way to do a non-replacement navigation on the initial + // about:blank, there's no way to actually get in a situation where we're on + // about:blank but there's something else backward/forward in the history + // list. So this test will almost certainly pass just because there's nothing + // to go back/forward to. Oh well; it's still reasonable coverage. + + await assertBothRejectDOM(t, i.contentWindow.navigation.back(), "InvalidStateError", i.contentWindow); + await assertBothRejectDOM(t, i.contentWindow.navigation.forward(), "InvalidStateError", i.contentWindow); +}, "back() and forward() in initial about:blank document"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-opaque-origin.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-opaque-origin.html new file mode 100644 index 0000000000..59849e961d --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-opaque-origin.html @@ -0,0 +1,9 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe id="i" sandbox="allow-scripts" src="resources/back-forward-opaque-origin-page.html"></iframe> + +<script> +fetch_tests_from_window(i.contentWindow); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-out-of-bounds.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-out-of-bounds.html new file mode 100644 index 0000000000..015c090bf9 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-forward-out-of-bounds.html @@ -0,0 +1,16 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + assert_equals(navigation.entries().length, 1); + assert_equals(navigation.entries()[0], navigation.currentEntry); + assert_false(navigation.canGoBack); + assert_false(navigation.canGoForward); + + await assertBothRejectDOM(t, navigation.back(), "InvalidStateError"); + await assertBothRejectDOM(t, navigation.forward(), "InvalidStateError"); +}, "back() and forward() out of bounds"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-intercept-rejected.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-intercept-rejected.html new file mode 100644 index 0000000000..9d4238087f --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-intercept-rejected.html @@ -0,0 +1,28 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + location.href = "#1"; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + const err = new Error("boo!"); + const promise = Promise.reject(err); + promise.catch(() => {}); // prevent unhandled rejection testharness.js errors + navigation.onnavigate = e => e.intercept({ handler: () => promise }); + + const result = navigation.back(); + await assertCommittedFulfillsFinishedRejectsExactly(t, result, entry0, err); + assert_equals(navigation.currentEntry, entry0); +}, "back() promise rejection with rejected intercept()"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-intercept.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-intercept.html new file mode 100644 index 0000000000..2654045c2b --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back-intercept.html @@ -0,0 +1,25 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + location.href = "#1"; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + navigation.onnavigate = e => e.intercept({ handler: () => Promise.resolve({ abc: "def" }) }); + + const result = navigation.back(); + await assertBothFulfill(t, result, entry0); + assert_equals(navigation.currentEntry, entry0); +}, "back() and intercept() with a fulfilled promise"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back.html new file mode 100644 index 0000000000..a2b13db901 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/back.html @@ -0,0 +1,23 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + location.href = "#1"; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + const result = navigation.back(); + await assertBothFulfill(t, result, entry0); + assert_equals(navigation.currentEntry, entry0); +}, "back() promises"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-already-detached.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-already-detached.html new file mode 100644 index 0000000000..4dfa74d9f9 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-already-detached.html @@ -0,0 +1,33 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + i.contentWindow.navigation.navigate("?1"); + await new Promise(resolve => i.onload = resolve); + + i.contentWindow.navigation.back(); + await new Promise(resolve => i.onload = resolve); + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[0]); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + i.remove(); + + await assertBothRejectDOM(t, iWindow.navigation.forward(), "InvalidStateError", iWindow, iDOMException); +}, "forward() in a detached window"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-beforeunload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-beforeunload.html new file mode 100644 index 0000000000..87fa4baa93 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-beforeunload.html @@ -0,0 +1,45 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + i.contentWindow.navigation.navigate("?1"); + await new Promise(resolve => i.onload = resolve); + + i.contentWindow.navigation.back(); + await new Promise(resolve => i.onload = resolve); + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[0]); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.forward(), "InvalidStateError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, "forward() inside onbeforeunload"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-intercept-rejected.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-intercept-rejected.html new file mode 100644 index 0000000000..9e86dcca19 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-intercept-rejected.html @@ -0,0 +1,29 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + location.href = "#1"; + await navigation.back().committed; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + const err = new Error("boo!"); + const promise = Promise.reject(err); + promise.catch(() => {}); // prevent unhandled rejection testharness.js errors + navigation.onnavigate = e => e.intercept({ handler: () => promise }); + + const result = navigation.forward(); + await assertCommittedFulfillsFinishedRejectsExactly(t, result, entry1, err); + assert_equals(navigation.currentEntry, entry1); +}, "forward() promise rejection with rejected intercept()"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-intercept.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-intercept.html new file mode 100644 index 0000000000..ce4ab32170 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward-intercept.html @@ -0,0 +1,28 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + location.href = "#1"; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + await navigation.back().committed; + + const promise = Promise.resolve({ abc: "def" }); + navigation.onnavigate = e => e.intercept({ handler: () => promise }); + + const result = navigation.forward(); + await assertBothFulfill(t, result, entry1); + assert_equals(navigation.currentEntry, entry1); +}, "forward() and intercept() with a fulfilled promise"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward.html new file mode 100644 index 0000000000..36bdba8daa --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/forward.html @@ -0,0 +1,24 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + location.href = "#1"; + await navigation.back().committed; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + const result = navigation.forward(); + await assertBothFulfill(t, result, entry1); + assert_equals(navigation.currentEntry, entry1); +}, "forward() promises"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-204-205-download.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-204-205-download.html new file mode 100644 index 0000000000..f1e89b6940 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-204-205-download.html @@ -0,0 +1,42 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<body> +<script> +const tests = [ + ["204s", "/common/blank.html?pipe=status(204)"], + ["205s", "/common/blank.html?pipe=status(205)"], + ["Content-Disposition: attachment responses", "/common/blank.html?pipe=header(Content-Disposition,attachment)"] +]; + +for (const [description, url] of tests) { + promise_test(async t => { + const i = document.createElement("iframe"); + i.src = "/common/blank.html"; + document.body.append(i); + await new Promise(resolve => i.onload = resolve); + + // This seems to be important? Without it the (outer) window load event + // doesn't fire, and the test harness hangs forever. This is probably a + // Chromium bug, but maybe a testharness bug, especially since explicit_done + // doesn't seem to help? + t.add_cleanup(() => i.remove()); + + let navigateCount = 0; + i.contentWindow.navigation.onnavigate = () => { ++navigateCount; }; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + const result = i.contentWindow.navigation.navigate(url); + + assert_equals(navigateCount, 1); + assertNeverSettles(t, result, i.contentWindow); + + await new Promise(resolve => t.step_timeout(resolve, 50)); + assert_equals(i.contentWindow.location.href, i.src); + assert_equals(i.contentWindow.navigation.transition, null); + }, `navigate() promises to ${description} never settle`); +} +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-already-detached.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-already-detached.html new file mode 100644 index 0000000000..33cdd6922d --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-already-detached.html @@ -0,0 +1,19 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + i.remove(); + + await assertBothRejectDOM(t, iWindow.navigation.navigate("?1"), "InvalidStateError", iWindow, iDOMException); +}, "navigate() in a detached window"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-beforeunload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-beforeunload.html new file mode 100644 index 0000000000..f0a9069677 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-beforeunload.html @@ -0,0 +1,31 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.navigate("#"), "InvalidStateError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, "navigate() inside onbeforeunload"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-cross-document.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-cross-document.html new file mode 100644 index 0000000000..b83b1e941f --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-cross-document.html @@ -0,0 +1,16 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const result = i.contentWindow.navigation.navigate("?1"); + assertNeverSettles(t, result, i.contentWindow); + + await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0)); +}, "cross-document navigate() promises never settle"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-detach-in-onnavigate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-detach-in-onnavigate.html new file mode 100644 index 0000000000..0e80e1b130 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-detach-in-onnavigate.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + i.contentWindow.navigation.onnavigate = () => i.remove(); + + await assertBothRejectDOM(t, i.contentWindow.navigation.navigate("#1"), "AbortError", iWindow, iDOMException); +}, "navigate() promise rejections when detaching an iframe inside onnavigate"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-detach-in-serialization.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-detach-in-serialization.html new file mode 100644 index 0000000000..14086c9f01 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-detach-in-serialization.html @@ -0,0 +1,24 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + const trappedState = { + get prop() { + i.remove(); + return "whatever"; + } + }; + + await assertBothRejectDOM(t, i.contentWindow.navigation.navigate("#1", { state: trappedState }), "InvalidStateError", iWindow, iDOMException); +}, "navigate() promise rejections when detaching an iframe inside state serialization"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-file-url.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-file-url.html new file mode 100644 index 0000000000..138f6ffc12 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-file-url.html @@ -0,0 +1,10 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + await assertBothRejectDOM(t, navigation.navigate("file://"), "AbortError"); +}, "navigate() to a file: URL"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-initial-about-blank-cross-document.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-initial-about-blank-cross-document.html new file mode 100644 index 0000000000..8ec76b11dd --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-initial-about-blank-cross-document.html @@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<body> +<script> +promise_test(async t => { + let i = document.createElement("iframe"); + document.body.append(i); + + i.contentWindow.navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + // Cannot just use "/common/blank.html?1" since it doesn't resolve relative to about:blank. + const result = i.contentWindow.navigation.navigate(new URL("/common/blank.html?1", location.href).href); + assertNeverSettles(t, result, i.contentWindow); + await new Promise(resolve => t.step_timeout(resolve, 10)); +}, "navigate() in initial about:blank document (cross-document)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-initial-about-blank.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-initial-about-blank.html new file mode 100644 index 0000000000..9734a09d01 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-initial-about-blank.html @@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<body> +<script> +promise_test(async t => { + let i = document.createElement("iframe"); + document.body.append(i); + + i.contentWindow.navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + const result = i.contentWindow.navigation.navigate("#1"); + assertNeverSettles(t, result, i.contentWindow); + await new Promise(resolve => t.step_timeout(resolve, 10)); +}, "navigate() in initial about:blank document"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept-interrupted.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept-interrupted.html new file mode 100644 index 0000000000..36403c892c --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept-interrupted.html @@ -0,0 +1,23 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + navigation.addEventListener("navigate", e => e.intercept()); + + const result1 = navigation.navigate("#1"); + const result2 = navigation.navigate("#2"); + + assert_equals(navigation.entries().length, 3); + assert_array_equals(navigation.entries().map(e => (new URL(e.url)).hash), ["", "#1", "#2"]); + + await assertCommittedFulfillsFinishedRejectsDOM(t, result1, navigation.entries()[1], "AbortError"); + await assertBothFulfill(t, result2, navigation.currentEntry); +}, "interrupted navigate() promises with intercept()"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept-rejected.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept-rejected.html new file mode 100644 index 0000000000..79c8bd803e --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept-rejected.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + const err = new Error("boo!"); + const promise = Promise.reject(err); + promise.catch(() => {}); // prevent unhandled rejection testharness.js errors + navigation.onnavigate = e => e.intercept({ handler: () => promise }); + + const result = navigation.navigate("#1"); + + await assertCommittedFulfillsFinishedRejectsExactly(t, result, navigation.currentEntry, err); +}, "navigate() and intercept() with a rejected promise"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept.html new file mode 100644 index 0000000000..a9946c71ff --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-intercept.html @@ -0,0 +1,15 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + navigation.onnavigate = e => e.intercept({ handler: () => Promise.resolve({ abc: 'def' }) }); + + const result = navigation.navigate("#1"); + + await assertBothFulfill(t, result, navigation.currentEntry); + assert_equals((new URL(navigation.currentEntry.url)).hash, "#1"); +}, "navigate() and intercept() with a fulfilled promise"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-interrupted-within-onnavigate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-interrupted-within-onnavigate.html new file mode 100644 index 0000000000..3db02c6931 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-interrupted-within-onnavigate.html @@ -0,0 +1,28 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + let result2; + navigation.onnavigate = t.step_func(e => { + if (e.info == 1) { + result2 = navigation.navigate("#2", { info: 2 }); + assert_true(e.defaultPrevented); + } + }); + + const result1 = navigation.navigate("#1", { info: 1 }); + + assert_equals(navigation.entries().length, 2); + assert_array_equals(navigation.entries().map(e => (new URL(e.url)).hash), ["", "#2"]); + + await assertBothRejectDOM(t, result1, "AbortError"); + await assertBothFulfill(t, result2, navigation.currentEntry); +}, "if navigate() is called inside onnavigate, the previous navigation and navigate event are cancelled"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-interrupted.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-interrupted.html new file mode 100644 index 0000000000..2c928254e0 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-interrupted.html @@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + const result1 = navigation.navigate("#1"); + const result2 = navigation.navigate("#2"); + + assert_equals(navigation.entries().length, 3); + assert_array_equals(navigation.entries().map(e => (new URL(e.url)).hash), ["", "#1", "#2"]); + + await assertCommittedFulfillsFinishedRejectsDOM(t, result1, navigation.entries()[1], "AbortError"); + await assertBothFulfill(t, result2, navigation.currentEntry); +}, "interrupted navigate() promises"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-invalid-url.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-invalid-url.html new file mode 100644 index 0000000000..5b5b442c91 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-invalid-url.html @@ -0,0 +1,10 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + await assertBothRejectDOM(t, navigation.navigate("https://example.com\u0000mozilla.org"), "SyntaxError"); +}, "navigate() with an invalid URL"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-opaque-origin.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-opaque-origin.html new file mode 100644 index 0000000000..51500eb8d8 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-opaque-origin.html @@ -0,0 +1,9 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe id="i" sandbox="allow-scripts" src="resources/navigate-opaque-origin-page.html"></iframe> + +<script> +fetch_tests_from_window(i.contentWindow); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-preventDefault.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-preventDefault.html new file mode 100644 index 0000000000..6257c5a03d --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-preventDefault.html @@ -0,0 +1,12 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + navigation.onnavigate = e => e.preventDefault(); + + await assertBothRejectDOM(t, navigation.navigate("#"), "AbortError"); +}, "navigate() when the onnavigate handler calls preventDefault()"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-push-initial-about-blank.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-push-initial-about-blank.html new file mode 100644 index 0000000000..9d47c8d0b5 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-push-initial-about-blank.html @@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<body> +<iframe id="i"></iframe> +<script> +promise_test(async t => { + // Wait for after the load event so that we are definitely testing the initial + // about:blank-ness as the cause of the rejections. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + i.contentWindow.navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + const result = i.contentWindow.navigation.navigate("#1", { history: "push" }); + await assertBothRejectDOM(t, result, "NotSupportedError", i.contentWindow); +}, "navigate() with history: 'push' in initial about:blank document"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-push-javascript-url.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-push-javascript-url.html new file mode 100644 index 0000000000..e41e06a78d --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-push-javascript-url.html @@ -0,0 +1,19 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that we are definitely testing the + // javascript: URL as the cause of the rejections. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + const result = navigation.navigate("javascript:'foo'", { history: "push" }); + await assertBothRejectDOM(t, result, "NotSupportedError"); +}, "navigate() to a javascript: URL"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-beforeunload-unserializablestate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-beforeunload-unserializablestate.html new file mode 100644 index 0000000000..878280a56e --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-beforeunload-unserializablestate.html @@ -0,0 +1,31 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func('onnavigatesuccess should not be called'); + i.contentWindow.navigation.onnavigateerror = t.unreached_func('onnavigateerror should not be called'); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.navigate("/common/blank.html?1", { state: document.body }), "DataCloneError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, `navigate() with an unserializable state inside onbeforeunload "DataCloneError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-detached-unserializablestate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-detached-unserializablestate.html new file mode 100644 index 0000000000..2c6f9a28d4 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-detached-unserializablestate.html @@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + i.remove(); + + iWindow.navigation.onnavigate = t.unreached_func("onnavigate"); + + await assertBothRejectDOM(t, iWindow.navigation.navigate("https://example.com/", { state: document.body }), "DataCloneError", iWindow, iDOMException); +}, `navigate() with unserializable state in a detached iframe throws "DataCloneError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-beforeunload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-beforeunload.html new file mode 100644 index 0000000000..4873e85a2f --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-beforeunload.html @@ -0,0 +1,31 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.navigate("https://example.com\u0000mozilla.org"), "SyntaxError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, `navigate() with an invalid URL inside onbeforeunload throws "SyntaxError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-detached.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-detached.html new file mode 100644 index 0000000000..2250a54114 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-detached.html @@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + i.remove(); + + iWindow.navigation.onnavigate = t.unreached_func("onnavigate"); + + await assertBothRejectDOM(t, iWindow.navigation.navigate("https://example.com\u0000mozilla.org"), "SyntaxError", iWindow, iDOMException); +}, `navigate() with an invalid URL in a detached iframe throws "SyntaxError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-unload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-unload.html new file mode 100644 index 0000000000..d778dd662c --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-unload.html @@ -0,0 +1,27 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + i.contentWindow.navigation.navigate("?1"); + + await new Promise(resolve => { + i.contentWindow.onunload = t.step_func(async () => { + await assertBothRejectDOM(t, i.contentWindow.navigation.navigate("https://example.com\u0000mozilla.org"), "SyntaxError", i.contentWindow); + assert_equals(navigateEventCount, 1); + resolve(); + }); + }); +}, `navigate() with an invalid URL inside onunload throws "SyntaxError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-unserializablestate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-unserializablestate.html new file mode 100644 index 0000000000..07e194ca41 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-invalidurl-unserializablestate.html @@ -0,0 +1,12 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + navigation.onnavigate = t.unreached_func("onnavigate"); + + await assertBothRejectDOM(t, navigation.navigate("https://example.com\u0000mozilla.org", { state: document.body }), "SyntaxError"); +}, `navigate() with an invalid URL and unserializable state throws "SyntaxError", not "DataCloneError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-unload-unserializablestate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-unload-unserializablestate.html new file mode 100644 index 0000000000..417dd27174 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-rejection-order-unload-unserializablestate.html @@ -0,0 +1,27 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + i.contentWindow.navigation.navigate("?1"); + + await new Promise(resolve => { + i.contentWindow.onunload = t.step_func(async () => { + await assertBothRejectDOM(t, i.contentWindow.navigation.navigate("?2", { state: document.body }), "DataCloneError", i.contentWindow); + assert_equals(navigateEventCount, 1); + resolve(); + }); + }); +}, `navigate() with an unserializable state inside onunload throws "DataCloneError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-unload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-unload.html new file mode 100644 index 0000000000..fbc1fde6e9 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-unload.html @@ -0,0 +1,27 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + i.contentWindow.navigation.navigate("?1"); + + await new Promise(resolve => { + i.contentWindow.onunload = t.step_func(async () => { + await assertBothRejectDOM(t, i.contentWindow.navigation.navigate("?2"), "InvalidStateError", i.contentWindow); + assert_equals(navigateEventCount, 1); + resolve(); + }); + }); +}, `navigate() inside onunload`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-unserializable-state.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-unserializable-state.html new file mode 100644 index 0000000000..36464ec3c5 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate-unserializable-state.html @@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + await assertBothRejectDOM(t, navigation.navigate("#1", { state: new WritableStream() }), "DataCloneError"); + assert_equals(navigation.currentEntry.getState(), undefined); + assert_equals(location.hash, ""); +}, "navigate() with an unserializable state (WritableStream)"); + +promise_test(async t => { + // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()` + const buffer = new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer; + + await assertBothRejectDOM(t, navigation.navigate("#2", { state: buffer }), "DataCloneError"); + assert_equals(navigation.currentEntry.getState(), undefined); + assert_equals(location.hash, ""); +}, "navigate() with an unserializable state (SharedArrayBuffer)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate.html new file mode 100644 index 0000000000..34ff84f0e9 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/navigate.html @@ -0,0 +1,12 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + const result = navigation.navigate("#1"); + await assertBothFulfill(t, result, navigation.currentEntry); + assert_equals((new URL(navigation.currentEntry.url)).hash, "#1"); +}, "navigate() promises"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-already-detached.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-already-detached.html new file mode 100644 index 0000000000..9b0780c4a9 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-already-detached.html @@ -0,0 +1,19 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + i.remove(); + + await assertBothRejectDOM(t, iWindow.navigation.reload(), "InvalidStateError", iWindow, iDOMException); +}, "reload() in a detached window"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-beforeunload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-beforeunload.html new file mode 100644 index 0000000000..05338acc5e --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-beforeunload.html @@ -0,0 +1,31 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.reload(), "InvalidStateError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, "reload() inside onbeforeunload"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-detach-in-onnavigate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-detach-in-onnavigate.html new file mode 100644 index 0000000000..621bb598f6 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-detach-in-onnavigate.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + i.contentWindow.navigation.onnavigate = () => i.remove(); + + await assertBothRejectDOM(t, i.contentWindow.navigation.reload(), "AbortError", iWindow, iDOMException); +}, "reload() promise rejections when detaching an iframe inside onnavigate"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-detach-in-serialization.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-detach-in-serialization.html new file mode 100644 index 0000000000..d958d9cc84 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-detach-in-serialization.html @@ -0,0 +1,24 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + const trappedState = { + get prop() { + i.remove(); + return "whatever"; + } + }; + + await assertBothRejectDOM(t, i.contentWindow.navigation.reload({ state: trappedState }), "InvalidStateError", iWindow, iDOMException); +}, "reload() promise rejections when detaching an iframe inside state serialization"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-initial-about-blank.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-initial-about-blank.html new file mode 100644 index 0000000000..9e717fee48 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-initial-about-blank.html @@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<body> +<script> +promise_test(async t => { + let i = document.createElement("iframe"); + document.body.append(i); + + i.contentWindow.navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + const result = i.contentWindow.navigation.reload(); + assertNeverSettles(t, result, i.contentWindow); + await new Promise(resolve => t.step_timeout(resolve, 10)); +}, "reload() in initial about:blank document"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-intercept-rejected.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-intercept-rejected.html new file mode 100644 index 0000000000..93cd75c2b9 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-intercept-rejected.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + const err = new Error("boo!"); + const promise = Promise.reject(err); + promise.catch(() => {}); // prevent unhandled rejection testharness.js errors + navigation.onnavigate = e => e.intercept({ handler: () => promise }); + + const result = navigation.reload(); + + await assertCommittedFulfillsFinishedRejectsExactly(t, result, navigation.currentEntry, err); +}, "reload() and intercept() with a rejected promise"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-intercept.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-intercept.html new file mode 100644 index 0000000000..92f1636a6e --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-intercept.html @@ -0,0 +1,14 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + navigation.onnavigate = e => e.intercept({ handler: () => Promise.resolve({ abc: 'def' }) }); + + const result = navigation.reload(); + + await assertBothFulfill(t, result, navigation.currentEntry); +}, "reload() and intercept() with a fulfilled promise"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-preventDefault.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-preventDefault.html new file mode 100644 index 0000000000..747044b60f --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-preventDefault.html @@ -0,0 +1,12 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + navigation.onnavigate = e => e.preventDefault(); + + await assertBothRejectDOM(t, navigation.reload(), "AbortError"); +}, "reload() when the onnavigate handler calls preventDefault()"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-beforeunload-unserializablestate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-beforeunload-unserializablestate.html new file mode 100644 index 0000000000..950d665218 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-beforeunload-unserializablestate.html @@ -0,0 +1,31 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func('onnavigatesuccess should not be called'); + i.contentWindow.navigation.onnavigateerror = t.unreached_func('onnavigateerror should not be called'); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.reload({ state: document.body }), "DataCloneError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, `reload() with an unserializable state inside onbeforeunload throws "DataCloneError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-detached-unserializablestate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-detached-unserializablestate.html new file mode 100644 index 0000000000..9206f18e6c --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-detached-unserializablestate.html @@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + + i.remove(); + + iWindow.navigation.onnavigate = t.unreached_func("onnavigate"); + + await assertBothRejectDOM(t, iWindow.navigation.reload({ state: document.body }), "DataCloneError", iWindow, iDOMException); +}, `reload() with unserializable state in a detached iframe throws "DataCloneError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-unload-unserializablestate.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-unload-unserializablestate.html new file mode 100644 index 0000000000..9e7edcbba4 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-rejection-order-unload-unserializablestate.html @@ -0,0 +1,32 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + i.contentWindow.navigation.navigate("?1"); + + let assertionPromise; + await new Promise(resolve => { + i.contentWindow.onunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.reload({ state: document.body }), "DataCloneError", i.contentWindow); + assert_equals(navigateEventCount, 1); + resolve(); + }); + }); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + +}, `reload() with an unserializable state inside onunload throws "DataCloneError", not "InvalidStateError"`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-unload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-unload.html new file mode 100644 index 0000000000..1906659d1d --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-unload.html @@ -0,0 +1,27 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + i.contentWindow.navigation.navigate("?1"); + + await new Promise(resolve => { + i.contentWindow.onunload = t.step_func(async () => { + await assertBothRejectDOM(t, i.contentWindow.navigation.reload(), "InvalidStateError", i.contentWindow); + assert_equals(navigateEventCount, 1); + resolve(); + }); + }); +}, `reload() inside onunload`); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-unserializable-state.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-unserializable-state.html new file mode 100644 index 0000000000..76fa870558 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload-unserializable-state.html @@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + await assertBothRejectDOM(t, navigation.reload({ state: new WritableStream() }), "DataCloneError"); + assert_equals(navigation.currentEntry.getState(), undefined); + assert_equals(location.hash, ""); +}, "reload() with an unserializable state (WritableStream)"); + +promise_test(async t => { + // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()` + const buffer = new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer; + + await assertBothRejectDOM(t, navigation.reload({ state: buffer }), "DataCloneError"); + assert_equals(navigation.currentEntry.getState(), undefined); + assert_equals(location.hash, ""); +}, "reload() with an unserializable state (SharedArrayBuffer)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload.html new file mode 100644 index 0000000000..388f0d94b5 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/reload.html @@ -0,0 +1,16 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const result = i.contentWindow.navigation.reload(); + assertNeverSettles(t, result, i.contentWindow); + + await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0)); +}, "reload() promises never settle (without intercept())"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/204-205-download-on-second-visit.py b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/204-205-download-on-second-visit.py new file mode 100644 index 0000000000..c18b0dec3d --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/204-205-download-on-second-visit.py @@ -0,0 +1,24 @@ +def main(request, response): + key = request.GET[b"id"] + + # If hit with a POST with ?action=X, store X in the stash + if request.method == "POST": + action = request.GET[b"action"] + request.server.stash.put(key, action) + + return (204, [], "") + + # If hit with a GET, either return a normal initial page, or the abnormal requested response + elif request.method == "GET": + action = request.server.stash.take(key) + + if action is None: + return (200, [("Content-Type", "text/html"), ("Cache-Control", "no-store")], "initial page") + if action == b"204": + return (204, [], "") + if action == b"205": + return (205, [], "") + if action == b"download": + return (200, [("Content-Type", "text/plain"), ("Content-Disposition", "attachment")], "some text to download") + + return (400, [], "") diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/back-forward-opaque-origin-page.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/back-forward-opaque-origin-page.html new file mode 100644 index 0000000000..ec63363952 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/back-forward-opaque-origin-page.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="helpers.js"></script> +<!-- Put this page in a sandbox to give it an opaque origin --> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + location.hash = "#1"; + await new Promise(resolve => window.onhashchange = resolve); + location.hash = "#2"; + await new Promise(resolve => window.onhashchange = resolve); + history.back(); + await new Promise(resolve => window.onhashchange = resolve); + + assert_equals(location.hash, "#1"); + + await assertBothRejectDOM(t, navigation.back(), "InvalidStateError"); + await assertBothRejectDOM(t, navigation.forward(), "InvalidStateError"); +}, "navigation.back()/forward() in an opaque origin iframe"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/helpers.js b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/helpers.js new file mode 100644 index 0000000000..63d706ed28 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/helpers.js @@ -0,0 +1,127 @@ +window.assertReturnValue = (result, w = window) => { + assert_equals(Object.getPrototypeOf(result), w.Object.prototype, "result object must be from the right realm"); + assert_array_equals(Reflect.ownKeys(result), ["committed", "finished"]); + assert_true(result.committed instanceof w.Promise); + assert_true(result.finished instanceof w.Promise); + assert_not_equals(result.committed, result.finished); +}; + +window.assertNeverSettles = (t, result, w = window) => { + assertReturnValue(result, w); + result.committed.then( + t.unreached_func("committed must not fulfill"), + t.unreached_func("committed must not reject") + ); + + result.finished.then( + t.unreached_func("finished must not fulfill"), + t.unreached_func("finished must not reject") + ); +}; + +window.assertBothFulfillEntryNotAvailable = async (t, result, w = window) => { + assertReturnValue(result, w); + + // Don't use await here so that we can catch out-of-order settlements. + let committedValue; + result.committed.then( + t.step_func(v => { committedValue = v;}), + t.unreached_func("committed must not reject") + ); + + const finishedValue = await result.finished; + + assert_not_equals(committedValue, undefined, "committed must fulfill before finished"); + assert_equals(finishedValue, committedValue, "committed and finished must fulfill with the same value"); + assert_true(finishedValue instanceof w.NavigationHistoryEntry, "fulfillment value must be a NavigationHistoryEntry"); +}; + +window.assertBothFulfill = async (t, result, expected, w = window) => { + assertReturnValue(result, w); + + // Don't use await here so that we can catch out-of-order settlements. + let committedValue; + result.committed.then( + t.step_func(v => { committedValue = v; }), + t.unreached_func("committed must not reject") + ); + + const finishedValue = await result.finished; + + assert_not_equals(committedValue, undefined, "committed must fulfill before finished"); + assert_equals(finishedValue, committedValue, "committed and finished must fulfill with the same value"); + assert_true(finishedValue instanceof w.NavigationHistoryEntry, "fulfillment value must be a NavigationHistoryEntry"); + assert_equals(finishedValue, expected); +}; + +window.assertCommittedFulfillsFinishedRejectsExactly = async (t, result, expectedEntry, expectedRejection, w = window) => { + assertReturnValue(result, w); + + // Don't use await here so that we can catch out-of-order settlements. + let committedValue; + result.committed.then( + t.step_func(v => { committedValue = v; }), + t.unreached_func("committed must not reject") + ); + + await promise_rejects_exactly(t, expectedRejection, result.finished); + + assert_not_equals(committedValue, undefined, "committed must fulfill before finished rejects"); + assert_true(committedValue instanceof w.NavigationHistoryEntry, "fulfillment value must be a NavigationHistoryEntry"); + assert_equals(committedValue, expectedEntry); +}; + +window.assertCommittedFulfillsFinishedRejectsDOM = async (t, result, expectedEntry, expectedDOMExceptionCode, w = window, domExceptionConstructor = w.DOMException, navigationHistoryEntryConstuctor = w.NavigationHistoryEntry) => { + assertReturnValue(result, w); + + let committedValue; + result.committed.then( + t.step_func(v => { committedValue = v; }), + t.unreached_func("committed must not reject") + ); + + await promise_rejects_dom(t, expectedDOMExceptionCode, domExceptionConstructor, result.finished); + + assert_not_equals(committedValue, undefined, "committed must fulfill before finished rejects"); + assert_true(committedValue instanceof navigationHistoryEntryConstuctor, "fulfillment value must be an NavigationHistoryEntry"); + assert_equals(committedValue, expectedEntry); +}; + +window.assertBothRejectExactly = async (t, result, expectedRejection, w = window) => { + assertReturnValue(result, w); + + let committedReason, finishedReason; + await Promise.all([ + result.committed.then( + t.unreached_func("committed must not fulfill"), + t.step_func(r => { committedReason = r; }) + ), + result.finished.then( + t.unreached_func("finished must not fulfill"), + t.step_func(r => { finishedReason = r; }) + ) + ]); + + assert_equals(committedReason, finishedReason, "committed and finished must reject with the same value"); + assert_equals(expectedRejection, committedReason); +}; + +window.assertBothRejectDOM = async (t, result, expectedDOMExceptionCode, w = window, domExceptionConstructor = w.DOMException) => { + assertReturnValue(result, w); + + // Don't use await here so that we can catch out-of-order settlements. + let committedReason, finishedReason; + await Promise.all([ + result.committed.then( + t.unreached_func("committed must not fulfill"), + t.step_func(r => { committedReason = r; }) + ), + result.finished.then( + t.unreached_func("finished must not fulfill"), + t.step_func(r => { finishedReason = r; }) + ) + ]); + + assert_equals(committedReason, finishedReason, "committed and finished must reject with the same value"); + assert_throws_dom(expectedDOMExceptionCode, domExceptionConstructor, () => { throw committedReason; }); +}; diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/navigate-opaque-origin-page.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/navigate-opaque-origin-page.html new file mode 100644 index 0000000000..831eefdb61 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/resources/navigate-opaque-origin-page.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="helpers.js"></script> +<!-- Put this page in a sandbox to give it an opaque origin --> + +<script> +promise_test(async t => { + navigation.onnavigate = t.unreached_func("onnavigate should not be called"); + navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + const result = navigation.navigate("#1"); + assertNeverSettles(t, result); + await new Promise(resolve => t.step_timeout(resolve, 10)); +}, "navigation.navigate() in an opaque origin iframe"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-already-detached.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-already-detached.html new file mode 100644 index 0000000000..b974393df6 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-already-detached.html @@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + const key = iWindow.navigation.currentEntry.key; + + i.remove(); + + await assertBothRejectDOM(t, iWindow.navigation.traverseTo(key), "InvalidStateError", iWindow, iDOMException); +}, "traverseTo() in a detached window"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-beforeunload.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-beforeunload.html new file mode 100644 index 0000000000..3b2722235e --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-beforeunload.html @@ -0,0 +1,31 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let navigateEventCount = 0; + i.contentWindow.navigation.onnavigate = () => navigateEventCount++; + i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called"); + + let assertionPromise; + // The iframe does not have sticky activation, so per + // https://html.spec.whatwg.org/#prompt-to-unload-a-document, no prompt is + // shown and the navigation will proceed. + i.contentWindow.onbeforeunload = t.step_func(() => { + assertionPromise = assertBothRejectDOM(t, i.contentWindow.navigation.traverseTo(i.contentWindow.navigation.currentEntry.key), "InvalidStateError", i.contentWindow); + }); + i.contentWindow.navigation.navigate("?1"); + + assert_not_equals(assertionPromise, undefined); + await assertionPromise; + + assert_equals(navigateEventCount, 1); +}, "traverseTo() inside onbeforeunload"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-cross-document-preventDefault.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-cross-document-preventDefault.html new file mode 100644 index 0000000000..09c91ee647 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-cross-document-preventDefault.html @@ -0,0 +1,29 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + i.contentWindow.navigation.navigate("?1"); + await new Promise(resolve => i.onload = resolve); + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[1]); + + // This will be a noop, because navigate events are uncancelable for traversals. + i.contentWindow.navigation.onnavigate = e => e.preventDefault(); + + assertNeverSettles(t, i.contentWindow.navigation.traverseTo(key), i.contentWindow); + await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0)); +}, "traverseTo() promise never settle when preventDefault()ing the navigate event (cross-document)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-current.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-current.html new file mode 100644 index 0000000000..212fe992cf --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-current.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + assert_equals(navigation.entries().length, 1); + const entry = navigation.currentEntry; + + const result = navigation.traverseTo(navigation.currentEntry.key); + await assertBothFulfill(t, result, entry); + + assert_equals(navigation.entries().length, 1); + assert_equals(navigation.currentEntry, entry); +}, "traverseTo() with current key"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-cross-document-before-navigate-event.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-cross-document-before-navigate-event.html new file mode 100644 index 0000000000..ed319f6223 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-cross-document-before-navigate-event.html @@ -0,0 +1,32 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + i.contentWindow.navigation.navigate("?1"); + await new Promise(resolve => i.onload = resolve); + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[1]); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + i.contentWindow.navigation.onnavigate = t.unreached_func("navigate should not fire"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("navigateerror should not fire"); + + let promises = i.contentWindow.navigation.traverseTo(key); + i.remove(); + await assertBothRejectDOM(t, promises, "AbortError", iWindow, iDOMException); +}, "traverseTo() promise rejections when detaching an iframe before onnavigate (cross-document)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-cross-document.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-cross-document.html new file mode 100644 index 0000000000..8784313b70 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-cross-document.html @@ -0,0 +1,29 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + i.contentWindow.navigation.navigate("?1"); + await new Promise(resolve => i.onload = resolve); + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[1]); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + i.contentWindow.navigation.onnavigate = () => i.remove(); + + await assertBothRejectDOM(t, i.contentWindow.navigation.traverseTo(key), "AbortError", iWindow, iDOMException); +}, "traverseTo() promise rejections when detaching an iframe inside onnavigate (cross-document)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-same-document-before-navigate-event.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-same-document-before-navigate-event.html new file mode 100644 index 0000000000..592ac6f199 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-same-document-before-navigate-event.html @@ -0,0 +1,31 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + await i.contentWindow.navigation.navigate("#1").committed; + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[1]); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + i.contentWindow.navigation.onnavigate = t.unreached_func("navigate should not fire"); + i.contentWindow.navigation.onnavigateerror = t.unreached_func("navigateerror should not fire"); + + let promises = i.contentWindow.navigation.traverseTo(key); + i.remove(); + await assertBothRejectDOM(t, promises, "AbortError", iWindow, iDOMException); +}, "traverseTo() promise rejections when detaching an iframe before onnavigate (same-document)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-same-document.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-same-document.html new file mode 100644 index 0000000000..b0308b8df8 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-detach-same-document.html @@ -0,0 +1,28 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<iframe id="i" src="/common/blank.html"></iframe> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + assert_equals(i.contentWindow.navigation.entries().length, 1); + let key = i.contentWindow.navigation.currentEntry.key; + + await i.contentWindow.navigation.navigate("#1").committed; + + assert_equals(i.contentWindow.navigation.entries().length, 2); + assert_equals(i.contentWindow.navigation.currentEntry, i.contentWindow.navigation.entries()[1]); + + const iWindow = i.contentWindow; + const iDOMException = iWindow.DOMException; + i.contentWindow.navigation.onnavigate = () => i.remove(); + + await assertBothRejectDOM(t, i.contentWindow.navigation.traverseTo(key), "AbortError", iWindow, iDOMException); +}, "traverseTo() promise rejections when detaching an iframe inside onnavigate (same-document)"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-intercept-rejected.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-intercept-rejected.html new file mode 100644 index 0000000000..f934eae5d4 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-intercept-rejected.html @@ -0,0 +1,30 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + const key0 = navigation.currentEntry.key; + + location.href = "#1"; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + const err = new Error("boo!"); + const promise = Promise.reject(err); + promise.catch(() => {}); // prevent unhandled rejection testharness.js errors + navigation.onnavigate = e => e.intercept({ handler: () => promise }); + + const result = navigation.traverseTo(key0); + await assertCommittedFulfillsFinishedRejectsExactly(t, result, entry0, err); + assert_equals(navigation.currentEntry, entry0); +}, "traverseTo() promise rejection with rejected intercept()"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-intercept.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-intercept.html new file mode 100644 index 0000000000..a4cb4e711d --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-intercept.html @@ -0,0 +1,27 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + const key0 = navigation.currentEntry.key; + + location.href = "#1"; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + navigation.onnavigate = e => e.intercept({ handler: () => Promise.resolve({ abc: "def" }) }); + + const result = navigation.traverseTo(key0); + await assertBothFulfill(t, result, entry0); + assert_equals(navigation.currentEntry, entry0); +}, "traverseTo() and intercept() with a fulfilled promise"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-invalid-key.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-invalid-key.html new file mode 100644 index 0000000000..42be40bfa7 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-invalid-key.html @@ -0,0 +1,10 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + await assertBothRejectDOM(t, navigation.traverseTo("not a real key"), "InvalidStateError"); +}, "traverseTo() with invalid key"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-repeated.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-repeated.html new file mode 100644 index 0000000000..d1754d6729 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo-repeated.html @@ -0,0 +1,24 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + const key = navigation.currentEntry.key; + const entry = navigation.currentEntry; + await navigation.navigate("#1").committed; + + const result1 = navigation.traverseTo(key); + const result2 = navigation.traverseTo(key); + + await assertBothFulfill(t, result1, entry); + assert_not_equals(result1, result2); + assert_equals(result2.committed, result1.committed, "committed promises must be equal"); + assert_equals(result2.finished, result1.finished, "finished promises must be equal"); +}, "Repeated navigation.traverseTo() with the same key"); +</script> diff --git a/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo.html b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo.html new file mode 100644 index 0000000000..8e00f5ba91 --- /dev/null +++ b/testing/web-platform/tests/navigation-api/navigation-methods/return-value/traverseTo.html @@ -0,0 +1,25 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> + +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + + const key0 = navigation.currentEntry.key; + + location.href = "#1"; + + assert_equals(navigation.entries().length, 2); + const [entry0, entry1] = navigation.entries(); + assert_equals((new URL(entry0.url)).hash, ""); + assert_equals((new URL(entry1.url)).hash, "#1"); + + const result = navigation.traverseTo(key0); + await assertBothFulfill(t, result, entry0); + assert_equals(navigation.currentEntry, entry0); +}, "traverseTo() promises"); +</script> |