<!
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>nt</
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");
// nsFind should be able to find text inside hidden=until-found
// or closed <
details> elements.
// Note: nsFind itself does not trigger the reveal algorithm; that is the
// responsibility of the caller (e.g., find-in-page, nsTypeAheadFind).
//
https:// style='color:red'>html.spec.whatwg.org/#attr-hidden-until-found
assertFound(document.body, "hidden until found");
assertNotFound(document.body, "hidden because of content-visibility: hidden outside of hidden=until-found");
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}");
// Bug 1951607: Text inside <option> elements within <optgroup> in a <select>
// should be findable.
var selectElement = document.getElementById("select-with-optgroup");
assertFound(selectElement, "optgroup");
assertFound(selectElement, "OptionInOptGroup");
// 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>nt</b>o</p>
<p id="quotes">"straight" and “curly” and ‘didn't’ and 'doesn’t'</p>
<p id="nullcharsnative">native null0;</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>
<select id="select-with-optgroup" multiple>
<optgroup label="optgroup">
<option>OptionInOptGroup</option>
</optgroup>
</select>
<pre id="test">
</pre>
</body>
</html>