|
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 // Get history service |
|
8 var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. |
|
9 getService(Ci.nsINavHistoryService); |
|
10 var bh = hs.QueryInterface(Ci.nsIBrowserHistory); |
|
11 var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. |
|
12 getService(Ci.nsINavBookmarksService); |
|
13 var ps = Cc["@mozilla.org/preferences-service;1"]. |
|
14 getService(Ci.nsIPrefBranch); |
|
15 |
|
16 /** |
|
17 * Adds a test URI visit to the database. |
|
18 * |
|
19 * @param aURI |
|
20 * The URI to add a visit for. |
|
21 * @param aTime |
|
22 * Reference "now" time. |
|
23 * @param aDayOffset |
|
24 * number of days to add, pass a negative value to subtract them. |
|
25 */ |
|
26 function task_add_normalized_visit(aURI, aTime, aDayOffset) { |
|
27 var dateObj = new Date(aTime); |
|
28 // Normalize to midnight |
|
29 dateObj.setHours(0); |
|
30 dateObj.setMinutes(0); |
|
31 dateObj.setSeconds(0); |
|
32 dateObj.setMilliseconds(0); |
|
33 // Days where DST changes should be taken in count. |
|
34 var previousDateObj = new Date(dateObj.getTime() + aDayOffset * 86400000); |
|
35 var DSTCorrection = (dateObj.getTimezoneOffset() - |
|
36 previousDateObj.getTimezoneOffset()) * 60 * 1000; |
|
37 // Substract aDayOffset |
|
38 var PRTimeWithOffset = (previousDateObj.getTime() - DSTCorrection) * 1000; |
|
39 var timeInMs = new Date(PRTimeWithOffset/1000); |
|
40 print("Adding visit to " + aURI.spec + " at " + timeInMs); |
|
41 yield promiseAddVisits({ |
|
42 uri: aURI, |
|
43 visitDate: PRTimeWithOffset |
|
44 }); |
|
45 } |
|
46 |
|
47 function days_for_x_months_ago(aNowObj, aMonths) { |
|
48 var oldTime = new Date(); |
|
49 // Set day before month, otherwise we could try to calculate 30 February, or |
|
50 // other nonexistent days. |
|
51 oldTime.setDate(1); |
|
52 oldTime.setMonth(aNowObj.getMonth() - aMonths); |
|
53 oldTime.setHours(0); |
|
54 oldTime.setMinutes(0); |
|
55 oldTime.setSeconds(0); |
|
56 // Stay larger for eventual timezone issues, add 2 days. |
|
57 return parseInt((aNowObj - oldTime) / (1000*60*60*24)) + 2; |
|
58 } |
|
59 |
|
60 var nowObj = new Date(); |
|
61 // This test relies on en-US locale |
|
62 // Offset is number of days |
|
63 var containers = [ |
|
64 { label: "Today" , offset: 0 , visible: true }, |
|
65 { label: "Yesterday" , offset: -1 , visible: true }, |
|
66 { label: "Last 7 days" , offset: -3 , visible: true }, |
|
67 { label: "This month" , offset: -8 , visible: nowObj.getDate() > 8 }, |
|
68 { label: "" , offset: -days_for_x_months_ago(nowObj, 0) , visible: true }, |
|
69 { label: "" , offset: -days_for_x_months_ago(nowObj, 1) , visible: true }, |
|
70 { label: "" , offset: -days_for_x_months_ago(nowObj, 2) , visible: true }, |
|
71 { label: "" , offset: -days_for_x_months_ago(nowObj, 3) , visible: true }, |
|
72 { label: "" , offset: -days_for_x_months_ago(nowObj, 4) , visible: true }, |
|
73 { label: "Older than 6 months" , offset: -days_for_x_months_ago(nowObj, 5) , visible: true }, |
|
74 ]; |
|
75 |
|
76 var visibleContainers = containers.filter( |
|
77 function(aContainer) {return aContainer.visible}); |
|
78 |
|
79 /** |
|
80 * Asynchronous task that fills history and checks containers' labels. |
|
81 */ |
|
82 function task_fill_history() { |
|
83 print("\n\n*** TEST Fill History\n"); |
|
84 // We can't use "now" because our hardcoded offsets would be invalid for some |
|
85 // date. So we hardcode a date. |
|
86 for (var i = 0; i < containers.length; i++) { |
|
87 var container = containers[i]; |
|
88 var testURI = uri("http://mirror"+i+".mozilla.com/b"); |
|
89 yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); |
|
90 var testURI = uri("http://mirror"+i+".mozilla.com/a"); |
|
91 yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); |
|
92 var testURI = uri("http://mirror"+i+".google.com/b"); |
|
93 yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); |
|
94 var testURI = uri("http://mirror"+i+".google.com/a"); |
|
95 yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); |
|
96 // Bug 485703 - Hide date containers not containing additional entries |
|
97 // compared to previous ones. |
|
98 // Check after every new container is added. |
|
99 check_visit(container.offset); |
|
100 } |
|
101 |
|
102 var options = hs.getNewQueryOptions(); |
|
103 options.resultType = options.RESULTS_AS_DATE_SITE_QUERY; |
|
104 var query = hs.getNewQuery(); |
|
105 |
|
106 var result = hs.executeQuery(query, options); |
|
107 var root = result.root; |
|
108 root.containerOpen = true; |
|
109 |
|
110 var cc = root.childCount; |
|
111 print("Found containers:"); |
|
112 var previousLabels = []; |
|
113 for (var i = 0; i < cc; i++) { |
|
114 var container = visibleContainers[i]; |
|
115 var node = root.getChild(i); |
|
116 print(node.title); |
|
117 if (container.label) |
|
118 do_check_eq(node.title, container.label); |
|
119 // Check labels are not repeated. |
|
120 do_check_eq(previousLabels.indexOf(node.title), -1); |
|
121 previousLabels.push(node.title); |
|
122 } |
|
123 do_check_eq(cc, visibleContainers.length); |
|
124 root.containerOpen = false; |
|
125 } |
|
126 |
|
127 /** |
|
128 * Bug 485703 - Hide date containers not containing additional entries compared |
|
129 * to previous ones. |
|
130 */ |
|
131 function check_visit(aOffset) { |
|
132 var options = hs.getNewQueryOptions(); |
|
133 options.resultType = options.RESULTS_AS_DATE_SITE_QUERY; |
|
134 var query = hs.getNewQuery(); |
|
135 var result = hs.executeQuery(query, options); |
|
136 var root = result.root; |
|
137 root.containerOpen = true; |
|
138 var cc = root.childCount; |
|
139 |
|
140 var unexpected = []; |
|
141 switch (aOffset) { |
|
142 case 0: |
|
143 unexpected = ["Yesterday", "Last 7 days", "This month"]; |
|
144 break; |
|
145 case -1: |
|
146 unexpected = ["Last 7 days", "This month"]; |
|
147 break; |
|
148 case -3: |
|
149 unexpected = ["This month"]; |
|
150 break; |
|
151 default: |
|
152 // Other containers are tested later. |
|
153 } |
|
154 |
|
155 print("Found containers:"); |
|
156 for (var i = 0; i < cc; i++) { |
|
157 var node = root.getChild(i); |
|
158 print(node.title); |
|
159 do_check_eq(unexpected.indexOf(node.title), -1); |
|
160 } |
|
161 |
|
162 root.containerOpen = false; |
|
163 } |
|
164 |
|
165 /** |
|
166 * Queries history grouped by date and site, checking containers' labels and |
|
167 * children. |
|
168 */ |
|
169 function test_RESULTS_AS_DATE_SITE_QUERY() { |
|
170 print("\n\n*** TEST RESULTS_AS_DATE_SITE_QUERY\n"); |
|
171 var options = hs.getNewQueryOptions(); |
|
172 options.resultType = options.RESULTS_AS_DATE_SITE_QUERY; |
|
173 var query = hs.getNewQuery(); |
|
174 var result = hs.executeQuery(query, options); |
|
175 var root = result.root; |
|
176 root.containerOpen = true; |
|
177 |
|
178 // Check one of the days |
|
179 var dayNode = root.getChild(0) |
|
180 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
181 dayNode.containerOpen = true; |
|
182 do_check_eq(dayNode.childCount, 2); |
|
183 |
|
184 // Items should be sorted by host |
|
185 var site1 = dayNode.getChild(0) |
|
186 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
187 do_check_eq(site1.title, "mirror0.google.com"); |
|
188 |
|
189 var site2 = dayNode.getChild(1) |
|
190 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
191 do_check_eq(site2.title, "mirror0.mozilla.com"); |
|
192 |
|
193 site1.containerOpen = true; |
|
194 do_check_eq(site1.childCount, 2); |
|
195 |
|
196 // Inside of host sites are sorted by title |
|
197 var site1visit = site1.getChild(0); |
|
198 do_check_eq(site1visit.uri, "http://mirror0.google.com/a"); |
|
199 |
|
200 // Bug 473157: changing sorting mode should not affect the containers |
|
201 result.sortingMode = options.SORT_BY_TITLE_DESCENDING; |
|
202 |
|
203 // Check one of the days |
|
204 var dayNode = root.getChild(0) |
|
205 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
206 dayNode.containerOpen = true; |
|
207 do_check_eq(dayNode.childCount, 2); |
|
208 |
|
209 // Hosts are still sorted by title |
|
210 var site1 = dayNode.getChild(0) |
|
211 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
212 do_check_eq(site1.title, "mirror0.google.com"); |
|
213 |
|
214 var site2 = dayNode.getChild(1) |
|
215 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
216 do_check_eq(site2.title, "mirror0.mozilla.com"); |
|
217 |
|
218 site1.containerOpen = true; |
|
219 do_check_eq(site1.childCount, 2); |
|
220 |
|
221 // But URLs are now sorted by title descending |
|
222 var site1visit = site1.getChild(0); |
|
223 do_check_eq(site1visit.uri, "http://mirror0.google.com/b"); |
|
224 |
|
225 site1.containerOpen = false; |
|
226 dayNode.containerOpen = false; |
|
227 root.containerOpen = false; |
|
228 } |
|
229 |
|
230 /** |
|
231 * Queries history grouped by date, checking containers' labels and children. |
|
232 */ |
|
233 function test_RESULTS_AS_DATE_QUERY() { |
|
234 print("\n\n*** TEST RESULTS_AS_DATE_QUERY\n"); |
|
235 var options = hs.getNewQueryOptions(); |
|
236 options.resultType = options.RESULTS_AS_DATE_QUERY; |
|
237 var query = hs.getNewQuery(); |
|
238 var result = hs.executeQuery(query, options); |
|
239 var root = result.root; |
|
240 root.containerOpen = true; |
|
241 |
|
242 var cc = root.childCount; |
|
243 do_check_eq(cc, visibleContainers.length); |
|
244 print("Found containers:"); |
|
245 for (var i = 0; i < cc; i++) { |
|
246 var container = visibleContainers[i]; |
|
247 var node = root.getChild(i); |
|
248 print(node.title); |
|
249 if (container.label) |
|
250 do_check_eq(node.title, container.label); |
|
251 } |
|
252 |
|
253 // Check one of the days |
|
254 var dayNode = root.getChild(0) |
|
255 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
256 dayNode.containerOpen = true; |
|
257 do_check_eq(dayNode.childCount, 4); |
|
258 |
|
259 // Items should be sorted by title |
|
260 var visit1 = dayNode.getChild(0); |
|
261 do_check_eq(visit1.uri, "http://mirror0.google.com/a"); |
|
262 |
|
263 var visit2 = dayNode.getChild(3); |
|
264 do_check_eq(visit2.uri, "http://mirror0.mozilla.com/b"); |
|
265 |
|
266 // Bug 473157: changing sorting mode should not affect the containers |
|
267 result.sortingMode = options.SORT_BY_TITLE_DESCENDING; |
|
268 |
|
269 // Check one of the days |
|
270 var dayNode = root.getChild(0) |
|
271 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
272 dayNode.containerOpen = true; |
|
273 do_check_eq(dayNode.childCount, 4); |
|
274 |
|
275 // But URLs are now sorted by title descending |
|
276 var visit1 = dayNode.getChild(0); |
|
277 do_check_eq(visit1.uri, "http://mirror0.mozilla.com/b"); |
|
278 |
|
279 var visit2 = dayNode.getChild(3); |
|
280 do_check_eq(visit2.uri, "http://mirror0.google.com/a"); |
|
281 |
|
282 dayNode.containerOpen = false; |
|
283 root.containerOpen = false; |
|
284 } |
|
285 |
|
286 /** |
|
287 * Queries history grouped by site, checking containers' labels and children. |
|
288 */ |
|
289 function test_RESULTS_AS_SITE_QUERY() { |
|
290 print("\n\n*** TEST RESULTS_AS_SITE_QUERY\n"); |
|
291 // add a bookmark with a domain not in the set of visits in the db |
|
292 var itemId = bs.insertBookmark(bs.toolbarFolder, uri("http://foobar"), |
|
293 bs.DEFAULT_INDEX, ""); |
|
294 |
|
295 var options = hs.getNewQueryOptions(); |
|
296 options.resultType = options.RESULTS_AS_SITE_QUERY; |
|
297 options.sortingMode = options.SORT_BY_TITLE_ASCENDING; |
|
298 var query = hs.getNewQuery(); |
|
299 var result = hs.executeQuery(query, options); |
|
300 var root = result.root; |
|
301 root.containerOpen = true; |
|
302 do_check_eq(root.childCount, containers.length * 2); |
|
303 |
|
304 /* Expected results: |
|
305 "mirror0.google.com", |
|
306 "mirror0.mozilla.com", |
|
307 "mirror1.google.com", |
|
308 "mirror1.mozilla.com", |
|
309 "mirror2.google.com", |
|
310 "mirror2.mozilla.com", |
|
311 "mirror3.google.com", <== We check for this site (index 6) |
|
312 "mirror3.mozilla.com", |
|
313 "mirror4.google.com", |
|
314 "mirror4.mozilla.com", |
|
315 "mirror5.google.com", |
|
316 "mirror5.mozilla.com", |
|
317 ... |
|
318 */ |
|
319 |
|
320 // Items should be sorted by host |
|
321 var siteNode = root.getChild(6) |
|
322 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
323 do_check_eq(siteNode.title, "mirror3.google.com"); |
|
324 |
|
325 siteNode.containerOpen = true; |
|
326 do_check_eq(siteNode.childCount, 2); |
|
327 |
|
328 // Inside of host sites are sorted by title |
|
329 var visitNode = siteNode.getChild(0); |
|
330 do_check_eq(visitNode.uri, "http://mirror3.google.com/a"); |
|
331 |
|
332 // Bug 473157: changing sorting mode should not affect the containers |
|
333 result.sortingMode = options.SORT_BY_TITLE_DESCENDING; |
|
334 var siteNode = root.getChild(6) |
|
335 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
336 do_check_eq(siteNode.title, "mirror3.google.com"); |
|
337 |
|
338 siteNode.containerOpen = true; |
|
339 do_check_eq(siteNode.childCount, 2); |
|
340 |
|
341 // But URLs are now sorted by title descending |
|
342 var visit = siteNode.getChild(0); |
|
343 do_check_eq(visit.uri, "http://mirror3.google.com/b"); |
|
344 |
|
345 siteNode.containerOpen = false; |
|
346 root.containerOpen = false; |
|
347 |
|
348 // Cleanup. |
|
349 bs.removeItem(itemId); |
|
350 } |
|
351 |
|
352 /** |
|
353 * Checks that queries grouped by date do liveupdate correctly. |
|
354 */ |
|
355 function task_test_date_liveupdate(aResultType) { |
|
356 var midnight = nowObj; |
|
357 midnight.setHours(0); |
|
358 midnight.setMinutes(0); |
|
359 midnight.setSeconds(0); |
|
360 midnight.setMilliseconds(0); |
|
361 |
|
362 // TEST 1. Test that the query correctly updates when it is root. |
|
363 var options = hs.getNewQueryOptions(); |
|
364 options.resultType = aResultType; |
|
365 var query = hs.getNewQuery(); |
|
366 var result = hs.executeQuery(query, options); |
|
367 var root = result.root; |
|
368 root.containerOpen = true; |
|
369 |
|
370 do_check_eq(root.childCount, visibleContainers.length); |
|
371 // Remove "Today". |
|
372 hs.removePagesByTimeframe(midnight.getTime() * 1000, Date.now() * 1000); |
|
373 do_check_eq(root.childCount, visibleContainers.length - 1); |
|
374 |
|
375 // Open "Last 7 days" container, this way we will have a container accepting |
|
376 // the new visit, but we should still add back "Today" container. |
|
377 var last7Days = root.getChild(1) |
|
378 .QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
379 last7Days.containerOpen = true; |
|
380 |
|
381 // Add a visit for "Today". This should add back the missing "Today" |
|
382 // container. |
|
383 yield task_add_normalized_visit(uri("http://www.mozilla.org/"), nowObj.getTime(), 0); |
|
384 do_check_eq(root.childCount, visibleContainers.length); |
|
385 |
|
386 last7Days.containerOpen = false; |
|
387 root.containerOpen = false; |
|
388 |
|
389 // TEST 2. Test that the query correctly updates even if it is not root. |
|
390 var itemId = bs.insertBookmark(bs.toolbarFolder, |
|
391 uri("place:type=" + aResultType), |
|
392 bs.DEFAULT_INDEX, ""); |
|
393 |
|
394 // Query toolbar and open our query container, then check again liveupdate. |
|
395 options = hs.getNewQueryOptions(); |
|
396 query = hs.getNewQuery(); |
|
397 query.setFolders([bs.toolbarFolder], 1); |
|
398 result = hs.executeQuery(query, options); |
|
399 root = result.root; |
|
400 root.containerOpen = true; |
|
401 do_check_eq(root.childCount, 1); |
|
402 var dateContainer = root.getChild(0).QueryInterface(Ci.nsINavHistoryContainerResultNode); |
|
403 dateContainer.containerOpen = true; |
|
404 |
|
405 do_check_eq(dateContainer.childCount, visibleContainers.length); |
|
406 // Remove "Today". |
|
407 hs.removePagesByTimeframe(midnight.getTime() * 1000, Date.now() * 1000); |
|
408 do_check_eq(dateContainer.childCount, visibleContainers.length - 1); |
|
409 // Add a visit for "Today". |
|
410 yield task_add_normalized_visit(uri("http://www.mozilla.org/"), nowObj.getTime(), 0); |
|
411 do_check_eq(dateContainer.childCount, visibleContainers.length); |
|
412 |
|
413 dateContainer.containerOpen = false; |
|
414 root.containerOpen = false; |
|
415 |
|
416 // Cleanup. |
|
417 bs.removeItem(itemId); |
|
418 } |
|
419 |
|
420 function run_test() |
|
421 { |
|
422 run_next_test(); |
|
423 } |
|
424 |
|
425 add_task(function test_history_sidebar() |
|
426 { |
|
427 // If we're dangerously close to a date change, just bail out. |
|
428 if (nowObj.getHours() == 23 && nowObj.getMinutes() >= 50) { |
|
429 return; |
|
430 } |
|
431 |
|
432 yield task_fill_history(); |
|
433 test_RESULTS_AS_DATE_SITE_QUERY(); |
|
434 test_RESULTS_AS_DATE_QUERY(); |
|
435 test_RESULTS_AS_SITE_QUERY(); |
|
436 |
|
437 yield task_test_date_liveupdate(Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY); |
|
438 yield task_test_date_liveupdate(Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY); |
|
439 |
|
440 // The remaining views are |
|
441 // RESULTS_AS_URI + SORT_BY_VISITCOUNT_DESCENDING |
|
442 // -> test_399266.js |
|
443 // RESULTS_AS_URI + SORT_BY_DATE_DESCENDING |
|
444 // -> test_385397.js |
|
445 }); |