Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/common/utils.js"></script>
<script src="../resources/utils.js"></script>
<script src="resources/utils.sub.js"></script>
<script src="/common/subset-tests-by-key.js"></script>
<meta name="variant" content="?include=noPrefetch">
<meta name="variant" content="?include=afterResponse">
<meta name="variant" content="?include=waitingForResponse">
<meta name="variant" content="?include=waitingForRedirect">
<script>
const setupProperties = {};
if (shouldRunSubTest('waitingForResponse') || shouldRunSubTest('waitingForRedirect')) {
// These tests rely on the relationship between these timeouts, the delays
// on the server, and any vendor specific timeouts. Force a multiplier of 1,
// since using setTimeout directly incurs the wrath of `wpt lint`.
setupProperties.timeout_multiplier = 1;
}
setup(() => assertSpeculationRulesIsSupported(), setupProperties);
subsetTestByKey('noPrefetch', promise_test, async t => {
const agent = await spawnWindow(t);
const landingUrl = agent.getExecutorURL({page: 2});
await agent.navigate(landingUrl);
assert_not_prefetched(await agent.getRequestHeaders(), `${landingUrl} should not be prefetched.`);
// It's generally expected that events occur in this order:
// ... -> connectEnd --> requestStart --> responseStart --> ...
const [entry] = await agent.execute_script(
() => performance.getEntriesByType('navigation'));
assert_less_than_equal(entry.connectEnd, entry.requestStart);
assert_less_than_equal(entry.requestStart, entry.responseStart);
}, "PerformanceNavigationTiming data should be in the correct order (no prefetch)");
subsetTestByKey('afterResponse', promise_test, async t => {
const agent = await spawnWindow(t);
const landingUrl = agent.getExecutorURL({page: 2});
await agent.forceSinglePrefetch(landingUrl);
await agent.navigate(landingUrl);
assert_prefetched(await agent.getRequestHeaders(), `${landingUrl} should have been prefetched.`);
// Since the response should have started before the navigation, these should
// all have the same value (i.e., the start of the fetch).
const [entry] = await agent.execute_script(
() => performance.getEntriesByType('navigation'));
assert_equals(entry.connectEnd, entry.requestStart);
assert_equals(entry.requestStart, entry.responseStart);
}, "PerformanceNavigationTiming data should show 'instantaneous' events completed beforehand");
subsetTestByKey('waitingForResponse', promise_test, async t => {
const agent = await spawnWindow(t);
const landingUrl = agent.getExecutorURL({executor: 'slow-executor.py', delay: '3', page: 2});
await agent.forceSinglePrefetch(landingUrl, {}, /*wait_for_completion=*/false);
// Chromium, at least, will give up the prefetch if the response head doesn't
// come back within 1 second of navigation. So since the server will take
// 3 seconds to respond, we wait 2.5 seconds before navigating, to ensure the
// response comes back within about 0.5 seconds.
await new Promise(resolve => t.step_timeout(resolve, 2_500));
await agent.navigate(landingUrl);
assert_prefetched(await agent.getRequestHeaders(), `${landingUrl} should have been prefetched.`);
// Unlike the `afterResponse` test, we expect delays between `requestStart`
// and `responseStart` here. If our timing was perfect and server round-trips
// were instantaneous, that delay would be 0.5 seconds. To give ourselves a
// bit of wiggle room, instead we assert that it's at least 0.1 seconds.
const [entry] = await agent.execute_script(
() => performance.getEntriesByType('navigation'));
assert_less_than_equal(entry.connectEnd, entry.requestStart, "connectEnd must be before requestStart");
assert_greater_than(entry.responseStart, entry.requestStart + 100, "responseStart must be > 100 ms after requestStart");
}, "PerformanceNavigationTiming data should show noticeable TTFB if the response is slow");
subsetTestByKey('waitingForRedirect', promise_test, async t => {
const agent = await spawnWindow(t);
const landingUrl = agent.getExecutorURL({page: 2});
const slowRedirectUrl = new URL(`/common/slow-redirect.py?delay=3&location=${encodeURIComponent(landingUrl)}`, document.baseURI);
await agent.forceSinglePrefetch(slowRedirectUrl, {}, /*wait_for_completion=*/false);
// Considerations here are the same as for `waitingForResponse`.
await new Promise(resolve => t.step_timeout(resolve, 2_500));
await agent.navigate(slowRedirectUrl, {expectedDestinationUrl: landingUrl});
assert_prefetched(await agent.getRequestHeaders(), `${landingUrl} should have been prefetched.`);
// As in `waitingForResponse`, we expect at least 0.1 seconds TTFB. Unlike in
// that test, the delta isn't captured by `requestStart` vs. `responseStart`,
// because these stats only measure the final request/response pair, which is
// not delayed.
const [entry] = await agent.execute_script(
() => performance.getEntriesByType('navigation'));
assert_less_than_equal(entry.connectEnd, entry.requestStart, "connectEnd must be before requestStart");
assert_less_than_equal(entry.requestStart, entry.responseStart, "requestStart must be before responseStart");
assert_greater_than(entry.connectEnd, 100, "connectEnd must be > 100 ms");
}, "PerformanceNavigationTiming data should show noticeable TTFB if the response is slow");
</script>