summaryrefslogtreecommitdiffstats
path: root/toolkit/modules/tests/xpcshell/test_FinderIterator.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/modules/tests/xpcshell/test_FinderIterator.js')
-rw-r--r--toolkit/modules/tests/xpcshell/test_FinderIterator.js444
1 files changed, 444 insertions, 0 deletions
diff --git a/toolkit/modules/tests/xpcshell/test_FinderIterator.js b/toolkit/modules/tests/xpcshell/test_FinderIterator.js
new file mode 100644
index 0000000000..fcbe97ba5f
--- /dev/null
+++ b/toolkit/modules/tests/xpcshell/test_FinderIterator.js
@@ -0,0 +1,444 @@
+const { FinderIterator } = ChromeUtils.importESModule(
+ "resource://gre/modules/FinderIterator.sys.mjs"
+);
+
+let finderIterator = new FinderIterator();
+
+var gFindResults = [];
+// Stub the method that instantiates nsIFind and does all the interaction with
+// the docShell to be searched through.
+finderIterator._iterateDocument = function* (word, window, finder) {
+ for (let range of gFindResults) {
+ yield range;
+ }
+};
+
+finderIterator._rangeStartsInLink = fakeRange => fakeRange.startsInLink;
+
+function FakeRange(textContent, startsInLink = false) {
+ this.startContainer = {};
+ this.startsInLink = startsInLink;
+ this.toString = () => textContent;
+}
+
+var gMockWindow = {
+ setTimeout(cb, delay) {
+ Cc["@mozilla.org/timer;1"]
+ .createInstance(Ci.nsITimer)
+ .initWithCallback(cb, delay, Ci.nsITimer.TYPE_ONE_SHOT);
+ },
+};
+
+var gMockFinder = {
+ _getWindow() {
+ return gMockWindow;
+ },
+};
+
+function prepareIterator(findText, rangeCount) {
+ gFindResults = [];
+ for (let i = rangeCount; --i >= 0; ) {
+ gFindResults.push(new FakeRange(findText));
+ }
+}
+
+add_task(async function test_start() {
+ let findText = "test";
+ let rangeCount = 300;
+ prepareIterator(findText, rangeCount);
+
+ let count = 0;
+ await finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ Assert.equal(range.toString(), findText, "Text content should match");
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ });
+
+ Assert.equal(rangeCount, count, "Amount of ranges yielded should match!");
+ Assert.ok(!finderIterator.running, "Running state should match");
+ Assert.equal(
+ finderIterator._previousRanges.length,
+ rangeCount,
+ "Ranges cache should match"
+ );
+
+ finderIterator.reset();
+});
+
+add_task(async function test_subframes() {
+ let findText = "test";
+ let rangeCount = 300;
+ prepareIterator(findText, rangeCount);
+
+ let count = 0;
+ await finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ Assert.equal(range.toString(), findText, "Text content should match");
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ useSubFrames: true,
+ });
+
+ Assert.equal(rangeCount, count, "Amount of ranges yielded should match!");
+ Assert.ok(!finderIterator.running, "Running state should match");
+ Assert.equal(
+ finderIterator._previousRanges.length,
+ rangeCount,
+ "Ranges cache should match"
+ );
+
+ finderIterator.reset();
+});
+
+add_task(async function test_valid_arguments() {
+ let findText = "foo";
+ let rangeCount = 20;
+ prepareIterator(findText, rangeCount);
+
+ let count = 0;
+
+ await finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ });
+
+ let params = finderIterator._previousParams;
+ Assert.ok(!params.linksOnly, "Default for linksOnly is false");
+ Assert.ok(!params.useCache, "Default for useCache is false");
+ Assert.equal(params.word, findText, "Words should match");
+
+ count = 0;
+ Assert.throws(
+ () =>
+ finderIterator.start({
+ entireWord: false,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ }),
+ /Missing required option 'caseSensitive'/,
+ "Should throw when missing an argument"
+ );
+ finderIterator.reset();
+
+ Assert.throws(
+ () =>
+ finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ word: findText,
+ }),
+ /Missing required option 'matchDiacritics'/,
+ "Should throw when missing an argument"
+ );
+ finderIterator.reset();
+
+ Assert.throws(
+ () =>
+ finderIterator.start({
+ caseSensitive: false,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ }),
+ /Missing required option 'entireWord'/,
+ "Should throw when missing an argument"
+ );
+ finderIterator.reset();
+
+ Assert.throws(
+ () =>
+ finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ }),
+ /Missing required option 'finder'/,
+ "Should throw when missing an argument"
+ );
+ finderIterator.reset();
+
+ Assert.throws(
+ () =>
+ finderIterator.start({
+ caseSensitive: true,
+ entireWord: false,
+ finder: gMockFinder,
+ matchDiacritics: false,
+ word: findText,
+ }),
+ /Missing valid, required option 'listener'/,
+ "Should throw when missing an argument"
+ );
+ finderIterator.reset();
+
+ Assert.throws(
+ () =>
+ finderIterator.start({
+ caseSensitive: false,
+ entireWord: true,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ }),
+ /Missing required option 'word'/,
+ "Should throw when missing an argument"
+ );
+ finderIterator.reset();
+
+ Assert.equal(count, 0, "No ranges should've been counted");
+});
+
+add_task(async function test_stop() {
+ let findText = "bar";
+ let rangeCount = 120;
+ prepareIterator(findText, rangeCount);
+
+ let count = 0;
+ let whenDone = finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ });
+
+ finderIterator.stop();
+
+ await whenDone;
+
+ Assert.equal(count, 0, "Number of ranges should be 0");
+
+ finderIterator.reset();
+});
+
+add_task(async function test_reset() {
+ let findText = "tik";
+ let rangeCount = 142;
+ prepareIterator(findText, rangeCount);
+
+ let count = 0;
+ let whenDone = finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ });
+
+ Assert.ok(finderIterator.running, "Yup, running we are");
+ Assert.equal(count, 0, "Number of ranges should match 0");
+ Assert.equal(
+ finderIterator.ranges.length,
+ 0,
+ "Number of ranges should match 0"
+ );
+
+ finderIterator.reset();
+
+ Assert.ok(!finderIterator.running, "Nope, running we are not");
+ Assert.equal(finderIterator.ranges.length, 0, "No ranges after reset");
+ Assert.equal(
+ finderIterator._previousRanges.length,
+ 0,
+ "No ranges after reset"
+ );
+
+ await whenDone;
+
+ Assert.equal(count, 0, "Number of ranges should match 0");
+});
+
+add_task(async function test_parallel_starts() {
+ let findText = "tak";
+ let rangeCount = 2143;
+ prepareIterator(findText, rangeCount);
+
+ // Start off the iterator.
+ let count = 0;
+ let whenDone = finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ });
+
+ await new Promise(resolve => gMockWindow.setTimeout(resolve, 100));
+ Assert.ok(finderIterator.running, "We ought to be running here");
+
+ let count2 = 0;
+ let whenDone2 = finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count2;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ });
+
+ // Let the iterator run for a little while longer before we assert the world.
+ await new Promise(resolve => gMockWindow.setTimeout(resolve, 10));
+ finderIterator.stop();
+
+ Assert.ok(!finderIterator.running, "Stop means stop");
+
+ await whenDone;
+ await whenDone2;
+
+ Assert.greater(
+ count,
+ finderIterator.kIterationSizeMax,
+ "At least one range should've been found"
+ );
+ Assert.less(count, rangeCount, "Not all ranges should've been found");
+ Assert.greater(
+ count2,
+ finderIterator.kIterationSizeMax,
+ "At least one range should've been found"
+ );
+ Assert.less(count2, rangeCount, "Not all ranges should've been found");
+
+ Assert.equal(
+ count2,
+ count,
+ "The second start was later, but should have caught up"
+ );
+
+ finderIterator.reset();
+});
+
+add_task(async function test_allowDistance() {
+ let findText = "gup";
+ let rangeCount = 20;
+ prepareIterator(findText, rangeCount);
+
+ // Start off the iterator.
+ let count = 0;
+ let whenDone = finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count;
+ },
+ },
+ matchDiacritics: false,
+ word: findText,
+ });
+
+ let count2 = 0;
+ let whenDone2 = finderIterator.start({
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count2;
+ },
+ },
+ matchDiacritics: false,
+ word: "gu",
+ });
+
+ let count3 = 0;
+ let whenDone3 = finderIterator.start({
+ allowDistance: 1,
+ caseSensitive: false,
+ entireWord: false,
+ finder: gMockFinder,
+ listener: {
+ onIteratorRangeFound(range) {
+ ++count3;
+ },
+ },
+ matchDiacritics: false,
+ word: "gu",
+ });
+
+ await Promise.all([whenDone, whenDone2, whenDone3]);
+
+ Assert.equal(
+ count,
+ rangeCount,
+ "The first iterator invocation should yield all results"
+ );
+ Assert.equal(
+ count2,
+ 0,
+ "The second iterator invocation should yield _no_ results"
+ );
+ Assert.equal(
+ count3,
+ rangeCount,
+ "The first iterator invocation should yield all results"
+ );
+
+ finderIterator.reset();
+});