find-range-from-text-directive.html (9370B)
1 <!doctype html> 2 <title>Tests find-a-range-from-a-text-directive algorithm</title> 3 <meta charset=utf-8> 4 <link rel="help" href="https://wicg.github.io/scroll-to-text-fragment/#find-a-range-from-a-text-directive"> 5 <meta name="timeout" content="long"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/resources/testdriver.js"></script> 9 <script src="/resources/testdriver-vendor.js"></script> 10 <script src="/common/utils.js"></script> 11 <script src="stash.js"></script> 12 <!-- 13 This test suite performs scroll to text navigations to 14 find-range-from-text-directive-target.html and then checks the results, which are 15 communicated back from the target page via the WPT Stash server (see stash.py). 16 This structure is necessary because scroll to text security restrictions 17 specifically restrict the navigator from being able to observe the result of 18 the navigation, e.g. the target page cannot have a window opener. 19 --> 20 <script> 21 // This test suite specifically exercises the "find a range from a text 22 // directive" algorithm in the spec. 23 24 let test_cases = [ 25 { 26 fragment: '#:~:text=jumped', 27 expect_to_scroll: true, 28 description: 'Basic smoke test - full word match' 29 }, 30 { 31 // Step 2.2.1 32 fragment: '#:~:text=u-,mped', 33 expect_to_scroll: false, 34 description: 'Prefix must start on a word boundary' 35 }, 36 { 37 // Step 2.2.1 38 fragment: '#:~:text=ju-,mped', 39 expect_to_scroll: true, 40 description: 'Prefix need not end on a word boundary' 41 }, 42 { 43 // Step 2.2.2 44 fragment: '#:~:text=null-,The%20quick', 45 expect_to_scroll: false, 46 description: 'Prefix doesn\'t exist' 47 }, 48 { 49 // Step 2.2.3 50 fragment: '#:~:text=foo%20foo-,bar', 51 expect_to_scroll: true, 52 description: 'Multiple overlapping prefixes' 53 }, 54 { 55 // Step 2.2.3 56 fragment: '#:~:text=a%20a-,b', 57 expect_to_scroll: true, 58 description: 'Multiple overlapping one letter prefixes' 59 }, 60 { 61 // Step 2.2.4 62 fragment: '#:~:text=quick%20brown-,brown%20fox', 63 expect_to_scroll: false, 64 description: 'Prefix overlaps match text' 65 }, 66 { 67 // Step 2.2.4 68 fragment: '#:~:text=quick%20brown-,fox', 69 expect_to_scroll: true, 70 description: 'Match text after prefix' 71 }, 72 { 73 // Step 2.2.5 74 fragment: '#:~:text=Lorem-,Ipsum', 75 expect_to_scroll: true, 76 description: 'Search invisible content between prefix and match' 77 }, 78 { 79 // Step 2.2.6 80 fragment: '#:~:text=end%20of%20the%20document-,test', 81 expect_to_scroll: false, 82 description: 'Prefix appears at end of document' 83 }, 84 { 85 // Step 2.2.8 86 fragment: '#:~:text=fox-,jum,over', 87 expect_to_scroll: false, 88 description: '|end| forces |start| to end on word boundary' 89 }, 90 { 91 // Step 2.2.8 92 fragment: '#:~:text=fox-,jum', 93 expect_to_scroll: false, 94 description: 'no |end| or suffix forces |start| to end on word boundary' 95 }, 96 { 97 // Step 2.2.8 98 fragment: '#:~:text=fox-,jum,-ped', 99 expect_to_scroll: true, 100 description: 'suffix means |start| need not end on word boundary' 101 }, 102 { 103 // Step 2.2.9 104 fragment: '#:~:text=jum-,ped', 105 expect_to_scroll: true, 106 description: '|start| doesn\'t need to start on word boundary' 107 }, 108 { 109 // Step 2.2.10 110 fragment: '#:~:text=jumped-,null', 111 expect_to_scroll: false, 112 description: 'prefix with non-existent exact match' 113 }, 114 { 115 // Step 2.2.10 116 fragment: '#:~:text=jumped-,null,lazy', 117 expect_to_scroll: false, 118 description: 'prefix with non-existent range match' 119 }, 120 { 121 // Step 2.2.11 122 fragment: '#:~:text=brown-,jumped', 123 expect_to_scroll: false, 124 description: 'match doesn\'t immediately follow prefix' 125 }, 126 { 127 // Step 2.2.11 128 fragment: '#:~:text=foo-,bar', 129 expect_to_scroll: true, 130 description: 'match doesn\'t immediately follow first prefix instance' 131 }, 132 { 133 // Step 2.3.1 134 fragment: '#:~:text=jum,over', 135 expect_to_scroll: false, 136 description: 'no-prefix; |end| forces |start| to end on word boundary' 137 }, 138 { 139 // Step 2.3.1 140 fragment: '#:~:text=jum', 141 expect_to_scroll: false, 142 description: 'no-prefix; no |end| or suffix forces |start| to end on word boundary' 143 }, 144 { 145 // Step 2.3.1 146 fragment: '#:~:text=jum,-ped', 147 expect_to_scroll: true, 148 description: 'no-prefix; suffix means |start| need not end on word boundary' 149 }, 150 { 151 // Step 2.3.2 152 fragment: '#:~:text=umped', 153 expect_to_scroll: false, 154 description: '|start| must start on a word boundary' 155 }, 156 { 157 // Step 2.3.3 158 fragment: '#:~:text=null', 159 expect_to_scroll: false, 160 description: 'non-existent exact match' 161 }, 162 { 163 // Step 2.3.3 164 fragment: '#:~:text=null,lazy', 165 expect_to_scroll: false, 166 description: 'non-existent range match' 167 }, 168 { 169 // Step 2.3.4 170 fragment: '#:~:text=b%20b,-c', 171 expect_to_scroll: true, 172 description: 'overlapping exact matches with suffix' 173 }, 174 { 175 // Step 2.3.4 176 fragment: '#:~:text=foo%20foo,-bar', 177 expect_to_scroll: true, 178 description: 'overlapping one letter exact matches with suffix' 179 }, 180 { 181 // Step 2.5.1 182 fragment: '#:~:text=brown,fox', 183 expect_to_scroll: true, 184 description: 'matching range search' 185 }, 186 { 187 // Step 2.4 188 fragment: '#:~:text=brown,quick', 189 expect_to_scroll: false, 190 description: 'inverted range search' 191 }, 192 { 193 // Step 2.5.1.1 194 fragment: '#:~:text=quick,bro', 195 expect_to_scroll: false, 196 description: 'no suffix forces |end| to be end bounded' 197 }, 198 { 199 // Step 2.5.1.1 200 fragment: '#:~:text=quick,bro,-wn', 201 expect_to_scroll: true, 202 description: 'suffix means |end| need not be end bounded' 203 }, 204 { 205 // Step 2.5.1.2 206 fragment: '#:~:text=quick,ro,-wn', 207 expect_to_scroll: false, 208 description: '|end| must be start bounded' 209 }, 210 { 211 // Step 2.5.1.2 212 fragment: '#:~:text=bro,wn', 213 expect_to_scroll: false, 214 description: '|end| must be start bounded even if full range is word bounded' 215 }, 216 { 217 // Step 2.5.1.3 218 fragment: '#:~:text=quick,null', 219 expect_to_scroll: false, 220 description: 'non-existent |end|' 221 }, 222 { 223 // Step 2.5.1.4 224 fragment: '#:~:text=quick,jumped,-fox', 225 expect_to_scroll: false, 226 description: 'Range with preceeding suffix' 227 }, 228 { 229 // Step 2.5.3 230 fragment: '#:~:text=The-,quick,brown', 231 expect_to_scroll: true, 232 description: 'Match with no suffix' 233 }, 234 { 235 // Step 2.5.4 236 fragment: '#:~:text=The-,quick,fox,-brown', 237 expect_to_scroll: false, 238 description: 'Suffix comes before |end|' 239 }, 240 { 241 // Step 2.5.5 242 fragment: '#:~:text=Lorem-,Ipsum,Whitespace,-Dipsum', 243 expect_to_scroll: true, 244 description: 'Search invisible content between |end| and suffix' 245 }, 246 { 247 // Step 2.5.6 248 fragment: '#:~:text=quick,-bro', 249 expect_to_scroll: false, 250 description: 'Suffix must be end bounded' 251 }, 252 { 253 // Step 2.5.6 254 fragment: '#:~:text=qu,-ick', 255 expect_to_scroll: true, 256 description: 'Suffix need not be start bounded' 257 }, 258 { 259 // Step 2.5.7 260 fragment: '#:~:text=quick,-null', 261 expect_to_scroll: false, 262 description: 'Non-existent suffix' 263 }, 264 { 265 // Step 2.5.8 266 fragment: '#:~:text=quick,-fox', 267 expect_to_scroll: false, 268 description: 'Content appears between match and suffix' 269 }, 270 { 271 // Step 2.5.9 272 fragment: '#:~:text=match,-suffix2', 273 expect_to_scroll: true, 274 description: 'Non-matching suffix in first potential match' 275 }, 276 { 277 // Step 2.5.9 278 fragment: '#:~:text=prefix-,match,-suffix3', 279 expect_to_scroll: true, 280 description: 'Non-matching suffix search continues to prefix match' 281 }, 282 { 283 // Step 2.5.10 284 fragment: '#:~:text=prefix-,match,matchEnd,-suffix5', 285 expect_to_scroll: true, 286 description: 'Range end matches correct suffix' 287 }, 288 { 289 fragment: '#:~:text=Text%20with%20display:%20none', 290 expect_to_scroll: true, 291 description: '`start` element contains search-invisible text (display: none)' 292 }, 293 { 294 fragment: '#:~:text=Text%20with%20visibility:%20hidden%20as%20block%20boundary', 295 expect_to_scroll: false, 296 description: '`start` element contains hidden text, which is a block boundary' 297 }, 298 { 299 fragment: '#:~:text=Text%20with%20visibility:%20hidden%20as%20inline', 300 expect_to_scroll: true, 301 description: '`start` element contains hidden text which is not a block boundary' 302 }, 303 { 304 fragment: '#:~:text=Text%20with%20Iframe', 305 expect_to_scroll: true, 306 description: '`start` element contains search-invisible text (iframe)' 307 }, 308 { 309 fragment: '#:~:text=Text%20with%20image', 310 expect_to_scroll: true, 311 description: '`start` element contains search-invisible text (image)' 312 } 313 ]; 314 315 for (const test_case of test_cases) { 316 promise_test(t => new Promise((resolve, reject) => { 317 let key = token(); 318 319 test_driver.bless('Open a URL with a text fragment directive', () => { 320 window.open(`find-range-from-text-directive-target.html?key=${key}${test_case.fragment}`, '_blank', 'noopener'); 321 }); 322 323 fetchResults(key, resolve, reject); 324 }).then(data => { 325 const expectation_string = test_case.expect_to_scroll ? 'to scroll' : 'not to scroll'; 326 assert_equals(data.didScroll, test_case.expect_to_scroll, 327 `Expected ${expectation_string}`); 328 }), `${test_case.description}.`); 329 } 330 </script>