summaryrefslogtreecommitdiffstats
path: root/toolkit/modules/tests/xpcshell/test_NewTabUtils.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/modules/tests/xpcshell/test_NewTabUtils.js')
-rw-r--r--toolkit/modules/tests/xpcshell/test_NewTabUtils.js378
1 files changed, 378 insertions, 0 deletions
diff --git a/toolkit/modules/tests/xpcshell/test_NewTabUtils.js b/toolkit/modules/tests/xpcshell/test_NewTabUtils.js
new file mode 100644
index 000000000..8cdb63550
--- /dev/null
+++ b/toolkit/modules/tests/xpcshell/test_NewTabUtils.js
@@ -0,0 +1,378 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// See also browser/base/content/test/newtab/.
+
+var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
+Cu.import("resource://gre/modules/NewTabUtils.jsm");
+Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+const PREF_NEWTAB_ENHANCED = "browser.newtabpage.enhanced";
+
+function run_test() {
+ Services.prefs.setBoolPref(PREF_NEWTAB_ENHANCED, true);
+ run_next_test();
+}
+
+add_task(function* validCacheMidPopulation() {
+ let expectedLinks = makeLinks(0, 3, 1);
+
+ let provider = new TestProvider(done => done(expectedLinks));
+ provider.maxNumLinks = expectedLinks.length;
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider);
+ let promise = new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+
+ // isTopSiteGivenProvider() and getProviderLinks() should still return results
+ // even when cache is empty or being populated.
+ do_check_false(NewTabUtils.isTopSiteGivenProvider("example1.com", provider));
+ do_check_links(NewTabUtils.getProviderLinks(provider), []);
+
+ yield promise;
+
+ // Once the cache is populated, we get the expected results
+ do_check_true(NewTabUtils.isTopSiteGivenProvider("example1.com", provider));
+ do_check_links(NewTabUtils.getProviderLinks(provider), expectedLinks);
+ NewTabUtils.links.removeProvider(provider);
+});
+
+add_task(function* notifyLinkDelete() {
+ let expectedLinks = makeLinks(0, 3, 1);
+
+ let provider = new TestProvider(done => done(expectedLinks));
+ provider.maxNumLinks = expectedLinks.length;
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider);
+ yield new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+
+ do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
+
+ // Remove a link.
+ let removedLink = expectedLinks[2];
+ provider.notifyLinkChanged(removedLink, 2, true);
+ let links = NewTabUtils.links._providers.get(provider);
+
+ // Check that sortedLinks is correctly updated.
+ do_check_links(NewTabUtils.links.getLinks(), expectedLinks.slice(0, 2));
+
+ // Check that linkMap is accurately updated.
+ do_check_eq(links.linkMap.size, 2);
+ do_check_true(links.linkMap.get(expectedLinks[0].url));
+ do_check_true(links.linkMap.get(expectedLinks[1].url));
+ do_check_false(links.linkMap.get(removedLink.url));
+
+ // Check that siteMap is correctly updated.
+ do_check_eq(links.siteMap.size, 2);
+ do_check_true(links.siteMap.has(NewTabUtils.extractSite(expectedLinks[0].url)));
+ do_check_true(links.siteMap.has(NewTabUtils.extractSite(expectedLinks[1].url)));
+ do_check_false(links.siteMap.has(NewTabUtils.extractSite(removedLink.url)));
+
+ NewTabUtils.links.removeProvider(provider);
+});
+
+add_task(function* populatePromise() {
+ let count = 0;
+ let expectedLinks = makeLinks(0, 10, 2);
+
+ let getLinksFcn = Task.async(function* (callback) {
+ // Should not be calling getLinksFcn twice
+ count++;
+ do_check_eq(count, 1);
+ yield Promise.resolve();
+ callback(expectedLinks);
+ });
+
+ let provider = new TestProvider(getLinksFcn);
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider);
+
+ NewTabUtils.links.populateProviderCache(provider, () => {});
+ NewTabUtils.links.populateProviderCache(provider, () => {
+ do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
+ NewTabUtils.links.removeProvider(provider);
+ });
+});
+
+add_task(function* isTopSiteGivenProvider() {
+ let expectedLinks = makeLinks(0, 10, 2);
+
+ // The lowest 2 frecencies have the same base domain.
+ expectedLinks[expectedLinks.length - 2].url = expectedLinks[expectedLinks.length - 1].url + "Test";
+
+ let provider = new TestProvider(done => done(expectedLinks));
+ provider.maxNumLinks = expectedLinks.length;
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider);
+ yield new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+
+ do_check_eq(NewTabUtils.isTopSiteGivenProvider("example2.com", provider), true);
+ do_check_eq(NewTabUtils.isTopSiteGivenProvider("example1.com", provider), false);
+
+ // Push out frecency 2 because the maxNumLinks is reached when adding frecency 3
+ let newLink = makeLink(3);
+ provider.notifyLinkChanged(newLink);
+
+ // There is still a frecent url with example2 domain, so it's still frecent.
+ do_check_eq(NewTabUtils.isTopSiteGivenProvider("example3.com", provider), true);
+ do_check_eq(NewTabUtils.isTopSiteGivenProvider("example2.com", provider), true);
+
+ // Push out frecency 3
+ newLink = makeLink(5);
+ provider.notifyLinkChanged(newLink);
+
+ // Push out frecency 4
+ newLink = makeLink(9);
+ provider.notifyLinkChanged(newLink);
+
+ // Our count reached 0 for the example2.com domain so it's no longer a frecent site.
+ do_check_eq(NewTabUtils.isTopSiteGivenProvider("example5.com", provider), true);
+ do_check_eq(NewTabUtils.isTopSiteGivenProvider("example2.com", provider), false);
+
+ NewTabUtils.links.removeProvider(provider);
+});
+
+add_task(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);
+
+ yield new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+
+ 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);
+});
+
+add_task(function* changeLinks() {
+ let expectedLinks = makeLinks(0, 20, 2);
+ let provider = new TestProvider(done => done(expectedLinks));
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider);
+
+ yield new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+
+ do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
+
+ // Notify of a new link.
+ let newLink = makeLink(19);
+ 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 = makeLink(21);
+ 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();
+
+ // Since _populateProviderCache() is async, we must wait until the provider's
+ // populate promise has been resolved.
+ yield NewTabUtils.links._providers.get(provider).populatePromise;
+
+ // NewTabUtils.links will now repopulate its cache
+ do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
+
+ NewTabUtils.links.removeProvider(provider);
+});
+
+add_task(function* oneProviderAlreadyCached() {
+ let links1 = makeLinks(0, 10, 1);
+ let provider1 = new TestProvider(done => done(links1));
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider1);
+
+ yield new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+ do_check_links(NewTabUtils.links.getLinks(), links1);
+
+ let links2 = makeLinks(10, 20, 1);
+ let provider2 = new TestProvider(done => done(links2));
+ NewTabUtils.links.addProvider(provider2);
+
+ yield new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+ do_check_links(NewTabUtils.links.getLinks(), links2.concat(links1));
+
+ NewTabUtils.links.removeProvider(provider1);
+ NewTabUtils.links.removeProvider(provider2);
+});
+
+add_task(function* newLowRankedLink() {
+ // Init a provider with 10 links and make its maximum number also 10.
+ let links = makeLinks(0, 10, 1);
+ let provider = new TestProvider(done => done(links));
+ provider.maxNumLinks = links.length;
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider);
+
+ yield new Promise(resolve => NewTabUtils.links.populateCache(resolve));
+ do_check_links(NewTabUtils.links.getLinks(), links);
+
+ // Notify of a new link that's low-ranked enough not to make the list.
+ let newLink = makeLink(0);
+ provider.notifyLinkChanged(newLink);
+ do_check_links(NewTabUtils.links.getLinks(), links);
+
+ // Notify about the new link's title change.
+ provider.notifyLinkChanged({
+ url: newLink.url,
+ title: "a new title",
+ });
+ do_check_links(NewTabUtils.links.getLinks(), links);
+
+ NewTabUtils.links.removeProvider(provider);
+});
+
+add_task(function* extractSite() {
+ // All these should extract to the same site
+ [ "mozilla.org",
+ "m.mozilla.org",
+ "mobile.mozilla.org",
+ "www.mozilla.org",
+ "www3.mozilla.org",
+ ].forEach(host => {
+ let url = "http://" + host;
+ do_check_eq(NewTabUtils.extractSite(url), "mozilla.org", "extracted same " + host);
+ });
+
+ // All these should extract to the same subdomain
+ [ "bugzilla.mozilla.org",
+ "www.bugzilla.mozilla.org",
+ ].forEach(host => {
+ let url = "http://" + host;
+ do_check_eq(NewTabUtils.extractSite(url), "bugzilla.mozilla.org", "extracted eTLD+2 " + host);
+ });
+
+ // All these should not extract to the same site
+ [ "bugzilla.mozilla.org",
+ "bug123.bugzilla.mozilla.org",
+ "too.many.levels.bugzilla.mozilla.org",
+ "m2.mozilla.org",
+ "mobile30.mozilla.org",
+ "ww.mozilla.org",
+ "ww2.mozilla.org",
+ "wwwww.mozilla.org",
+ "wwwww50.mozilla.org",
+ "wwws.mozilla.org",
+ "secure.mozilla.org",
+ "secure10.mozilla.org",
+ "many.levels.deep.mozilla.org",
+ "just.check.in",
+ "192.168.0.1",
+ "localhost",
+ ].forEach(host => {
+ let url = "http://" + host;
+ do_check_neq(NewTabUtils.extractSite(url), "mozilla.org", "extracted diff " + host);
+ });
+
+ // All these should not extract to the same site
+ [ "about:blank",
+ "file:///Users/user/file",
+ "chrome://browser/something",
+ "ftp://ftp.mozilla.org/",
+ ].forEach(url => {
+ do_check_neq(NewTabUtils.extractSite(url), "mozilla.org", "extracted diff url " + url);
+ });
+});
+
+function TestProvider(getLinksFn) {
+ this.getLinks = getLinksFn;
+ this._observers = new Set();
+}
+
+TestProvider.prototype = {
+ addObserver: function (observer) {
+ this._observers.add(observer);
+ },
+ notifyLinkChanged: function (link, index=-1, deleted=false) {
+ this._notifyObservers("onLinkChanged", link, index, deleted);
+ },
+ notifyManyLinksChanged: function () {
+ this._notifyObservers("onManyLinksChanged");
+ },
+ _notifyObservers: function () {
+ let observerMethodName = arguments[0];
+ let args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(this);
+ for (let obs of this._observers) {
+ if (obs[observerMethodName])
+ obs[observerMethodName].apply(NewTabUtils.links, args);
+ }
+ },
+};
+
+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(makeLink(i));
+ }
+ return links;
+}
+
+function makeLink(frecency) {
+ return {
+ url: "http://example" + frecency + ".com/",
+ title: "My frecency is " + frecency,
+ frecency: frecency,
+ lastVisitDate: 0,
+ };
+}