diff options
Diffstat (limited to 'testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js')
-rw-r--r-- | testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js new file mode 100644 index 0000000000..80c164f560 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js @@ -0,0 +1,137 @@ +// A collection of helper functions that make use of the `remoteContextHelper` +// to test BFCache support and behavior. + +// Call `prepareForBFCache()` before navigating away from the page. This simply +// sets a variable in window. +async function prepareForBFCache(remoteContextHelper) { + await remoteContextHelper.executeScript(() => { + window.beforeBFCache = true; + }); +} + +// Call `getBeforeCache()` after navigating back to the page. This returns the +// value in window. +async function getBeforeBFCache(remoteContextHelper) { + return await remoteContextHelper.executeScript(() => { + return window.beforeBFCache; + }); +} + +// If the value in window is set to true, this means that the page was reloaded, +// i.e., the page was restored from BFCache. +// Call `prepareForBFCache()` before navigating away to call this function. +async function assertImplementsBFCacheOptional(remoteContextHelper) { + var beforeBFCache = await getBeforeBFCache(remoteContextHelper); + assert_implements_optional(beforeBFCache == true, 'BFCache not supported.'); +} + +// Subtracts set `b` from set `a` and returns the result. +function setMinus(a, b) { + const minus = new Set(); + a.forEach(e => { + if (!b.has(e)) { + minus.add(e); + } + }); + return minus; +} + +// Return a sorted Array from the iterable `s`. +function sorted(s) { + return Array.from(s).sort(); +} + +// Assert expected reasons and the reported reasons match. +function matchReasons(expectedNotRestoredReasonsSet, notRestoredReasonsSet) { + const missing = setMinus( + expectedNotRestoredReasonsSet, notRestoredReasonsSet, 'Missing reasons'); + const extra = setMinus( + notRestoredReasonsSet, expectedNotRestoredReasonsSet, 'Extra reasons'); + assert_true(missing.size + extra.size == 0, `Expected: ${sorted(expectedNotRestoredReasonsSet)}\n` + + `Got: ${sorted(notRestoredReasonsSet)}\n` + + `Missing: ${sorted(missing)}\n` + + `Extra: ${sorted(extra)}\n`); +} + +// This function takes a set of reasons and extracts reasons out of it and returns a set of strings. +// For example, if the input is [{"reason": "error-document"}, {"reason": "masked"}], +// the output is ["error-document", "masked"]. +function extractReason(reasonSet) { + let reasonsExtracted = new Set(); + for (let reason of reasonSet) { + reasonsExtracted.add(reason.reason); + } + return reasonsExtracted; +} + +// A helper function to assert that the page is not restored from BFCache by +// checking whether the `beforeBFCache` value from `window` is undefined +// due to page reload. +// This function also takes an optional `notRestoredReasons` list which +// indicates the set of expected reasons that make the page not restored. +// If the reasons list is undefined, the check will be skipped. Otherwise +// this check will use the `notRestoredReasons` API, to obtain the reasons +// in a tree structure, and flatten the reasons before making the order- +// insensitive comparison. +// If the API is not available, the function will terminate instead of marking +// the assertion failed. +// Call `prepareForBFCache()` before navigating away to call this function. +async function assertNotRestoredFromBFCache( + remoteContextHelper, notRestoredReasons) { + var beforeBFCache = await getBeforeBFCache(remoteContextHelper); + assert_equals(beforeBFCache, undefined, 'document unexpectedly BFCached'); + + // The reason is optional, so skip the remaining test if the + // `notRestoredReasons` is not set. + if (notRestoredReasons === undefined) { + return; + } + + let isFeatureEnabled = await remoteContextHelper.executeScript(() => { + return 'notRestoredReasons' in + performance.getEntriesByType('navigation')[0]; + }); + + // Return if the `notRestoredReasons` API is not available. + if (!isFeatureEnabled) { + return; + } + + let result = await remoteContextHelper.executeScript(() => { + return performance.getEntriesByType('navigation')[0].notRestoredReasons; + }); + + let expectedNotRestoredReasonsSet = new Set(notRestoredReasons); + let notRestoredReasonsSet = new Set(); + + // Flatten the reasons from the main frame and all the child frames. + const collectReason = (node) => { + for (let reason of node.reasons) { + notRestoredReasonsSet.add(reason.reason); + } + for (let child of node.children) { + collectReason(child); + } + }; + collectReason(result); + matchReasons(expectedNotRestoredReasonsSet, notRestoredReasonsSet); +} + +// A helper function that combines the steps of setting window property, +// navigating away and back, and making assertion on whether BFCache is +// supported. +// This function can be used to check if the current page is eligible for +// BFCache. +async function assertBFCacheEligibility( + remoteContextHelper, shouldRestoreFromBFCache) { + await prepareForBFCache(remoteContextHelper); + // Navigate away and back. + const newRemoteContextHelper = await remoteContextHelper.navigateToNew(); + await newRemoteContextHelper.historyBack(); + + if (shouldRestoreFromBFCache) { + await assertImplementsBFCacheOptional(remoteContextHelper); + } else { + await assertNotRestoredFromBFCache(remoteContextHelper); + } +} |