/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ // See also browser/base/content/test/newtab/. const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; Cu.import("resource://gre/modules/NewTabUtils.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); function run_test() { run_next_test(); } add_test(function multipleProviders() { // Make each provider generate NewTabUtils.links.maxNumLinks links to check // that no more than maxNumLinks are actually returned in the merged list. let evenLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks, 2); let evenProvider = new TestProvider(done => done(evenLinks)); let oddLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks - 1, 2); let oddProvider = new TestProvider(done => done(oddLinks)); NewTabUtils.initWithoutProviders(); NewTabUtils.links.addProvider(evenProvider); NewTabUtils.links.addProvider(oddProvider); // This is sync since the providers' getLinks are sync. NewTabUtils.links.populateCache(function () {}, false); let links = NewTabUtils.links.getLinks(); let expectedLinks = makeLinks(NewTabUtils.links.maxNumLinks, 2 * NewTabUtils.links.maxNumLinks, 1); do_check_eq(links.length, NewTabUtils.links.maxNumLinks); do_check_links(links, expectedLinks); NewTabUtils.links.removeProvider(evenProvider); NewTabUtils.links.removeProvider(oddProvider); run_next_test(); }); add_test(function changeLinks() { let expectedLinks = makeLinks(0, 20, 2); let provider = new TestProvider(done => done(expectedLinks)); NewTabUtils.initWithoutProviders(); NewTabUtils.links.addProvider(provider); // This is sync since the provider's getLinks is sync. NewTabUtils.links.populateCache(function () {}, false); do_check_links(NewTabUtils.links.getLinks(), expectedLinks); // Notify of a new link. let newLink = { url: "http://example.com/19", title: "My frecency is 19", frecency: 19, lastVisitDate: 0, }; expectedLinks.splice(1, 0, newLink); provider.notifyLinkChanged(newLink); do_check_links(NewTabUtils.links.getLinks(), expectedLinks); // Notify of a link that's changed sort criteria. newLink.frecency = 17; expectedLinks.splice(1, 1); expectedLinks.splice(2, 0, newLink); provider.notifyLinkChanged({ url: newLink.url, frecency: 17, }); do_check_links(NewTabUtils.links.getLinks(), expectedLinks); // Notify of a link that's changed title. newLink.title = "My frecency is now 17"; provider.notifyLinkChanged({ url: newLink.url, title: newLink.title, }); do_check_links(NewTabUtils.links.getLinks(), expectedLinks); // Notify of a new link again, but this time make it overflow maxNumLinks. provider.maxNumLinks = expectedLinks.length; newLink = { url: "http://example.com/21", frecency: 21, lastVisitDate: 0, }; expectedLinks.unshift(newLink); expectedLinks.pop(); do_check_eq(expectedLinks.length, provider.maxNumLinks); // Sanity check. provider.notifyLinkChanged(newLink); do_check_links(NewTabUtils.links.getLinks(), expectedLinks); // Notify of many links changed. expectedLinks = makeLinks(0, 3, 1); provider.notifyManyLinksChanged(); // NewTabUtils.links will now repopulate its cache, which is sync since // the provider's getLinks is sync. do_check_links(NewTabUtils.links.getLinks(), expectedLinks); NewTabUtils.links.removeProvider(provider); run_next_test(); }); add_task(function oneProviderAlreadyCached() { let links1 = makeLinks(0, 10, 1); let provider1 = new TestProvider(done => done(links1)); NewTabUtils.initWithoutProviders(); NewTabUtils.links.addProvider(provider1); // This is sync since the provider's getLinks is sync. NewTabUtils.links.populateCache(function () {}, false); do_check_links(NewTabUtils.links.getLinks(), links1); let links2 = makeLinks(10, 20, 1); let provider2 = new TestProvider(done => done(links2)); NewTabUtils.links.addProvider(provider2); NewTabUtils.links.populateCache(function () {}, false); do_check_links(NewTabUtils.links.getLinks(), links2.concat(links1)); NewTabUtils.links.removeProvider(provider1); NewTabUtils.links.removeProvider(provider2); }); function TestProvider(getLinksFn) { this.getLinks = getLinksFn; this._observers = new Set(); } TestProvider.prototype = { addObserver: function (observer) { this._observers.add(observer); }, notifyLinkChanged: function (link) { this._notifyObservers("onLinkChanged", link); }, notifyManyLinksChanged: function () { this._notifyObservers("onManyLinksChanged"); }, _notifyObservers: function (observerMethodName, arg) { for (let obs of this._observers) { if (obs[observerMethodName]) obs[observerMethodName](this, arg); } }, }; function do_check_links(actualLinks, expectedLinks) { do_check_true(Array.isArray(actualLinks)); do_check_eq(actualLinks.length, expectedLinks.length); for (let i = 0; i < expectedLinks.length; i++) { let expected = expectedLinks[i]; let actual = actualLinks[i]; do_check_eq(actual.url, expected.url); do_check_eq(actual.title, expected.title); do_check_eq(actual.frecency, expected.frecency); do_check_eq(actual.lastVisitDate, expected.lastVisitDate); } } function makeLinks(frecRangeStart, frecRangeEnd, step) { let links = []; // Remember, links are ordered by frecency descending. for (let i = frecRangeEnd; i > frecRangeStart; i -= step) { links.push({ url: "http://example.com/" + i, title: "My frecency is " + i, frecency: i, lastVisitDate: 0, }); } return links; }