Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

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* () {
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() {
++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() {
++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() {
++count;
},
},
word: findText,
}),
/Missing required option 'matchDiacritics'/,
"Should throw when missing an argument"
);
finderIterator.reset();
Assert.throws(
() =>
finderIterator.start({
caseSensitive: false,
listener: {
onIteratorRangeFound() {
++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() {
++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() {
++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() {
++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() {
++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() {
++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() {
++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() {
++count;
},
},
matchDiacritics: false,
word: findText,
});
let count2 = 0;
let whenDone2 = finderIterator.start({
caseSensitive: false,
entireWord: false,
finder: gMockFinder,
listener: {
onIteratorRangeFound() {
++count2;
},
},
matchDiacritics: false,
word: "gu",
});
let count3 = 0;
let whenDone3 = finderIterator.start({
allowDistance: 1,
caseSensitive: false,
entireWord: false,
finder: gMockFinder,
listener: {
onIteratorRangeFound() {
++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();
});