1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/modules/tests/xpcshell/test_NewTabUtils.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,199 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +// See also browser/base/content/test/newtab/. 1.8 + 1.9 +const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; 1.10 +Cu.import("resource://gre/modules/NewTabUtils.jsm"); 1.11 +Cu.import("resource://gre/modules/Promise.jsm"); 1.12 + 1.13 +function run_test() { 1.14 + run_next_test(); 1.15 +} 1.16 + 1.17 +add_test(function multipleProviders() { 1.18 + // Make each provider generate NewTabUtils.links.maxNumLinks links to check 1.19 + // that no more than maxNumLinks are actually returned in the merged list. 1.20 + let evenLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks, 2); 1.21 + let evenProvider = new TestProvider(done => done(evenLinks)); 1.22 + let oddLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks - 1, 2); 1.23 + let oddProvider = new TestProvider(done => done(oddLinks)); 1.24 + 1.25 + NewTabUtils.initWithoutProviders(); 1.26 + NewTabUtils.links.addProvider(evenProvider); 1.27 + NewTabUtils.links.addProvider(oddProvider); 1.28 + 1.29 + // This is sync since the providers' getLinks are sync. 1.30 + NewTabUtils.links.populateCache(function () {}, false); 1.31 + 1.32 + let links = NewTabUtils.links.getLinks(); 1.33 + let expectedLinks = makeLinks(NewTabUtils.links.maxNumLinks, 1.34 + 2 * NewTabUtils.links.maxNumLinks, 1.35 + 1); 1.36 + do_check_eq(links.length, NewTabUtils.links.maxNumLinks); 1.37 + do_check_links(links, expectedLinks); 1.38 + 1.39 + NewTabUtils.links.removeProvider(evenProvider); 1.40 + NewTabUtils.links.removeProvider(oddProvider); 1.41 + run_next_test(); 1.42 +}); 1.43 + 1.44 +add_test(function changeLinks() { 1.45 + let expectedLinks = makeLinks(0, 20, 2); 1.46 + let provider = new TestProvider(done => done(expectedLinks)); 1.47 + 1.48 + NewTabUtils.initWithoutProviders(); 1.49 + NewTabUtils.links.addProvider(provider); 1.50 + 1.51 + // This is sync since the provider's getLinks is sync. 1.52 + NewTabUtils.links.populateCache(function () {}, false); 1.53 + 1.54 + do_check_links(NewTabUtils.links.getLinks(), expectedLinks); 1.55 + 1.56 + // Notify of a new link. 1.57 + let newLink = makeLink(19); 1.58 + expectedLinks.splice(1, 0, newLink); 1.59 + provider.notifyLinkChanged(newLink); 1.60 + do_check_links(NewTabUtils.links.getLinks(), expectedLinks); 1.61 + 1.62 + // Notify of a link that's changed sort criteria. 1.63 + newLink.frecency = 17; 1.64 + expectedLinks.splice(1, 1); 1.65 + expectedLinks.splice(2, 0, newLink); 1.66 + provider.notifyLinkChanged({ 1.67 + url: newLink.url, 1.68 + frecency: 17, 1.69 + }); 1.70 + do_check_links(NewTabUtils.links.getLinks(), expectedLinks); 1.71 + 1.72 + // Notify of a link that's changed title. 1.73 + newLink.title = "My frecency is now 17"; 1.74 + provider.notifyLinkChanged({ 1.75 + url: newLink.url, 1.76 + title: newLink.title, 1.77 + }); 1.78 + do_check_links(NewTabUtils.links.getLinks(), expectedLinks); 1.79 + 1.80 + // Notify of a new link again, but this time make it overflow maxNumLinks. 1.81 + provider.maxNumLinks = expectedLinks.length; 1.82 + newLink = makeLink(21); 1.83 + expectedLinks.unshift(newLink); 1.84 + expectedLinks.pop(); 1.85 + do_check_eq(expectedLinks.length, provider.maxNumLinks); // Sanity check. 1.86 + provider.notifyLinkChanged(newLink); 1.87 + do_check_links(NewTabUtils.links.getLinks(), expectedLinks); 1.88 + 1.89 + // Notify of many links changed. 1.90 + expectedLinks = makeLinks(0, 3, 1); 1.91 + provider.notifyManyLinksChanged(); 1.92 + // NewTabUtils.links will now repopulate its cache, which is sync since 1.93 + // the provider's getLinks is sync. 1.94 + do_check_links(NewTabUtils.links.getLinks(), expectedLinks); 1.95 + 1.96 + NewTabUtils.links.removeProvider(provider); 1.97 + run_next_test(); 1.98 +}); 1.99 + 1.100 +add_task(function oneProviderAlreadyCached() { 1.101 + let links1 = makeLinks(0, 10, 1); 1.102 + let provider1 = new TestProvider(done => done(links1)); 1.103 + 1.104 + NewTabUtils.initWithoutProviders(); 1.105 + NewTabUtils.links.addProvider(provider1); 1.106 + 1.107 + // This is sync since the provider's getLinks is sync. 1.108 + NewTabUtils.links.populateCache(function () {}, false); 1.109 + do_check_links(NewTabUtils.links.getLinks(), links1); 1.110 + 1.111 + let links2 = makeLinks(10, 20, 1); 1.112 + let provider2 = new TestProvider(done => done(links2)); 1.113 + NewTabUtils.links.addProvider(provider2); 1.114 + 1.115 + NewTabUtils.links.populateCache(function () {}, false); 1.116 + do_check_links(NewTabUtils.links.getLinks(), links2.concat(links1)); 1.117 + 1.118 + NewTabUtils.links.removeProvider(provider1); 1.119 + NewTabUtils.links.removeProvider(provider2); 1.120 +}); 1.121 + 1.122 +add_task(function newLowRankedLink() { 1.123 + // Init a provider with 10 links and make its maximum number also 10. 1.124 + let links = makeLinks(0, 10, 1); 1.125 + let provider = new TestProvider(done => done(links)); 1.126 + provider.maxNumLinks = links.length; 1.127 + 1.128 + NewTabUtils.initWithoutProviders(); 1.129 + NewTabUtils.links.addProvider(provider); 1.130 + 1.131 + // This is sync since the provider's getLinks is sync. 1.132 + NewTabUtils.links.populateCache(function () {}, false); 1.133 + do_check_links(NewTabUtils.links.getLinks(), links); 1.134 + 1.135 + // Notify of a new link that's low-ranked enough not to make the list. 1.136 + let newLink = makeLink(0); 1.137 + provider.notifyLinkChanged(newLink); 1.138 + do_check_links(NewTabUtils.links.getLinks(), links); 1.139 + 1.140 + // Notify about the new link's title change. 1.141 + provider.notifyLinkChanged({ 1.142 + url: newLink.url, 1.143 + title: "a new title", 1.144 + }); 1.145 + do_check_links(NewTabUtils.links.getLinks(), links); 1.146 + 1.147 + NewTabUtils.links.removeProvider(provider); 1.148 +}); 1.149 + 1.150 +function TestProvider(getLinksFn) { 1.151 + this.getLinks = getLinksFn; 1.152 + this._observers = new Set(); 1.153 +} 1.154 + 1.155 +TestProvider.prototype = { 1.156 + addObserver: function (observer) { 1.157 + this._observers.add(observer); 1.158 + }, 1.159 + notifyLinkChanged: function (link) { 1.160 + this._notifyObservers("onLinkChanged", link); 1.161 + }, 1.162 + notifyManyLinksChanged: function () { 1.163 + this._notifyObservers("onManyLinksChanged"); 1.164 + }, 1.165 + _notifyObservers: function (observerMethodName, arg) { 1.166 + for (let obs of this._observers) { 1.167 + if (obs[observerMethodName]) 1.168 + obs[observerMethodName](this, arg); 1.169 + } 1.170 + }, 1.171 +}; 1.172 + 1.173 +function do_check_links(actualLinks, expectedLinks) { 1.174 + do_check_true(Array.isArray(actualLinks)); 1.175 + do_check_eq(actualLinks.length, expectedLinks.length); 1.176 + for (let i = 0; i < expectedLinks.length; i++) { 1.177 + let expected = expectedLinks[i]; 1.178 + let actual = actualLinks[i]; 1.179 + do_check_eq(actual.url, expected.url); 1.180 + do_check_eq(actual.title, expected.title); 1.181 + do_check_eq(actual.frecency, expected.frecency); 1.182 + do_check_eq(actual.lastVisitDate, expected.lastVisitDate); 1.183 + } 1.184 +} 1.185 + 1.186 +function makeLinks(frecRangeStart, frecRangeEnd, step) { 1.187 + let links = []; 1.188 + // Remember, links are ordered by frecency descending. 1.189 + for (let i = frecRangeEnd; i > frecRangeStart; i -= step) { 1.190 + links.push(makeLink(i)); 1.191 + } 1.192 + return links; 1.193 +} 1.194 + 1.195 +function makeLink(frecency) { 1.196 + return { 1.197 + url: "http://example.com/" + frecency, 1.198 + title: "My frecency is " + frecency, 1.199 + frecency: frecency, 1.200 + lastVisitDate: 0, 1.201 + }; 1.202 +}