toolkit/components/places/tests/autocomplete/head_autocomplete.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:848ac0e9d4ce
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 const Ci = Components.interfaces;
6 const Cc = Components.classes;
7 const Cr = Components.results;
8 const Cu = Components.utils;
9
10 Cu.import("resource://gre/modules/Services.jsm");
11
12 // Import common head.
13 let (commonFile = do_get_file("../head_common.js", false)) {
14 let uri = Services.io.newFileURI(commonFile);
15 Services.scriptloader.loadSubScript(uri.spec, this);
16 }
17
18 // Put any other stuff relative to this test folder below.
19
20
21 /**
22 * Header file for autocomplete testcases that create a set of pages with uris,
23 * titles, tags and tests that a given search term matches certain pages.
24 */
25
26 let current_test = 0;
27
28 function AutoCompleteInput(aSearches) {
29 this.searches = aSearches;
30 }
31 AutoCompleteInput.prototype = {
32 timeout: 10,
33 textValue: "",
34 searches: null,
35 searchParam: "",
36 popupOpen: false,
37 minResultsForPopup: 0,
38 invalidate: function() {},
39 disableAutoComplete: false,
40 completeDefaultIndex: false,
41 get popup() { return this; },
42 onSearchBegin: function() {},
43 onSearchComplete: function() {},
44 setSelectedIndex: function() {},
45 get searchCount() { return this.searches.length; },
46 getSearchAt: function(aIndex) this.searches[aIndex],
47 QueryInterface: XPCOMUtils.generateQI([
48 Ci.nsIAutoCompleteInput,
49 Ci.nsIAutoCompletePopup,
50 ])
51 };
52
53 function toURI(aSpec) {
54 return uri(aSpec);
55 }
56
57 let appendTags = true;
58 // Helper to turn off tag matching in results
59 function ignoreTags()
60 {
61 print("Ignoring tags from results");
62 appendTags = false;
63 }
64
65 function ensure_results(aSearch, aExpected)
66 {
67 let controller = Cc["@mozilla.org/autocomplete/controller;1"].
68 getService(Ci.nsIAutoCompleteController);
69
70 // Make an AutoCompleteInput that uses our searches
71 // and confirms results on search complete
72 let input = new AutoCompleteInput(["history"]);
73
74 controller.input = input;
75
76 if (typeof kSearchParam == "string")
77 input.searchParam = kSearchParam;
78
79 let numSearchesStarted = 0;
80 input.onSearchBegin = function() {
81 numSearchesStarted++;
82 do_check_eq(numSearchesStarted, 1);
83 };
84
85 input.onSearchComplete = function() {
86 do_check_eq(numSearchesStarted, 1);
87 aExpected = aExpected.slice();
88
89 // Check to see the expected uris and titles match up (in any order)
90 for (let i = 0; i < controller.matchCount; i++) {
91 let value = controller.getValueAt(i);
92 let comment = controller.getCommentAt(i);
93
94 print("Looking for '" + value + "', '" + comment + "' in expected results...");
95 let j;
96 for (j = 0; j < aExpected.length; j++) {
97 // Skip processed expected results
98 if (aExpected[j] == undefined)
99 continue;
100
101 let [uri, title, tags] = gPages[aExpected[j]];
102
103 // Load the real uri and titles and tags if necessary
104 uri = toURI(kURIs[uri]).spec;
105 title = kTitles[title];
106 if (tags && appendTags)
107 title += " \u2013 " + tags.map(function(aTag) kTitles[aTag]);
108 print("Checking against expected '" + uri + "', '" + title + "'...");
109
110 // Got a match on both uri and title?
111 if (uri == value && title == comment) {
112 print("Got it at index " + j + "!!");
113 // Make it undefined so we don't process it again
114 aExpected[j] = undefined;
115 break;
116 }
117 }
118
119 // We didn't hit the break, so we must have not found it
120 if (j == aExpected.length)
121 do_throw("Didn't find the current result ('" + value + "', '" + comment + "') in expected: " + aExpected);
122 }
123
124 // Make sure we have the right number of results
125 print("Expecting " + aExpected.length + " results; got " +
126 controller.matchCount + " results");
127 do_check_eq(controller.matchCount, aExpected.length);
128
129 // If we expect results, make sure we got matches
130 do_check_eq(controller.searchStatus, aExpected.length ?
131 Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH :
132 Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH);
133
134 // Fetch the next test if we have more
135 if (++current_test < gTests.length)
136 run_test();
137
138 do_test_finished();
139 };
140
141 print("Searching for.. '" + aSearch + "'");
142 controller.startSearch(aSearch);
143 }
144
145 // Get history services
146 var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
147 getService(Ci.nsINavHistoryService);
148 var bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory);
149 var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
150 getService(Ci.nsINavBookmarksService);
151 var tagsvc = Cc["@mozilla.org/browser/tagging-service;1"].
152 getService(Ci.nsITaggingService);
153 var iosvc = Cc["@mozilla.org/network/io-service;1"].
154 getService(Ci.nsIIOService);
155 var prefs = Cc["@mozilla.org/preferences-service;1"].
156 getService(Ci.nsIPrefBranch);
157
158 // Some date not too long ago
159 let gDate = new Date(Date.now() - 1000 * 60 * 60) * 1000;
160 // Store the page info for each uri
161 let gPages = [];
162
163 // Initialization tasks to be run before the next test
164 let gNextTestSetupTasks = [];
165
166 /**
167 * Adds a page, and creates various properties for it depending on the
168 * parameters passed in. This function will also add one visit, unless
169 * aNoVisit is true.
170 *
171 * @param aURI
172 * An index into kURIs that holds the string for the URI we are to add a
173 * page for.
174 * @param aTitle
175 * An index into kTitles that holds the string for the title we are to
176 * associate with the specified URI.
177 * @param aBook [optional]
178 * An index into kTitles that holds the string for the title we are to
179 * associate with the bookmark. If this is undefined, no bookmark is
180 * created.
181 * @param aTags [optional]
182 * An array of indexes into kTitles that hold the strings for the tags we
183 * are to associate with the URI. If this is undefined (or aBook is), no
184 * tags are added.
185 * @param aKey [optional]
186 * A string to associate as the keyword for this bookmark. aBook must be
187 * a valid index into kTitles for this to be checked and used.
188 * @param aTransitionType [optional]
189 * The transition type to use when adding the visit. The default is
190 * nsINavHistoryService::TRANSITION_LINK.
191 * @param aNoVisit [optional]
192 * If true, no visit is added for the URI. If false or undefined, a
193 * visit is added.
194 */
195 function addPageBook(aURI, aTitle, aBook, aTags, aKey, aTransitionType, aNoVisit)
196 {
197 gNextTestSetupTasks.push([task_addPageBook, arguments]);
198 }
199
200 function task_addPageBook(aURI, aTitle, aBook, aTags, aKey, aTransitionType, aNoVisit)
201 {
202 // Add a page entry for the current uri
203 gPages[aURI] = [aURI, aBook != undefined ? aBook : aTitle, aTags];
204
205 let uri = toURI(kURIs[aURI]);
206 let title = kTitles[aTitle];
207
208 let out = [aURI, aTitle, aBook, aTags, aKey];
209 out.push("\nuri=" + kURIs[aURI]);
210 out.push("\ntitle=" + title);
211
212 // Add the page and a visit if we need to
213 if (!aNoVisit) {
214 yield promiseAddVisits({
215 uri: uri,
216 transition: aTransitionType || TRANSITION_LINK,
217 visitDate: gDate,
218 title: title
219 });
220 out.push("\nwith visit");
221 }
222
223 // Add a bookmark if we need to
224 if (aBook != undefined) {
225 let book = kTitles[aBook];
226 let bmid = bmsvc.insertBookmark(bmsvc.unfiledBookmarksFolder, uri,
227 bmsvc.DEFAULT_INDEX, book);
228 out.push("\nbook=" + book);
229
230 // Add a keyword to the bookmark if we need to
231 if (aKey != undefined)
232 bmsvc.setKeywordForBookmark(bmid, aKey);
233
234 // Add tags if we need to
235 if (aTags != undefined && aTags.length > 0) {
236 // Convert each tag index into the title
237 let tags = aTags.map(function(aTag) kTitles[aTag]);
238 tagsvc.tagURI(uri, tags);
239 out.push("\ntags=" + tags);
240 }
241 }
242
243 print("\nAdding page/book/tag: " + out.join(", "));
244 }
245
246 function run_test() {
247 print("\n");
248 // always search in history + bookmarks, no matter what the default is
249 prefs.setIntPref("browser.urlbar.search.sources", 3);
250 prefs.setIntPref("browser.urlbar.default.behavior", 0);
251
252 // Search is asynchronous, so don't let the test finish immediately
253 do_test_pending();
254
255 // Load the test and print a description then run the test
256 let [description, search, expected, func] = gTests[current_test];
257 print(description);
258
259 // By default assume we want to match tags
260 appendTags = true;
261
262 // Do an extra function if necessary
263 if (func)
264 func();
265
266 Task.spawn(function () {
267 // Iterate over all tasks and execute them
268 for (let [, [fn, args]] in Iterator(gNextTestSetupTasks)) {
269 yield fn.apply(this, args);
270 };
271
272 // Clean up to allow tests to register more functions.
273 gNextTestSetupTasks = [];
274
275 // At this point frecency could still be updating due to latest pages
276 // updates. This is not a problem in real life, but autocomplete tests
277 // should return reliable resultsets, thus we have to wait.
278 yield promiseAsyncUpdates();
279
280 }).then(function () ensure_results(search, expected),
281 do_report_unexpected_exception);
282 }
283
284 // Utility function to remove history pages
285 function removePages(aURIs)
286 {
287 gNextTestSetupTasks.push([do_removePages, arguments]);
288 }
289
290 function do_removePages(aURIs)
291 {
292 for each (let uri in aURIs)
293 histsvc.removePage(toURI(kURIs[uri]));
294 }
295
296 // Utility function to mark pages as typed
297 function markTyped(aURIs, aTitle)
298 {
299 gNextTestSetupTasks.push([task_markTyped, arguments]);
300 }
301
302 function task_markTyped(aURIs, aTitle)
303 {
304 for (let uri of aURIs) {
305 yield promiseAddVisits({
306 uri: toURI(kURIs[uri]),
307 transition: TRANSITION_TYPED,
308 title: kTitles[aTitle]
309 });
310 }
311 }

mercurial