diff options
Diffstat (limited to 'toolkit/modules/tests/xpcshell/test_FinderIterator.js')
-rw-r--r-- | toolkit/modules/tests/xpcshell/test_FinderIterator.js | 444 |
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(); +}); |