blob: 696734b663d2cbd49adbb6a2a400d0747be5ebc6 [file] [edit]
<!DOCTYPE html>
<title>Percent-encoding in a text directive</title>
<meta charset=utf-8>
<link rel="help" href="https://wicg.github.io/ScrollToTextFragment/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/common/utils.js"></script>
<script src="stash.js"></script>
<script src="resources/util.js"></script>
<style>
.target {
margin-top: 2000px;
margin-bottom: 2000px;
}
</style>
<script>
const params = new URLSearchParams(location.search);
const is_popup = params.has('key');
// This test opens a popup to this document which invokes a text directive. The
// popup checks the result of navigating the text directive and communicates it
// back to the original page via Stash (since text fragments require noopener).
if (is_popup) {
const key = params.get('key');
function sendResult() {
let result = 'unknown';
if (window.scrollY == 0)
result = 'noscroll';
else {
for (let target of document.querySelectorAll('.target')) {
if (isInViewport(target)) {
result = target.id;
break;
}
}
}
stashResultsThenClose(key, result);
}
// Ensure two animation frames on load to test the fallback to element anchor,
// which gets queued for the next frame if the text fragment is not found.
onload = () => { requestAnimationFrame( () => requestAnimationFrame(sendResult) ); };
} else {
let test_cases = [
{
fragment: '#:~:text=%25',
expect: 'singlepercent',
description: 'Percent-encoded "%" char.'
},
{
fragment: '#:~:text=%',
expect: 'noscroll',
description: 'Percent char without hex digits is invalid.'
},
{
fragment: '#:~:text=%%',
expect: 'noscroll',
description: 'Percent char followed by percent char is invalid.'
},
{
fragment: '#:~:text=%F',
expect: 'noscroll',
description: 'Single digit percent-encoding is invalid.'
},
{
fragment: '#:~:text=%25F',
expect: 'percentf',
description: 'Percent-encoding limited to two digits.'
},
{
fragment: '#:~:text=%25%25F',
expect: 'doublepercentf',
description: 'Percent-encoded "%%F"'
},
{
fragment: '#:~:text=%E2%9C%85',
expect: 'checkmark',
description: 'Percent-encoding multibyte codepoint (CHECKMARK).'
},
];
for (const test_case of test_cases) {
promise_test(t => new Promise((resolve, reject) => {
let key = token();
test_driver.bless('Open a URL with a text fragment directive', () => {
window.open(`${location.href}?key=${key}${test_case.fragment}`, '_blank', 'noopener');
});
fetchResults(key, resolve, reject);
}).then(result => {
assert_equals(result, test_case.expect);
}), `Test navigation with fragment: ${test_case.description}.`);
}
}
</script>
<p class="target" id="singlepercent">
%
</p>
<p class="target" id="doublepercent">
%%
</p>
<p class="target" id="percentf">
%F
</p>
<p class="target" id="doublepercentf">
%%f
</p>
<p class="target" id="checkmark">
<!-- U+2705 WHITE HEAVY CHECK MARK - UTF-8 percent encoding: %E2%9C%85 -->
&#x2705;
</p>
<p class="target" id="helloworld">
Hello world
</p>