| window.testDeferredCommit = async (t, navigationType, mode, destinationIndex = 0) => { |
| let startHash = location.hash; |
| let destinationHash; |
| const err = new Error("boo!"); |
| |
| let popstate_fired = false; |
| window.addEventListener("popstate", () => popstate_fired = true, { once : true }); |
| let navigatesuccess_fired = false; |
| navigation.addEventListener("navigatesuccess", () => navigatesuccess_fired = true, { once : true }); |
| let navigateerror_fired = false; |
| navigation.addEventListener("navigateerror", () => navigateerror_fired = true, { once : true }); |
| |
| // mode-specific logic for the navigate event handler |
| let navigate_helpers = { |
| rejectBeforeCommit : async (e) => { return Promise.reject("Should never run") }, |
| rejectAfterCommit : async (e) => { |
| assert_equals(location.hash, destinationHash, "hash after commit"); |
| assert_equals(false, popstate_fired, "popstate before handler starts"); |
| await new Promise(resolve => t.step_timeout(resolve, 0)); |
| assert_equals(navigationType == "traverse", popstate_fired, "popstate fired after handler async step"); |
| return Promise.reject(err); |
| }, |
| success : async (e) => { |
| assert_equals(location.hash, destinationHash, "hash after commit"); |
| assert_equals(false, popstate_fired, "popstate before handler starts"); |
| await new Promise(resolve => t.step_timeout(resolve, 0)); |
| assert_equals(navigationType == "traverse", popstate_fired, "popstate fired after handler async step"); |
| return new Promise(resolve => t.step_timeout(resolve, 0)); |
| }, |
| } |
| |
| navigation.addEventListener("navigate", e => { |
| e.intercept({ precommitHandler: t.step_func(async () => { |
| assert_equals(e.navigationType, navigationType); |
| assert_equals(location.hash, startHash, "start hash"); |
| assert_false(popstate_fired, "popstate fired at handler start"); |
| |
| await new Promise(resolve => t.step_timeout(resolve, 0)); |
| assert_equals(location.hash, startHash, "hash after first async step"); |
| assert_false(popstate_fired, "popstate fired after first async step"); |
| |
| if (mode == "rejectBeforeCommit") |
| return Promise.reject(err); |
| }), |
| handler: t.step_func(navigate_helpers[mode]) |
| }); |
| }, { once: true }); |
| |
| let startingIndex = navigation.currentEntry.index; |
| let expectedIndexOnCommit; |
| |
| let promises; |
| if (navigationType === "push" || navigationType === "replace") { |
| destinationHash = (startHash === "" ? "#" : startHash) + "a"; |
| promises = navigation.navigate(destinationHash, { history: navigationType }); |
| expectedIndexOnCommit = (navigationType === "push") ? startingIndex + 1 |
| : startingIndex; |
| } else if (navigationType === "reload") { |
| destinationHash = startHash; |
| promises = navigation.reload(); |
| expectedIndexOnCommit = startingIndex; |
| } else if (navigationType === "traverse") { |
| let destinationEntry = navigation.entries()[destinationIndex]; |
| destinationHash = new URL(destinationEntry.url).hash; |
| promises = navigation.traverseTo(destinationEntry.key); |
| expectedIndexOnCommit = destinationIndex; |
| } |
| |
| if (mode === "rejectBeforeCommit") { |
| await assertBothRejectExactly(t, promises, err); |
| assert_equals(location.hash, startHash, "hash after promise resolution"); |
| assert_false(popstate_fired, "popstate fired after promise resolution"); |
| assert_false(navigatesuccess_fired, "navigatesuccess fired"); |
| assert_true(navigateerror_fired, "navigateerror fired"); |
| assert_equals(navigation.currentEntry.index, startingIndex); |
| } else if (mode === "rejectAfterCommit") { |
| await promises.committed; |
| await assertCommittedFulfillsFinishedRejectsExactly(t, promises, navigation.currentEntry, err); |
| assert_equals(location.hash, destinationHash, "hash after promise resolution"); |
| assert_equals(navigationType == "traverse", popstate_fired, "popstate fired after promise resolution"); |
| assert_false(navigatesuccess_fired, "navigatesuccess fired"); |
| assert_true(navigateerror_fired, "navigateerror fired"); |
| assert_equals(navigation.currentEntry.index, expectedIndexOnCommit); |
| } else { |
| await promises.committed; |
| await assertBothFulfill(t, promises, navigation.currentEntry); |
| assert_equals(location.hash, destinationHash, "hash after promise resolution"); |
| assert_equals(navigationType == "traverse", popstate_fired, "popstate fired after promise resolution"); |
| assert_true(navigatesuccess_fired, "navigatesuccess fired"); |
| assert_false(navigateerror_fired, "navigateerror fired"); |
| assert_equals(navigation.currentEntry.index, expectedIndexOnCommit); |
| } |
| } |