summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/speculation-rules/prefetch/out-of-document-rule-set.https.html
blob: 9f2c311715a8a3d9b5ff129809e57dbfe80dceb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/common/subset-tests-by-key.js"></script>
<script src="/common/utils.js"></script>
<script src="resources/utils.sub.js"></script>

<meta name="variant" content="?include=BaseCase">
<meta name="variant" content="?include=FollowRedirect">
<meta name="variant" content="?include=RelativeUrlForSpeculationRulesSet">
<meta name="variant" content="?include=RelativeUrlForCandidate">
<meta name="variant" content="?include=UseNonUTF8EncodingForSpeculationRulesSet">
<meta name="variant" content="?include=FailCORS">
<meta name="variant" content="?include=FailToParseSpeculationRulesHeader">
<meta name="variant" content="?include=InnerListInSpeculationRulesHeader">
<meta name="variant" content="?include=EmptyRuleSet">
<meta name="variant" content="?include=FailToParseRuleSet">
<meta name="variant" content="?include=InvalidUrlForSpeculationRulesSet">
<meta name="variant" content="?include=StatusCode199">
<meta name="variant" content="?include=StatusCode404">
<meta name="variant" content="?include=InvalidMimeType">

<script>
  async function runSpeculationRulesFetchTest(t, options) {
    options = {
      // Whether a prefetch is expected to succeed.
      shouldPrefetch: true,
      // Status code to be returned in the response.
      status: 200,
      // Whether a redirect must be followed to reach the rule set.
      redirect: false,
      // Whether to use relative URLs for the candidates in the rule set.
      useRelativeUrlForCandidate: false,
      // Whether to use relative URL for the rule set in SpeculationRules header.
      useRelativeUrlForSpeculationRulesSet: false,
      // Whether to use UTF-8 encoding for the rule set.
      useUtf8EncodingForSpeculationRulesSet: true,
      // Whether to force the response to cause a CORS failure.
      failCors: false,
      // Whether to use a valid SpeculationRules header format.
      useValidSpeculationRulesHeaderValue: true,
      // Whether to use an inner list of URLS in SpeculationRules header.
      useInnerListInSpeculationRulesHeaderValue: false,
      // Whether to return an empty response.
      useEmptySpeculationRulesSet: false,
      // Wheter to return a rule set with valid JSON format
      useValidJsonForSpeculationRulesSet: true,
      // Wheter to use a valid URL for the rule set in SpeculationRules header.
      useValidUrlForSpeculationRulesSet: true,
      // Wheter to use the valid "application/speculationrules-json" MIME type for the rule set.
      useValidMimeTypeForSpeculationRulesSet: true,
      ...options
    };
    assert_implements(HTMLScriptElement.supports('speculationrules'), "Speculation Rules not supported.");

    let page = 2;
    let uuid = token();
    let executor_url = new URL(`executor.sub.html`, SR_PREFETCH_UTILS_URL).toString();
    if (options.useRelativeUrlForCandidate) {
      executor_url = `executor.sub.html`;
    }
    let speculation_rule_set_url = `ruleset.py?url=${executor_url}&uuid=${uuid}&page=${page}&status=${options.status}&valid_mime=${options.useValidMimeTypeForSpeculationRulesSet}&valid_json=${options.useValidJsonForSpeculationRulesSet}&empty_json=${options.useEmptySpeculationRulesSet}&fail_cors=${options.failCors}&valid_encoding=${options.useUtf8EncodingForSpeculationRulesSet}&redirect=${options.redirect}`;
    if (!options.useRelativeUrlForSpeculationRulesSet) {
      let base_url = new URL(SR_PREFETCH_UTILS_URL);
      base_url.hostname = PREFETCH_PROXY_BYPASS_HOST;
      speculation_rule_set_url = new URL(speculation_rule_set_url, base_url).toString();
    }
    if (!options.useValidUrlForSpeculationRulesSet) {
      speculation_rule_set_url = "http://:80/";
    }

    let speculation_rules_header = `header(Speculation-Rules,"${speculation_rule_set_url}")`;
    if (!options.useValidSpeculationRulesHeaderValue) {
      speculation_rules_header = `header(Speculation-Rules, x y z)`;
    }
    else if (options.useInnerListInSpeculationRulesHeaderValue) {
      speculation_rules_header =  `header(Speculation-Rules, \\("${speculation_rule_set_url}" "xyz.com/rule-set.json"\\))`;
    }

    let agent = await spawnWindow(t, {pipe: speculation_rules_header}, uuid);
    await new Promise(resolve => t.step_timeout(resolve, 2000));
    // Passing non-ascii character '÷' as part of the next URL to check if we always decode the speculation rules set using utf-8 or not. This character is encoded differently in utf-8 and windows-1250
    let nextUrl = agent.getExecutorURL({ page, str: decodeURIComponent('%C3%B7')});
    await agent.navigate(nextUrl);

    await new Promise(resolve => t.step_timeout(resolve, 2000));

    let test_case_desc = JSON.stringify(options);
    if (options.shouldPrefetch)
      assert_prefetched(await agent.getRequestHeaders(), `Prefetch should work for request ${test_case_desc}.`);
    else
      assert_not_prefetched(await agent.getRequestHeaders(), `Prefetch should not work for request ${test_case_desc}.`);
  }

  subsetTestByKey('BaseCase', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {});
  }, "Base case.");

  subsetTestByKey('FollowRedirect', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {redirect: true});
  }, "It should follow redirects and fetch the speculation rules set.");

  subsetTestByKey('RelativeUrlForSpeculationRulesSet', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useRelativeUrlForSpeculationRulesSet: true});
  }, "It should fetch a speculation rules set using its relative URL.");

  subsetTestByKey('RelativeUrlForCandidate', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useRelativeUrlForCandidate: true, shouldPrefetch: false});
  }, "It should resolve the relative candidate URLs in the speculation rules set based on the speculation rules set's URL");

  subsetTestByKey('UseNonUTF8EncodingForSpeculationRulesSet', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useUtf8EncodingForSpeculationRulesSet: false, shouldPrefetch: false});
  }, "The speculation rules set should always be encoded using UTF-8.");

  subsetTestByKey('FailCORS', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {failCors: true, shouldPrefetch: false});
  }, "It should reject the speculation rules set if CORS fails.");

  subsetTestByKey('FailToParseSpeculationRulesHeader', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useValidSpeculationRulesHeaderValue: false, shouldPrefetch: false});
  }, "It should reject the speculation rules set if it fails to parse the SpeculationRules header.");

  subsetTestByKey('InnerListInSpeculationRulesHeader', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useInnerListInSpeculationRulesHeaderValue: true, shouldPrefetch: false});
  }, "It should reject the speculation rules passed as inner list in the SpeculationRules header.");

  subsetTestByKey('EmptyRuleSet', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useEmptySpeculationRulesSet: true, shouldPrefetch: false});
  }, "It should reject an empty speculation rules set.");

  subsetTestByKey('FailToParseRuleSet', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useValidJsonForSpeculationRulesSet: false, shouldPrefetch: false});
  }, "It should reject the speculation rules set if it cannot parse it.");

  subsetTestByKey('InvalidUrlForSpeculationRulesSet', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useValidUrlForSpeculationRulesSet: false, shouldPrefetch: false});
  }, "It should reject the speculation rules set with invalid URL.");

  subsetTestByKey('StatusCode199', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {status: 199, shouldPrefetch: false});
  }, "It should reject the speculation rules set with unsuccessful status code.");

  subsetTestByKey('StatusCode404', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {status: 404, shouldPrefetch: false});
  }, "It should reject the speculation rules set with unsuccessful status code.");

  subsetTestByKey('InvalidMimeType', promise_test, async t => {
    return runSpeculationRulesFetchTest(t, {useValidMimeTypeForSpeculationRulesSet: false, shouldPrefetch: false});
  }, "It should reject the speculation rules set with invalid MIME type.");

</script>