Commit 88d98fda authored by Nick Burris's avatar Nick Burris Committed by Commit Bot

Add more scroll to text WPTs

Adds more web platform tests for scroll to text:

- Combination of non-text directive and text directive
- Scroll second text directive into view if first doesn't match
- Matching shadow DOM
- Don't scroll to hidden text
- Text that requires a horizontal scroll into view
- Also fixed non-ASCII test case (and changed to Japanese example)

Change-Id: Id7e21a185897267dc565b19adc7bfdfb5fe70974
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1903624
Commit-Queue: Nick Burris <nburris@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714381}
parent 19f6b5e6
......@@ -3,7 +3,8 @@
<script>
function isInView(element) {
let rect = element.getBoundingClientRect();
return rect.top >= 0 && rect.top <= window.innerHeight;
return rect.top >= 0 && rect.top <= window.innerHeight
&& rect.left >= 0 && rect.left <= window.innerWidth;
}
function checkScroll() {
......@@ -22,6 +23,12 @@ function checkScroll() {
position = 'cross-node-context';
else if (isInView(document.getElementById('text-directive-parameters')))
position = 'text-directive-parameters';
else if (isInView(document.getElementById('shadow-parent')))
position = 'shadow-parent';
else if (isInView(document.getElementById('hidden')))
position = 'hidden';
else if (isInView(document.getElementById('horizontal-scroll')) && window.scrollX > 0)
position = 'horizontal-scroll';
bc.postMessage({ scrollPosition: position, href: window.location.href });
bc.close();
......@@ -29,40 +36,38 @@ function checkScroll() {
}
</script>
<style>
body {
height: 6200px;
.scroll-section {
/* 1000px margin on top and bottom so only one section can be in view. */
margin: 1000px 0px;
}
#element {
position: absolute;
top: 2000px;
#hidden {
visibility: hidden;
}
#text {
position: absolute;
top: 3000px;
#horizontal-scroll {
margin-left: 2000px;
}
#more-text {
position: absolute;
top: 4000px;
}
#cross-node-context {
position: absolute;
top: 5000px;
}
#text-directive-parameters {
position: absolute;
top: 6000px;
#display-none {
display: none;
}
</style>
<body onload="window.requestAnimationFrame(checkScroll)">
<div id="element">Element</div>
<p id="text">This is a test page !$'()*+./:;=?@_~ &,- &#x2665;</p>
<p id="more-text">More test page text</p>
<div id="cross-node-context">
<div id="element" class="scroll-section">Element</div>
<p id="text" class="scroll-section">This is a test page !$'()*+./:;=?@_~ &,- &#x30cd;&#x30b3;</p>
<p id="more-text" class="scroll-section">More test page text</p>
<div id="cross-node-context" class="scroll-section">
<div>
<p>prefix</p>
<p>test page</p>
</div>
<div><p>suffix</p></div>
</div>
<p id="text-directive-parameters">this,is,test,page</p>
<p id="text-directive-parameters" class="scroll-section">this,is,test,page</p>
<div id="shadow-parent" class="scroll-section"></div>
<script>
let shadow = document.getElementById("shadow-parent").attachShadow({mode: 'open'});
shadow.innerHTML = '<p>shadow text</p>';
</script>
<p id="hidden" class="scroll-section">hidden text</p>
<p id="horizontal-scroll" class="scroll-section">horizontally scrolled text</p>
<p id="display-none" class="scroll-section">display none</p>
</body>
......@@ -13,162 +13,207 @@ let test_cases = [
{
fragment: '#',
expect_position: 'top',
description: 'Empty hash'
description: 'Empty hash should scroll to top'
},
{
fragment: '#:~:text=this,is,test,page',
expect_position: 'top',
description: 'Text directive with invalid syntax, context terms without "-"'
description: 'Text directive with invalid syntax (context terms without "-") should not parse as a text directive'
},
{
fragment: '#element:~:directive',
expect_position: 'element',
description: 'Generic fragment directive with existing element fragment'
description: 'Generic fragment directive with existing element fragment should scroll to element'
},
{
fragment: '#:~:TEXT=test',
expect_position: 'top',
description: 'Uppercase TEXT directive should not parse as a text directive'
},
// Test exact text matching, with all combinations of context terms
{
fragment: '#:~:text=test',
expect_position: 'text',
description: 'Exact text with no context'
description: 'Exact text with no context should match text'
},
{
fragment: '#:~:text=this is a-,test',
expect_position: 'text',
description: 'Exact text with prefix'
description: 'Exact text with prefix should match text'
},
{
fragment: '#:~:text=test,-page',
expect_position: 'text',
description: 'Exact text with suffix'
description: 'Exact text with suffix should match text'
},
{
fragment: '#:~:text=this is a-,test,-page',
expect_position: 'text',
description: 'Exact text with prefix and suffix'
description: 'Exact text with prefix and suffix should match text'
},
// Test text range matching, with all combinations of context terms
{
fragment: '#:~:text=this,page',
expect_position: 'text',
description: 'Text range with no context'
description: 'Text range with no context should match text'
},
{
fragment: '#:~:text=this-,is,test',
expect_position: 'text',
description: 'Text range with prefix'
description: 'Text range with prefix should match text'
},
{
fragment: '#:~:text=this,test,-page',
expect_position: 'text',
description: 'Text range with suffix'
description: 'Text range with suffix should match text'
},
{
fragment: '#:~:text=this-,is,test,-page',
expect_position: 'text',
description: 'Text range with prefix and suffix'
description: 'Text range with prefix and suffix should match text'
},
// Test partially non-matching text ranges
{
fragment: '#:~:text=this,none',
expect_position: 'top',
description: 'Text range with non-matching endText'
description: 'Text range with non-matching endText should not match'
},
{
fragment: '#:~:text=none,page',
expect_position: 'top',
description: 'Text range with non-matching startText'
description: 'Text range with non-matching startText should not match'
},
// Test non-matching context terms
{
fragment: '#:~:text=this-,is,page,-none',
expect_position: 'top',
description: 'Text range with prefix and nonmatching suffix'
description: 'Text range with prefix and nonmatching suffix should not match'
},
{
fragment: '#:~:text=none-,this,test,-page',
expect_position: 'top',
description: 'Text range with nonmatching prefix and matching suffix'
description: 'Text range with nonmatching prefix and matching suffix should not match'
},
// Test percent encoded characters
{
fragment: '#:~:text=this%20is%20a%20test%20page',
expect_position: 'text',
description: 'Exact text with percent encoded spaces'
description: 'Exact text with percent encoded spaces should match text'
},
{
fragment: '#:~:text=test%20pag',
expect_position: 'top',
description: 'Non-whole-word exact text with spaces'
description: 'Non-whole-word exact text with spaces should not match'
},
{
fragment: '#:~:text=%26%2C%2D',
expect_position: 'text',
description: 'Fragment directive with percent encoded syntactical characters "&,-"'
description: 'Fragment directive with percent encoded syntactical characters "&,-" should match text'
},
{
fragment: '#:~:text=%2665',
fragment: '#:~:text=%E3%83%8D%E3%82%B3',
expect_position: 'text',
description: 'Fragment directive with percent encoded non-ASCII unicode character'
description: 'Fragment directive with percent encoded non-ASCII unicode character should match text'
},
{
fragment: '#:~:text=!$\'()*+./:;=?@_~',
expect_position: 'text',
description: 'Fragment directive with all TextMatchChars'
description: 'Fragment directive with all TextMatchChars should match text'
},
// Test multiple text directives
{
fragment: '#:~:text=this&text=test,page',
expect_position: 'text',
description: 'Multiple matching exact texts'
description: 'Multiple matching exact texts should match text'
},
{
fragment: '#:~:text=tes&text=age',
expect_position: 'top',
description: 'Multiple non-whole-word exact texts'
description: 'Multiple non-whole-word exact texts should not match'
},
{
fragment: '#:~:text=none&text=test%20page',
expect_position: 'text',
description: 'A non-matching text directive followed by a matching text directive should match and scroll into view the second text directive'
},
{
fragment: '#:~:text=test%20page&directive',
expect_position: 'text',
description: 'Text directive followed by non-text directive should match text'
},
{
fragment: '#:~:text=test&directive&text=page',
expect_position: 'text',
description: 'Multiple text directives and a non-text directive should match text'
},
// Test text directive behavior when there's an element fragment identifier
{
fragment: '#element:~:text=test',
expect_position: 'text',
description: 'Text directive with existing element fragment'
description: 'Text directive with existing element fragment should match and scroll into view text'
},
{
fragment: '#pagestate:~:text=test',
expect_position: 'text',
description: 'Text directive with nonexistent element fragment'
description: 'Text directive with nonexistent element fragment should match and scroll into view text'
},
{
fragment: '#element:~:text=nomatch',
expect_position: 'element',
description: 'Non-matching text directive with existing element fragment'
description: 'Non-matching text directive with existing element fragment should scroll to element'
},
{
fragment: '#pagestate:~:text=nomatch',
expect_position: 'top',
description: 'Non-matching text directive with nonexistent element fragment'
description: 'Non-matching text directive with nonexistent element fragment should not match and not scroll'
},
// Test ambiguous text matches disambiguated by context terms
{
fragment: '#:~:text=more-,test%20page',
expect_position: 'more-text',
description: 'Multiple match text directive disambiguated by prefix'
description: 'Multiple match text directive disambiguated by prefix should match the prefixed text'
},
{
fragment: '#:~:text=test%20page,-text',
expect_position: 'more-text',
description: 'Multiple match text directive disambiguated by suffix'
description: 'Multiple match text directive disambiguated by suffix should match the suffixed text'
},
{
fragment: '#:~:text=more-,test%20page,-text',
expect_position: 'more-text',
description: 'Multiple match text directive disambiguated by prefix and suffix'
description: 'Multiple match text directive disambiguated by prefix and suffix should match the text with the given context'
},
// Test context terms separated by node boundaries
{
fragment: '#:~:text=prefix-,test%20page,-suffix',
expect_position: 'cross-node-context',
description: 'Text directive with context terms separated by node boundaries'
description: 'Text directive should match when context terms are separated by node boundaries'
},
// Test text directive within shadow DOM
{
fragment: '#:~:text=shadow%20text',
expect_position: 'shadow-parent',
description: 'Text directive should match text within shadow DOM'
},
// Test text directive within hidden and display none elements. These cases should not scroll into
// view, but still "match" in that they should be highlighted or otherwise visibly indicated
// if they were to become visible.
{
fragment: '#:~:text=hidden%20text',
expect_position: 'top',
description: 'Text directive should not scroll to hidden text'
},
{
fragment: '#:~:text=display%20none',
expect_position: 'top',
description: 'Text directive should not scroll to display none text'
},
// Test horizontal scroll into view
{
fragment: '#:~:text=horizontally%20scrolled%20text',
expect_position: 'horizontal-scroll',
description: 'Text directive should horizontally scroll into view'
}
];
for (const test_case of test_cases) {
......@@ -185,7 +230,7 @@ for (const test_case of test_cases) {
assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
assert_equals(data.scrollPosition, test_case.expect_position,
`Expected ${test_case.fragment} (${test_case.description}) to scroll to ${test_case.expect_position}.`);
}), `Test navigation with fragment: ${test_case.description}`);
}), `Test navigation with fragment: ${test_case.description}.`);
}
promise_test(t => new Promise(resolve => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment