489 lines
17 KiB
HTML
489 lines
17 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<!--
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=202251
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=450048
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=812837
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=969980
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1589786
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1611568
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1649187
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1699599
|
|
-->
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Test for nsFind::Find()</title>
|
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
|
|
|
<script type="application/javascript">
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
|
|
async function runTests() {
|
|
// Check nsFind class and its nsIFind interface.
|
|
|
|
// Inject some text that we'll search for later.
|
|
const NULL_CHARACTER = "\0";
|
|
const INJECTED_NULL_TEXT = "injected null\0";
|
|
const nullcharsinjected = document.getElementById("nullcharsinjected");
|
|
const nulltextnode = document.createTextNode(INJECTED_NULL_TEXT);
|
|
nullcharsinjected.appendChild(nulltextnode);
|
|
|
|
// Take steps to ensure that the frame is created for the newly added
|
|
// nulltextnode. Our find code is dependent upon finding visible frames.
|
|
// One way to ensure the frame exists is to ask for its bounds.
|
|
const injectionBounds = nullcharsinjected.getBoundingClientRect();
|
|
ok(injectionBounds, "Got a bounding rect for the injected text container.");
|
|
|
|
var rf = SpecialPowers.Cc["@mozilla.org/embedcomp/rangefind;1"]
|
|
.getService(SpecialPowers.Ci.nsIFind);
|
|
|
|
var display = window.document.getElementById("display");
|
|
var testNode = window.document.getElementById("test");
|
|
var searchRange = window.document.createRange();
|
|
searchRange.setStart(display, 0);
|
|
searchRange.setEnd(testNode, testNode.childNodes.length);
|
|
var startPt = searchRange;
|
|
var endPt = searchRange;
|
|
|
|
var searchValue, retRange;
|
|
|
|
rf.findBackwards = false;
|
|
|
|
rf.caseSensitive = false;
|
|
rf.matchDiacritics = false;
|
|
rf.entireWord = false;
|
|
|
|
searchValue = "TexT";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "λογος";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "유";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found (not caseSensitive)");
|
|
|
|
searchValue = "కె";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found (not caseSensitive)");
|
|
|
|
searchValue = "𑂥";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "istanbul";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "wroclaw";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "goteborg";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "degrees k";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "≠";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found (not caseSensitive)");
|
|
|
|
searchValue = "guahe";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "g̃uah̰e";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "𐐸𐐯𐑊𐐬";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (not caseSensitive)");
|
|
|
|
searchValue = "東京駅"
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found");
|
|
|
|
rf.matchDiacritics = true;
|
|
|
|
searchValue = "λογος";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found (matchDiacritics on)");
|
|
|
|
searchValue = "g̃uahe";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (matchDiacritics on)");
|
|
|
|
searchValue = "guahe";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found (matchDiacritics on)");
|
|
|
|
rf.caseSensitive = true;
|
|
|
|
searchValue = "TexT";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found (caseSensitive)");
|
|
|
|
searchValue = "text";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found");
|
|
|
|
// Matches |i<b>n­t</b>o|.
|
|
searchValue = "into";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found");
|
|
|
|
// Matches inside |search|.
|
|
searchValue = "ear";
|
|
retRange = rf.Find(searchValue, searchRange, startPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found");
|
|
|
|
// Set new start point (to end of last search).
|
|
let newStartPt = retRange.endContainer.ownerDocument.createRange();
|
|
newStartPt.setStart(retRange.endContainer, retRange.endOffset);
|
|
newStartPt.setEnd(retRange.endContainer, retRange.endOffset);
|
|
|
|
searchValue = "t";
|
|
retRange = rf.Find(searchValue, searchRange, newStartPt, endPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found (forward)");
|
|
|
|
searchValue = "the";
|
|
retRange = rf.Find(searchValue, searchRange, newStartPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found (forward)");
|
|
|
|
rf.findBackwards = true;
|
|
|
|
// searchValue = "the";
|
|
retRange = rf.Find(searchValue, searchRange, newStartPt, endPt);
|
|
ok(!retRange, "\"" + searchValue + "\" found in second sub range (backward)");
|
|
|
|
retRange = rf.Find(searchValue, searchRange, startPt, newStartPt);
|
|
ok(retRange, "\"" + searchValue + "\" not found in first sub range (backward)");
|
|
|
|
// Curly quotes and straight quotes should match.
|
|
|
|
rf.matchDiacritics = false;
|
|
rf.findBackwards = false;
|
|
|
|
function find(node, value) {
|
|
var range = document.createRange();
|
|
range.setStart(node, 0);
|
|
range.setEnd(node, node.childNodes.length);
|
|
return rf.Find(value, range, range, range);
|
|
}
|
|
|
|
function assertFound(node, value) {
|
|
ok(find(node, value), "\"" + value + "\" should be found");
|
|
}
|
|
|
|
function assertNotFound(node, value) {
|
|
ok(!find(node, value), "\"" + value + "\" should not be found");
|
|
}
|
|
|
|
var quotes = document.getElementById("quotes");
|
|
|
|
assertFound(quotes, "\"straight\"");
|
|
assertFound(quotes, "\u201Cstraight\u201D");
|
|
|
|
assertNotFound(quotes, "'straight'");
|
|
assertNotFound(quotes, "\u2018straight\u2019");
|
|
assertNotFound(quotes, "\u2019straight\u2018");
|
|
assertNotFound(quotes, ".straight.");
|
|
|
|
assertFound(quotes, "\"curly\"");
|
|
assertFound(quotes, "\u201Ccurly\u201D");
|
|
|
|
assertNotFound(quotes, "'curly'");
|
|
assertNotFound(quotes, "\u2018curly\u2019");
|
|
assertNotFound(quotes, ".curly.");
|
|
|
|
assertFound(quotes, "didn't");
|
|
assertFound(quotes, "didn\u2018t");
|
|
assertFound(quotes, "didn\u2019t");
|
|
|
|
assertNotFound(quotes, "didnt");
|
|
assertNotFound(quotes, "didn t");
|
|
assertNotFound(quotes, "didn.t");
|
|
|
|
assertFound(quotes, "'didn't'");
|
|
assertFound(quotes, "'didn\u2018t'");
|
|
assertFound(quotes, "'didn\u2019t'");
|
|
assertFound(quotes, "\u2018didn't\u2019");
|
|
assertFound(quotes, "\u2019didn't\u2018");
|
|
assertFound(quotes, "\u2018didn't\u2018");
|
|
assertFound(quotes, "\u2019didn't\u2019");
|
|
assertFound(quotes, "\u2018didn\u2019t\u2019");
|
|
assertFound(quotes, "\u2019didn\u2018t\u2019");
|
|
assertFound(quotes, "\u2018didn\u2019t\u2018");
|
|
|
|
assertNotFound(quotes, "\"didn't\"");
|
|
assertNotFound(quotes, "\u201Cdidn't\u201D");
|
|
|
|
assertFound(quotes, "doesn't");
|
|
assertFound(quotes, "doesn\u2018t");
|
|
assertFound(quotes, "doesn\u2019t");
|
|
|
|
assertNotFound(quotes, "doesnt");
|
|
assertNotFound(quotes, "doesn t");
|
|
assertNotFound(quotes, "doesn.t");
|
|
|
|
assertFound(quotes, "'doesn't'");
|
|
assertFound(quotes, "'doesn\u2018t'");
|
|
assertFound(quotes, "'doesn\u2019t'");
|
|
assertFound(quotes, "\u2018doesn't\u2019");
|
|
assertFound(quotes, "\u2019doesn't\u2018");
|
|
assertFound(quotes, "\u2018doesn't\u2018");
|
|
assertFound(quotes, "\u2019doesn't\u2019");
|
|
assertFound(quotes, "\u2018doesn\u2019t\u2019");
|
|
assertFound(quotes, "\u2019doesn\u2018t\u2019");
|
|
assertFound(quotes, "\u2018doesn\u2019t\u2018");
|
|
|
|
assertNotFound(quotes, "\"doesn't\"");
|
|
assertNotFound(quotes, "\u201Cdoesn't\u201D");
|
|
|
|
// Curly quotes and straight quotes should not match.
|
|
rf.matchDiacritics = true;
|
|
|
|
assertFound(quotes, "\"straight\"");
|
|
assertNotFound(quotes, "\u201Cstraight\u201D");
|
|
|
|
assertNotFound(quotes, "\"curly\"");
|
|
assertFound(quotes, "\u201Ccurly\u201D");
|
|
|
|
assertFound(quotes, "\u2018didn't\u2019");
|
|
assertNotFound(quotes, "'didn't'");
|
|
|
|
assertFound(quotes, "'doesn\u2019t'");
|
|
assertNotFound(quotes, "'doesn\u2018t'");
|
|
assertNotFound(quotes, "'doesn't'");
|
|
|
|
// Embedded strings containing null characters can't be found, because
|
|
// the HTML parser converts them to \ufffd, which is the replacement
|
|
// character.
|
|
const nullcharsnative = document.getElementById("nullcharsnative");
|
|
assertFound(nullcharsnative, "native null\ufffd");
|
|
|
|
// Injected strings containing null characters can be found.
|
|
assertFound(nullcharsinjected, NULL_CHARACTER);
|
|
assertFound(nullcharsinjected, INJECTED_NULL_TEXT);
|
|
|
|
// Content skipped via content-visibility can't be found.
|
|
assertNotFound(quotes, "Tardigrade");
|
|
assertNotFound(quotes, "Amoeba");
|
|
|
|
// hidden=until-found content is found
|
|
// https://html.spec.whatwg.org/#attr-hidden-until-found
|
|
const hiddenUntilFound = document.querySelector("#hidden-until-found");
|
|
// Create a promise that resolves when the beforematch event fires.
|
|
const beforematchPromise = new Promise(resolve => {
|
|
hiddenUntilFound.onbeforematch = () => resolve();
|
|
});
|
|
is(
|
|
getComputedStyle(hiddenUntilFound).contentVisibility,
|
|
"hidden",
|
|
"hidden=until-found content has content-visibility: hidden before being found"
|
|
);
|
|
assertFound(document.body, "hidden until found");
|
|
|
|
await beforematchPromise;
|
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
|
|
is(
|
|
getComputedStyle(hiddenUntilFound).contentVisibility,
|
|
"visible",
|
|
"hidden=until-found content has content-visibility: visible after being found"
|
|
);
|
|
|
|
// https://html.spec.whatwg.org/#interaction-with-details-and-hidden=until-found
|
|
const hiddenHiddenUntilFound = document.querySelector("div#hidden-until-found-inside-hidden");
|
|
hiddenHiddenUntilFound.onbeforematch = () => ok(
|
|
false,
|
|
"Beforematch must not be fired for a hidden=until-found element which is inside a content-visibility:hidden element."
|
|
);
|
|
assertNotFound(document.body, "hidden because of content-visibility: hidden outside of hidden=until-found");
|
|
|
|
const nestedHiddenInHiddenUntilFound = document.querySelector("div#hidden-until-found-with-inner-hidden");
|
|
nestedHiddenInHiddenUntilFound.onbeforematch = () => ok(
|
|
false,
|
|
"Beforematch must not be fired for a hidden=until-found element if the matched content is content-visibility:hidden"
|
|
);
|
|
assertNotFound(document.body, "nested hidden block should not be found");
|
|
assertNotFound(document.body, "nested visibility:hidden should not be found");
|
|
|
|
assertNotFound(document.body, "hidden content in details");
|
|
assertFound(document.body, "auto-expanding details");
|
|
assertNotFound(document.body, "hidden details from outer node");
|
|
|
|
// Simple checks for behavior of the entireWord option.
|
|
var entireWord = document.getElementById("entireWord");
|
|
rf.entireWord = true;
|
|
assertFound(entireWord, "one");
|
|
assertNotFound(entireWord, "on");
|
|
assertFound(entireWord, "(one)");
|
|
assertFound(entireWord, "two");
|
|
assertFound(entireWord, "[two]");
|
|
assertFound(entireWord, "[three]");
|
|
assertFound(entireWord, "foo");
|
|
assertFound(entireWord, "-foo");
|
|
assertFound(entireWord, "bar");
|
|
assertFound(entireWord, "-bar");
|
|
assertNotFound(entireWord, "-fo");
|
|
assertNotFound(entireWord, "-ba");
|
|
|
|
rf.entireWord = false;
|
|
assertFound(entireWord, "on");
|
|
assertFound(entireWord, "-fo");
|
|
assertFound(entireWord, "-ba");
|
|
|
|
// Searching in elements with display: table-*, bug 1645990
|
|
var table = document.getElementById("tabular");
|
|
assertFound(table, "One");
|
|
assertFound(table, "TwoThree"); // across adjacent cells
|
|
assertNotFound(table, "wordsanother"); // not across rows
|
|
rf.entireWord = true;
|
|
assertNotFound(table, "One"); // because nothing separates it from next cell
|
|
assertFound(table, "several");
|
|
assertFound(table, "whole");
|
|
assertFound(table, "words");
|
|
rf.entireWord = false;
|
|
|
|
// Bug 1943846: Searching for U+2000D should not match space.
|
|
var nonspace = document.getElementById("nonspace");
|
|
assertFound(nonspace, "\u{2000D}");
|
|
assertFound(nonspace, "\u{10000A}");
|
|
assertNotFound(nonspace, "\u{3000D}");
|
|
assertNotFound(nonspace, "\u{3000A}");
|
|
|
|
var space = document.getElementById("space");
|
|
assertFound(space, " ");
|
|
assertFound(space, "\n");
|
|
assertFound(space, "\r");
|
|
assertFound(space, "\t");
|
|
assertFound(space, "\u00A0");
|
|
assertNotFound(space, "\u{2000D}");
|
|
assertNotFound(space, "\u{10000A}");
|
|
assertNotFound(space, "\u{3000D}");
|
|
assertNotFound(space, "\u{3000A}");
|
|
|
|
// Do these test at the end since they trigger failure screenshots in
|
|
// the test harness, and we want as much information as possible about
|
|
// any OTHER tests that may have already failed.
|
|
|
|
// Check |null| detection on |aSearchRange| parameter.
|
|
try {
|
|
rf.Find("", null, startPt, endPt);
|
|
|
|
ok(false, "Missing NS_ERROR_ILLEGAL_VALUE exception");
|
|
} catch (e) {
|
|
let wrappedError = SpecialPowers.wrap(e);
|
|
if (wrappedError.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE) {
|
|
ok(true, null);
|
|
} else {
|
|
throw wrappedError;
|
|
}
|
|
}
|
|
|
|
// Check |null| detection on |aStartPoint| parameter.
|
|
try {
|
|
rf.Find("", searchRange, null, endPt);
|
|
|
|
ok(false, "Missing NS_ERROR_ILLEGAL_VALUE exception");
|
|
} catch (e) {
|
|
let wrappedError = SpecialPowers.wrap(e);
|
|
if (wrappedError.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE) {
|
|
ok(true, null);
|
|
} else {
|
|
throw wrappedError;
|
|
}
|
|
}
|
|
|
|
// Check |null| detection on |aEndPoint| parameter.
|
|
try {
|
|
rf.Find("", searchRange, startPt, null);
|
|
|
|
ok(false, "Missing NS_ERROR_ILLEGAL_VALUE exception");
|
|
} catch (e) {
|
|
let wrappedError = SpecialPowers.wrap(e);
|
|
if (wrappedError.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE) {
|
|
ok(true, null);
|
|
} else {
|
|
throw wrappedError;
|
|
}
|
|
}
|
|
|
|
SimpleTest.finish();
|
|
}
|
|
</script>
|
|
<style>
|
|
#tabular { display: table; }
|
|
#tabular div { display: table-row; }
|
|
#tabular div div { display: table-cell; }
|
|
</style>
|
|
</head>
|
|
<body onload="runTests()">
|
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450048">Mozilla Bug 450048</a>
|
|
<p id="display">This is the text to search i<b>n­t</b>o</p>
|
|
<p id="quotes">"straight" and “curly” and ‘didn't’ and 'doesn’t'</p>
|
|
<p id="nullcharsnative">native null�</p>
|
|
<p id="nullcharsinjected"></p>
|
|
<p id="greek">ΛΌΓΟΣ</p>
|
|
<p id="korean">위</p>
|
|
<p id="telugu">కై</p>
|
|
<p id="kaithi">𑂫</p>
|
|
<p id="turkish">İstanbul</p>
|
|
<p id="polish">Wrocław</p>
|
|
<p id="norwegian">Gøteborg</p>
|
|
<p id="kelvin">degrees K</p>
|
|
<p id="math">=</p>
|
|
<p id="guarani">G̃uahe</p>
|
|
<p id="deseret">𐐐𐐯𐑊𐐬 𐐶𐐯𐑉𐑊𐐼!</p>
|
|
<p id="ruby"><ruby>東<rt>とう</rt></ruby><ruby>京<rt>きょう</ruby>駅</p>
|
|
<div id="content-visibility-hidden" style="content-visibility: hidden">
|
|
Tardigrade
|
|
<div>Amoeba</div>
|
|
</div>
|
|
<div id="hidden-until-found" hidden="until-found">hidden <span>until</span> found</div>
|
|
<div style="content-visibility: hidden;">
|
|
<div id="hidden-until-found-inside-hidden" hidden="until-found">
|
|
hidden because of content-visibility: hidden outside of hidden=until-found
|
|
</div>
|
|
</div>
|
|
<div id="hidden-until-found-with-inner-hidden" hidden="until-found">
|
|
<div style="content-visibility: hidden;">
|
|
nested hidden block should not be found
|
|
</div>
|
|
<div style="visibility: hidden;">nested visibility:hidden should not be found</div>
|
|
</div>
|
|
<details>
|
|
<summary>Content below should be found</summary>
|
|
auto-expanding details
|
|
<div style="content-visibility: hidden;">hidden content in details</div>
|
|
</details>
|
|
<div style="content-visibility: hidden;">
|
|
<details>
|
|
<summary>Invisible details</summary>
|
|
hidden details from outer node
|
|
</details>
|
|
</div>
|
|
<div id="entireWord"><p>(one)</p><p>[two] [three]</p><p>-foo -bar</p></div>
|
|
<div id="content" style="display: none">
|
|
|
|
</div>
|
|
<div id="tabular">
|
|
<div><div>One</div><div>Two</div><div>Three</div></div>
|
|
<div><div></div><div></div><div>several whole words</div></div>
|
|
<div><div>one</div><div>more</div><div>row</div></div>
|
|
</div>
|
|
<p id="nonspace">𠀍􀀊</p>
|
|
<p id="space"> <br> </p>
|
|
<pre id="test">
|
|
</pre>
|
|
</body>
|
|
</html>
|