|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 // See also browser/base/content/test/newtab/. |
|
5 |
|
6 const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; |
|
7 Cu.import("resource://gre/modules/NewTabUtils.jsm"); |
|
8 Cu.import("resource://gre/modules/Promise.jsm"); |
|
9 |
|
10 function run_test() { |
|
11 run_next_test(); |
|
12 } |
|
13 |
|
14 add_test(function multipleProviders() { |
|
15 // Make each provider generate NewTabUtils.links.maxNumLinks links to check |
|
16 // that no more than maxNumLinks are actually returned in the merged list. |
|
17 let evenLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks, 2); |
|
18 let evenProvider = new TestProvider(done => done(evenLinks)); |
|
19 let oddLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks - 1, 2); |
|
20 let oddProvider = new TestProvider(done => done(oddLinks)); |
|
21 |
|
22 NewTabUtils.initWithoutProviders(); |
|
23 NewTabUtils.links.addProvider(evenProvider); |
|
24 NewTabUtils.links.addProvider(oddProvider); |
|
25 |
|
26 // This is sync since the providers' getLinks are sync. |
|
27 NewTabUtils.links.populateCache(function () {}, false); |
|
28 |
|
29 let links = NewTabUtils.links.getLinks(); |
|
30 let expectedLinks = makeLinks(NewTabUtils.links.maxNumLinks, |
|
31 2 * NewTabUtils.links.maxNumLinks, |
|
32 1); |
|
33 do_check_eq(links.length, NewTabUtils.links.maxNumLinks); |
|
34 do_check_links(links, expectedLinks); |
|
35 |
|
36 NewTabUtils.links.removeProvider(evenProvider); |
|
37 NewTabUtils.links.removeProvider(oddProvider); |
|
38 run_next_test(); |
|
39 }); |
|
40 |
|
41 add_test(function changeLinks() { |
|
42 let expectedLinks = makeLinks(0, 20, 2); |
|
43 let provider = new TestProvider(done => done(expectedLinks)); |
|
44 |
|
45 NewTabUtils.initWithoutProviders(); |
|
46 NewTabUtils.links.addProvider(provider); |
|
47 |
|
48 // This is sync since the provider's getLinks is sync. |
|
49 NewTabUtils.links.populateCache(function () {}, false); |
|
50 |
|
51 do_check_links(NewTabUtils.links.getLinks(), expectedLinks); |
|
52 |
|
53 // Notify of a new link. |
|
54 let newLink = makeLink(19); |
|
55 expectedLinks.splice(1, 0, newLink); |
|
56 provider.notifyLinkChanged(newLink); |
|
57 do_check_links(NewTabUtils.links.getLinks(), expectedLinks); |
|
58 |
|
59 // Notify of a link that's changed sort criteria. |
|
60 newLink.frecency = 17; |
|
61 expectedLinks.splice(1, 1); |
|
62 expectedLinks.splice(2, 0, newLink); |
|
63 provider.notifyLinkChanged({ |
|
64 url: newLink.url, |
|
65 frecency: 17, |
|
66 }); |
|
67 do_check_links(NewTabUtils.links.getLinks(), expectedLinks); |
|
68 |
|
69 // Notify of a link that's changed title. |
|
70 newLink.title = "My frecency is now 17"; |
|
71 provider.notifyLinkChanged({ |
|
72 url: newLink.url, |
|
73 title: newLink.title, |
|
74 }); |
|
75 do_check_links(NewTabUtils.links.getLinks(), expectedLinks); |
|
76 |
|
77 // Notify of a new link again, but this time make it overflow maxNumLinks. |
|
78 provider.maxNumLinks = expectedLinks.length; |
|
79 newLink = makeLink(21); |
|
80 expectedLinks.unshift(newLink); |
|
81 expectedLinks.pop(); |
|
82 do_check_eq(expectedLinks.length, provider.maxNumLinks); // Sanity check. |
|
83 provider.notifyLinkChanged(newLink); |
|
84 do_check_links(NewTabUtils.links.getLinks(), expectedLinks); |
|
85 |
|
86 // Notify of many links changed. |
|
87 expectedLinks = makeLinks(0, 3, 1); |
|
88 provider.notifyManyLinksChanged(); |
|
89 // NewTabUtils.links will now repopulate its cache, which is sync since |
|
90 // the provider's getLinks is sync. |
|
91 do_check_links(NewTabUtils.links.getLinks(), expectedLinks); |
|
92 |
|
93 NewTabUtils.links.removeProvider(provider); |
|
94 run_next_test(); |
|
95 }); |
|
96 |
|
97 add_task(function oneProviderAlreadyCached() { |
|
98 let links1 = makeLinks(0, 10, 1); |
|
99 let provider1 = new TestProvider(done => done(links1)); |
|
100 |
|
101 NewTabUtils.initWithoutProviders(); |
|
102 NewTabUtils.links.addProvider(provider1); |
|
103 |
|
104 // This is sync since the provider's getLinks is sync. |
|
105 NewTabUtils.links.populateCache(function () {}, false); |
|
106 do_check_links(NewTabUtils.links.getLinks(), links1); |
|
107 |
|
108 let links2 = makeLinks(10, 20, 1); |
|
109 let provider2 = new TestProvider(done => done(links2)); |
|
110 NewTabUtils.links.addProvider(provider2); |
|
111 |
|
112 NewTabUtils.links.populateCache(function () {}, false); |
|
113 do_check_links(NewTabUtils.links.getLinks(), links2.concat(links1)); |
|
114 |
|
115 NewTabUtils.links.removeProvider(provider1); |
|
116 NewTabUtils.links.removeProvider(provider2); |
|
117 }); |
|
118 |
|
119 add_task(function newLowRankedLink() { |
|
120 // Init a provider with 10 links and make its maximum number also 10. |
|
121 let links = makeLinks(0, 10, 1); |
|
122 let provider = new TestProvider(done => done(links)); |
|
123 provider.maxNumLinks = links.length; |
|
124 |
|
125 NewTabUtils.initWithoutProviders(); |
|
126 NewTabUtils.links.addProvider(provider); |
|
127 |
|
128 // This is sync since the provider's getLinks is sync. |
|
129 NewTabUtils.links.populateCache(function () {}, false); |
|
130 do_check_links(NewTabUtils.links.getLinks(), links); |
|
131 |
|
132 // Notify of a new link that's low-ranked enough not to make the list. |
|
133 let newLink = makeLink(0); |
|
134 provider.notifyLinkChanged(newLink); |
|
135 do_check_links(NewTabUtils.links.getLinks(), links); |
|
136 |
|
137 // Notify about the new link's title change. |
|
138 provider.notifyLinkChanged({ |
|
139 url: newLink.url, |
|
140 title: "a new title", |
|
141 }); |
|
142 do_check_links(NewTabUtils.links.getLinks(), links); |
|
143 |
|
144 NewTabUtils.links.removeProvider(provider); |
|
145 }); |
|
146 |
|
147 function TestProvider(getLinksFn) { |
|
148 this.getLinks = getLinksFn; |
|
149 this._observers = new Set(); |
|
150 } |
|
151 |
|
152 TestProvider.prototype = { |
|
153 addObserver: function (observer) { |
|
154 this._observers.add(observer); |
|
155 }, |
|
156 notifyLinkChanged: function (link) { |
|
157 this._notifyObservers("onLinkChanged", link); |
|
158 }, |
|
159 notifyManyLinksChanged: function () { |
|
160 this._notifyObservers("onManyLinksChanged"); |
|
161 }, |
|
162 _notifyObservers: function (observerMethodName, arg) { |
|
163 for (let obs of this._observers) { |
|
164 if (obs[observerMethodName]) |
|
165 obs[observerMethodName](this, arg); |
|
166 } |
|
167 }, |
|
168 }; |
|
169 |
|
170 function do_check_links(actualLinks, expectedLinks) { |
|
171 do_check_true(Array.isArray(actualLinks)); |
|
172 do_check_eq(actualLinks.length, expectedLinks.length); |
|
173 for (let i = 0; i < expectedLinks.length; i++) { |
|
174 let expected = expectedLinks[i]; |
|
175 let actual = actualLinks[i]; |
|
176 do_check_eq(actual.url, expected.url); |
|
177 do_check_eq(actual.title, expected.title); |
|
178 do_check_eq(actual.frecency, expected.frecency); |
|
179 do_check_eq(actual.lastVisitDate, expected.lastVisitDate); |
|
180 } |
|
181 } |
|
182 |
|
183 function makeLinks(frecRangeStart, frecRangeEnd, step) { |
|
184 let links = []; |
|
185 // Remember, links are ordered by frecency descending. |
|
186 for (let i = frecRangeEnd; i > frecRangeStart; i -= step) { |
|
187 links.push(makeLink(i)); |
|
188 } |
|
189 return links; |
|
190 } |
|
191 |
|
192 function makeLink(frecency) { |
|
193 return { |
|
194 url: "http://example.com/" + frecency, |
|
195 title: "My frecency is " + frecency, |
|
196 frecency: frecency, |
|
197 lastVisitDate: 0, |
|
198 }; |
|
199 } |