same-hash.html (4449B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Using the location interface to navigate to the same hash as the current one</title> 4 <link rel="help" href="https://github.com/whatwg/html/issues/7386"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 8 <iframe id="i" srcdoc="<div style='height: 200vh'></div><div id='te<st'></div>"></iframe> 9 10 <script type="module"> 11 setup({ explicit_done: true }); 12 await new Promise(r => window.onload = r); 13 14 for (const value of ["#te<st", "te<st", "#te%3Cst", "te%3Cst"]) { 15 promise_test(async t => { 16 t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); 17 assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); 18 19 i.contentWindow.location.hash = "te<st"; 20 await delayForFragmentNavigationScrolling(t); 21 22 assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); 23 24 i.contentWindow.scroll({ top: 0, behavior: "instant" }); 25 assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); 26 27 i.contentWindow.location.hash = value; 28 await delayForFragmentNavigationScrolling(t); 29 30 assert_equals(i.contentWindow.scrollY, 0, "Reassigning the same hash must not change the scroll position"); 31 }, `Using location.hash = "${value}" must not reset scroll position`); 32 } 33 34 // These don't canonicalize to the current value of location.hash; the post-parsing version of 35 // "te<st" is "te%3Cst", uppercase. 36 for (const value of ["#te%3cst", "te%3cst"]) { 37 promise_test(async t => { 38 t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); 39 assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); 40 41 i.contentWindow.location.hash = "te<st"; 42 await delayForFragmentNavigationScrolling(t); 43 44 assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); 45 46 i.contentWindow.scroll({ top: 0, behavior: "instant" }); 47 assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); 48 49 i.contentWindow.location.hash = value; 50 await delayForFragmentNavigationScrolling(t); 51 52 assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Reassigning the same-ish hash scrolls the iframe"); 53 }, `Using location.hash = "${value}" must reset scroll position`); 54 } 55 56 for (const value of ["about:srcdoc#te<st", "about:srcdoc#te%3cst", "about:srcdoc#te%3Cst"]) { 57 promise_test(async t => { 58 t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); 59 assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); 60 61 i.contentWindow.location.hash = "te<st"; 62 await delayForFragmentNavigationScrolling(t); 63 64 assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); 65 66 i.contentWindow.scroll({ top: 0, behavior: "instant" }); 67 assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); 68 69 i.contentWindow.location.href = value; 70 await delayForFragmentNavigationScrolling(t); 71 72 assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Setting href must scroll the iframe"); 73 }, `Using location.href = "${value}" must reset scroll position`); 74 75 promise_test(async t => { 76 t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); 77 assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); 78 79 i.contentWindow.location.hash = "te<st"; 80 await delayForFragmentNavigationScrolling(t); 81 82 assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); 83 84 i.contentWindow.scroll({ top: 0, behavior: "instant" }); 85 assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); 86 87 i.contentWindow.location.assign(value); 88 await delayForFragmentNavigationScrolling(t); 89 90 assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Setting href must scroll the iframe"); 91 }, `Using location.assign("${value}") must reset scroll position`); 92 } 93 94 function delayForFragmentNavigationScrolling(t) { 95 // Scroll behavior for fragment navigation is set to "auto" in the spec, so we can't guarantee it's instant. 96 // In practice 10 milliseconds seems to be enough. 97 return new Promise(r => t.step_timeout(r, 10)); 98 } 99 100 done(); 101 </script>