|
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 /** |
|
8 * Test for bug 406358 to make sure frecency works for empty input/search, but |
|
9 * this also tests for non-empty inputs as well. Because the interactions among |
|
10 * *DIFFERENT* visit counts and visit dates is not well defined, this test |
|
11 * holds one of the two values constant when modifying the other. |
|
12 * |
|
13 * Also test bug 419068 to make sure tagged pages don't necessarily have to be |
|
14 * first in the results. |
|
15 * |
|
16 * Also test bug 426166 to make sure that the results of autocomplete searches |
|
17 * are stable. Note that failures of this test will be intermittent by nature |
|
18 * since we are testing to make sure that the unstable sort algorithm used |
|
19 * by SQLite is not changing the order of the results on us. |
|
20 */ |
|
21 |
|
22 function AutoCompleteInput(aSearches) { |
|
23 this.searches = aSearches; |
|
24 } |
|
25 AutoCompleteInput.prototype = { |
|
26 constructor: AutoCompleteInput, |
|
27 |
|
28 searches: null, |
|
29 |
|
30 minResultsForPopup: 0, |
|
31 timeout: 10, |
|
32 searchParam: "", |
|
33 textValue: "", |
|
34 disableAutoComplete: false, |
|
35 completeDefaultIndex: false, |
|
36 |
|
37 get searchCount() { |
|
38 return this.searches.length; |
|
39 }, |
|
40 |
|
41 getSearchAt: function(aIndex) { |
|
42 return this.searches[aIndex]; |
|
43 }, |
|
44 |
|
45 onSearchBegin: function() {}, |
|
46 onSearchComplete: function() {}, |
|
47 |
|
48 popupOpen: false, |
|
49 |
|
50 popup: { |
|
51 setSelectedIndex: function(aIndex) {}, |
|
52 invalidate: function() {}, |
|
53 |
|
54 // nsISupports implementation |
|
55 QueryInterface: function(iid) { |
|
56 if (iid.equals(Ci.nsISupports) || |
|
57 iid.equals(Ci.nsIAutoCompletePopup)) |
|
58 return this; |
|
59 |
|
60 throw Components.results.NS_ERROR_NO_INTERFACE; |
|
61 } |
|
62 }, |
|
63 |
|
64 // nsISupports implementation |
|
65 QueryInterface: function(iid) { |
|
66 if (iid.equals(Ci.nsISupports) || |
|
67 iid.equals(Ci.nsIAutoCompleteInput)) |
|
68 return this; |
|
69 |
|
70 throw Components.results.NS_ERROR_NO_INTERFACE; |
|
71 } |
|
72 } |
|
73 |
|
74 function ensure_results(uris, searchTerm) |
|
75 { |
|
76 promiseAsyncUpdates().then(function () ensure_results_internal(uris, |
|
77 searchTerm)); |
|
78 } |
|
79 |
|
80 function ensure_results_internal(uris, searchTerm) |
|
81 { |
|
82 var controller = Components.classes["@mozilla.org/autocomplete/controller;1"]. |
|
83 getService(Components.interfaces.nsIAutoCompleteController); |
|
84 |
|
85 // Make an AutoCompleteInput that uses our searches |
|
86 // and confirms results on search complete |
|
87 var input = new AutoCompleteInput(["history"]); |
|
88 |
|
89 controller.input = input; |
|
90 |
|
91 var numSearchesStarted = 0; |
|
92 input.onSearchBegin = function() { |
|
93 numSearchesStarted++; |
|
94 do_check_eq(numSearchesStarted, 1); |
|
95 }; |
|
96 |
|
97 input.onSearchComplete = function() { |
|
98 do_check_eq(numSearchesStarted, 1); |
|
99 do_check_eq(controller.searchStatus, |
|
100 Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH); |
|
101 do_check_eq(controller.matchCount, uris.length); |
|
102 for (var i=0; i<controller.matchCount; i++) { |
|
103 do_check_eq(controller.getValueAt(i), uris[i].spec); |
|
104 } |
|
105 |
|
106 deferEnsureResults.resolve(); |
|
107 }; |
|
108 |
|
109 controller.startSearch(searchTerm); |
|
110 } |
|
111 |
|
112 // Get history service |
|
113 try { |
|
114 var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. |
|
115 getService(Ci.nsINavHistoryService); |
|
116 var bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory); |
|
117 var tagssvc = Cc["@mozilla.org/browser/tagging-service;1"]. |
|
118 getService(Ci.nsITaggingService); |
|
119 var bmksvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. |
|
120 getService(Ci.nsINavBookmarksService); |
|
121 } catch(ex) { |
|
122 do_throw("Could not get history service\n"); |
|
123 } |
|
124 |
|
125 function task_setCountDate(aURI, aCount, aDate) |
|
126 { |
|
127 // We need visits so that frecency can be computed over multiple visits |
|
128 let visits = []; |
|
129 for (let i = 0; i < aCount; i++) { |
|
130 visits.push({ uri: aURI, visitDate: aDate, transition: TRANSITION_TYPED }); |
|
131 } |
|
132 yield promiseAddVisits(visits); |
|
133 } |
|
134 |
|
135 function setBookmark(aURI) |
|
136 { |
|
137 bmksvc.insertBookmark(bmksvc.bookmarksMenuFolder, aURI, -1, "bleh"); |
|
138 } |
|
139 |
|
140 function tagURI(aURI, aTags) { |
|
141 bmksvc.insertBookmark(bmksvc.unfiledBookmarksFolder, aURI, |
|
142 bmksvc.DEFAULT_INDEX, "bleh"); |
|
143 tagssvc.tagURI(aURI, aTags); |
|
144 } |
|
145 |
|
146 var uri1 = uri("http://site.tld/1"); |
|
147 var uri2 = uri("http://site.tld/2"); |
|
148 var uri3 = uri("http://aaaaaaaaaa/1"); |
|
149 var uri4 = uri("http://aaaaaaaaaa/2"); |
|
150 |
|
151 // d1 is younger (should show up higher) than d2 (PRTime is in usecs not msec) |
|
152 // Make sure the dates fall into different frecency buckets |
|
153 var d1 = new Date(Date.now() - 1000 * 60 * 60) * 1000; |
|
154 var d2 = new Date(Date.now() - 1000 * 60 * 60 * 24 * 10) * 1000; |
|
155 // c1 is larger (should show up higher) than c2 |
|
156 var c1 = 10; |
|
157 var c2 = 1; |
|
158 |
|
159 var tests = [ |
|
160 // test things without a search term |
|
161 function() { |
|
162 print("TEST-INFO | Test 0: same count, different date"); |
|
163 yield task_setCountDate(uri1, c1, d1); |
|
164 yield task_setCountDate(uri2, c1, d2); |
|
165 tagURI(uri1, ["site"]); |
|
166 ensure_results([uri1, uri2], ""); |
|
167 }, |
|
168 function() { |
|
169 print("TEST-INFO | Test 1: same count, different date"); |
|
170 yield task_setCountDate(uri1, c1, d2); |
|
171 yield task_setCountDate(uri2, c1, d1); |
|
172 tagURI(uri1, ["site"]); |
|
173 ensure_results([uri2, uri1], ""); |
|
174 }, |
|
175 function() { |
|
176 print("TEST-INFO | Test 2: different count, same date"); |
|
177 yield task_setCountDate(uri1, c1, d1); |
|
178 yield task_setCountDate(uri2, c2, d1); |
|
179 tagURI(uri1, ["site"]); |
|
180 ensure_results([uri1, uri2], ""); |
|
181 }, |
|
182 function() { |
|
183 print("TEST-INFO | Test 3: different count, same date"); |
|
184 yield task_setCountDate(uri1, c2, d1); |
|
185 yield task_setCountDate(uri2, c1, d1); |
|
186 tagURI(uri1, ["site"]); |
|
187 ensure_results([uri2, uri1], ""); |
|
188 }, |
|
189 |
|
190 // test things with a search term |
|
191 function() { |
|
192 print("TEST-INFO | Test 4: same count, different date"); |
|
193 yield task_setCountDate(uri1, c1, d1); |
|
194 yield task_setCountDate(uri2, c1, d2); |
|
195 tagURI(uri1, ["site"]); |
|
196 ensure_results([uri1, uri2], "site"); |
|
197 }, |
|
198 function() { |
|
199 print("TEST-INFO | Test 5: same count, different date"); |
|
200 yield task_setCountDate(uri1, c1, d2); |
|
201 yield task_setCountDate(uri2, c1, d1); |
|
202 tagURI(uri1, ["site"]); |
|
203 ensure_results([uri2, uri1], "site"); |
|
204 }, |
|
205 function() { |
|
206 print("TEST-INFO | Test 6: different count, same date"); |
|
207 yield task_setCountDate(uri1, c1, d1); |
|
208 yield task_setCountDate(uri2, c2, d1); |
|
209 tagURI(uri1, ["site"]); |
|
210 ensure_results([uri1, uri2], "site"); |
|
211 }, |
|
212 function() { |
|
213 print("TEST-INFO | Test 7: different count, same date"); |
|
214 yield task_setCountDate(uri1, c2, d1); |
|
215 yield task_setCountDate(uri2, c1, d1); |
|
216 tagURI(uri1, ["site"]); |
|
217 ensure_results([uri2, uri1], "site"); |
|
218 }, |
|
219 // There are multiple tests for 8, hence the multiple functions |
|
220 // Bug 426166 section |
|
221 function() { |
|
222 print("TEST-INFO | Test 8.1a: same count, same date"); |
|
223 setBookmark(uri3); |
|
224 setBookmark(uri4); |
|
225 ensure_results([uri4, uri3], "a"); |
|
226 }, |
|
227 function() { |
|
228 print("TEST-INFO | Test 8.1b: same count, same date"); |
|
229 setBookmark(uri3); |
|
230 setBookmark(uri4); |
|
231 ensure_results([uri4, uri3], "aa"); |
|
232 }, |
|
233 function() { |
|
234 print("TEST-INFO | Test 8.2: same count, same date"); |
|
235 setBookmark(uri3); |
|
236 setBookmark(uri4); |
|
237 ensure_results([uri4, uri3], "aaa"); |
|
238 }, |
|
239 function() { |
|
240 print("TEST-INFO | Test 8.3: same count, same date"); |
|
241 setBookmark(uri3); |
|
242 setBookmark(uri4); |
|
243 ensure_results([uri4, uri3], "aaaa"); |
|
244 }, |
|
245 function() { |
|
246 print("TEST-INFO | Test 8.4: same count, same date"); |
|
247 setBookmark(uri3); |
|
248 setBookmark(uri4); |
|
249 ensure_results([uri4, uri3], "aaa"); |
|
250 }, |
|
251 function() { |
|
252 print("TEST-INFO | Test 8.5: same count, same date"); |
|
253 setBookmark(uri3); |
|
254 setBookmark(uri4); |
|
255 ensure_results([uri4, uri3], "aa"); |
|
256 }, |
|
257 function() { |
|
258 print("TEST-INFO | Test 8.6: same count, same date"); |
|
259 setBookmark(uri3); |
|
260 setBookmark(uri4); |
|
261 ensure_results([uri4, uri3], "a"); |
|
262 } |
|
263 ]; |
|
264 |
|
265 /** |
|
266 * This deferred object contains a promise that is resolved when the |
|
267 * ensure_results_internal function has finished its execution. |
|
268 */ |
|
269 let deferEnsureResults; |
|
270 |
|
271 /** |
|
272 * Test adaptive autocomplete |
|
273 */ |
|
274 function run_test() |
|
275 { |
|
276 run_next_test(); |
|
277 } |
|
278 |
|
279 add_task(function test_frecency() |
|
280 { |
|
281 // always search in history + bookmarks, no matter what the default is |
|
282 var prefs = Cc["@mozilla.org/preferences-service;1"]. |
|
283 getService(Ci.nsIPrefBranch); |
|
284 prefs.setIntPref("browser.urlbar.search.sources", 3); |
|
285 prefs.setIntPref("browser.urlbar.default.behavior", 0); |
|
286 for (let [, test] in Iterator(tests)) { |
|
287 remove_all_bookmarks(); |
|
288 yield promiseClearHistory(); |
|
289 |
|
290 deferEnsureResults = Promise.defer(); |
|
291 yield test(); |
|
292 yield deferEnsureResults.promise; |
|
293 } |
|
294 }); |