1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/places/tests/unit/test_frecency.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,294 @@ 1.4 +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/** 1.11 + * Test for bug 406358 to make sure frecency works for empty input/search, but 1.12 + * this also tests for non-empty inputs as well. Because the interactions among 1.13 + * *DIFFERENT* visit counts and visit dates is not well defined, this test 1.14 + * holds one of the two values constant when modifying the other. 1.15 + * 1.16 + * Also test bug 419068 to make sure tagged pages don't necessarily have to be 1.17 + * first in the results. 1.18 + * 1.19 + * Also test bug 426166 to make sure that the results of autocomplete searches 1.20 + * are stable. Note that failures of this test will be intermittent by nature 1.21 + * since we are testing to make sure that the unstable sort algorithm used 1.22 + * by SQLite is not changing the order of the results on us. 1.23 + */ 1.24 + 1.25 +function AutoCompleteInput(aSearches) { 1.26 + this.searches = aSearches; 1.27 +} 1.28 +AutoCompleteInput.prototype = { 1.29 + constructor: AutoCompleteInput, 1.30 + 1.31 + searches: null, 1.32 + 1.33 + minResultsForPopup: 0, 1.34 + timeout: 10, 1.35 + searchParam: "", 1.36 + textValue: "", 1.37 + disableAutoComplete: false, 1.38 + completeDefaultIndex: false, 1.39 + 1.40 + get searchCount() { 1.41 + return this.searches.length; 1.42 + }, 1.43 + 1.44 + getSearchAt: function(aIndex) { 1.45 + return this.searches[aIndex]; 1.46 + }, 1.47 + 1.48 + onSearchBegin: function() {}, 1.49 + onSearchComplete: function() {}, 1.50 + 1.51 + popupOpen: false, 1.52 + 1.53 + popup: { 1.54 + setSelectedIndex: function(aIndex) {}, 1.55 + invalidate: function() {}, 1.56 + 1.57 + // nsISupports implementation 1.58 + QueryInterface: function(iid) { 1.59 + if (iid.equals(Ci.nsISupports) || 1.60 + iid.equals(Ci.nsIAutoCompletePopup)) 1.61 + return this; 1.62 + 1.63 + throw Components.results.NS_ERROR_NO_INTERFACE; 1.64 + } 1.65 + }, 1.66 + 1.67 + // nsISupports implementation 1.68 + QueryInterface: function(iid) { 1.69 + if (iid.equals(Ci.nsISupports) || 1.70 + iid.equals(Ci.nsIAutoCompleteInput)) 1.71 + return this; 1.72 + 1.73 + throw Components.results.NS_ERROR_NO_INTERFACE; 1.74 + } 1.75 +} 1.76 + 1.77 +function ensure_results(uris, searchTerm) 1.78 +{ 1.79 + promiseAsyncUpdates().then(function () ensure_results_internal(uris, 1.80 + searchTerm)); 1.81 +} 1.82 + 1.83 +function ensure_results_internal(uris, searchTerm) 1.84 +{ 1.85 + var controller = Components.classes["@mozilla.org/autocomplete/controller;1"]. 1.86 + getService(Components.interfaces.nsIAutoCompleteController); 1.87 + 1.88 + // Make an AutoCompleteInput that uses our searches 1.89 + // and confirms results on search complete 1.90 + var input = new AutoCompleteInput(["history"]); 1.91 + 1.92 + controller.input = input; 1.93 + 1.94 + var numSearchesStarted = 0; 1.95 + input.onSearchBegin = function() { 1.96 + numSearchesStarted++; 1.97 + do_check_eq(numSearchesStarted, 1); 1.98 + }; 1.99 + 1.100 + input.onSearchComplete = function() { 1.101 + do_check_eq(numSearchesStarted, 1); 1.102 + do_check_eq(controller.searchStatus, 1.103 + Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH); 1.104 + do_check_eq(controller.matchCount, uris.length); 1.105 + for (var i=0; i<controller.matchCount; i++) { 1.106 + do_check_eq(controller.getValueAt(i), uris[i].spec); 1.107 + } 1.108 + 1.109 + deferEnsureResults.resolve(); 1.110 + }; 1.111 + 1.112 + controller.startSearch(searchTerm); 1.113 +} 1.114 + 1.115 +// Get history service 1.116 +try { 1.117 + var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. 1.118 + getService(Ci.nsINavHistoryService); 1.119 + var bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory); 1.120 + var tagssvc = Cc["@mozilla.org/browser/tagging-service;1"]. 1.121 + getService(Ci.nsITaggingService); 1.122 + var bmksvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. 1.123 + getService(Ci.nsINavBookmarksService); 1.124 +} catch(ex) { 1.125 + do_throw("Could not get history service\n"); 1.126 +} 1.127 + 1.128 +function task_setCountDate(aURI, aCount, aDate) 1.129 +{ 1.130 + // We need visits so that frecency can be computed over multiple visits 1.131 + let visits = []; 1.132 + for (let i = 0; i < aCount; i++) { 1.133 + visits.push({ uri: aURI, visitDate: aDate, transition: TRANSITION_TYPED }); 1.134 + } 1.135 + yield promiseAddVisits(visits); 1.136 +} 1.137 + 1.138 +function setBookmark(aURI) 1.139 +{ 1.140 + bmksvc.insertBookmark(bmksvc.bookmarksMenuFolder, aURI, -1, "bleh"); 1.141 +} 1.142 + 1.143 +function tagURI(aURI, aTags) { 1.144 + bmksvc.insertBookmark(bmksvc.unfiledBookmarksFolder, aURI, 1.145 + bmksvc.DEFAULT_INDEX, "bleh"); 1.146 + tagssvc.tagURI(aURI, aTags); 1.147 +} 1.148 + 1.149 +var uri1 = uri("http://site.tld/1"); 1.150 +var uri2 = uri("http://site.tld/2"); 1.151 +var uri3 = uri("http://aaaaaaaaaa/1"); 1.152 +var uri4 = uri("http://aaaaaaaaaa/2"); 1.153 + 1.154 +// d1 is younger (should show up higher) than d2 (PRTime is in usecs not msec) 1.155 +// Make sure the dates fall into different frecency buckets 1.156 +var d1 = new Date(Date.now() - 1000 * 60 * 60) * 1000; 1.157 +var d2 = new Date(Date.now() - 1000 * 60 * 60 * 24 * 10) * 1000; 1.158 +// c1 is larger (should show up higher) than c2 1.159 +var c1 = 10; 1.160 +var c2 = 1; 1.161 + 1.162 +var tests = [ 1.163 +// test things without a search term 1.164 +function() { 1.165 + print("TEST-INFO | Test 0: same count, different date"); 1.166 + yield task_setCountDate(uri1, c1, d1); 1.167 + yield task_setCountDate(uri2, c1, d2); 1.168 + tagURI(uri1, ["site"]); 1.169 + ensure_results([uri1, uri2], ""); 1.170 +}, 1.171 +function() { 1.172 + print("TEST-INFO | Test 1: same count, different date"); 1.173 + yield task_setCountDate(uri1, c1, d2); 1.174 + yield task_setCountDate(uri2, c1, d1); 1.175 + tagURI(uri1, ["site"]); 1.176 + ensure_results([uri2, uri1], ""); 1.177 +}, 1.178 +function() { 1.179 + print("TEST-INFO | Test 2: different count, same date"); 1.180 + yield task_setCountDate(uri1, c1, d1); 1.181 + yield task_setCountDate(uri2, c2, d1); 1.182 + tagURI(uri1, ["site"]); 1.183 + ensure_results([uri1, uri2], ""); 1.184 +}, 1.185 +function() { 1.186 + print("TEST-INFO | Test 3: different count, same date"); 1.187 + yield task_setCountDate(uri1, c2, d1); 1.188 + yield task_setCountDate(uri2, c1, d1); 1.189 + tagURI(uri1, ["site"]); 1.190 + ensure_results([uri2, uri1], ""); 1.191 +}, 1.192 + 1.193 +// test things with a search term 1.194 +function() { 1.195 + print("TEST-INFO | Test 4: same count, different date"); 1.196 + yield task_setCountDate(uri1, c1, d1); 1.197 + yield task_setCountDate(uri2, c1, d2); 1.198 + tagURI(uri1, ["site"]); 1.199 + ensure_results([uri1, uri2], "site"); 1.200 +}, 1.201 +function() { 1.202 + print("TEST-INFO | Test 5: same count, different date"); 1.203 + yield task_setCountDate(uri1, c1, d2); 1.204 + yield task_setCountDate(uri2, c1, d1); 1.205 + tagURI(uri1, ["site"]); 1.206 + ensure_results([uri2, uri1], "site"); 1.207 +}, 1.208 +function() { 1.209 + print("TEST-INFO | Test 6: different count, same date"); 1.210 + yield task_setCountDate(uri1, c1, d1); 1.211 + yield task_setCountDate(uri2, c2, d1); 1.212 + tagURI(uri1, ["site"]); 1.213 + ensure_results([uri1, uri2], "site"); 1.214 +}, 1.215 +function() { 1.216 + print("TEST-INFO | Test 7: different count, same date"); 1.217 + yield task_setCountDate(uri1, c2, d1); 1.218 + yield task_setCountDate(uri2, c1, d1); 1.219 + tagURI(uri1, ["site"]); 1.220 + ensure_results([uri2, uri1], "site"); 1.221 +}, 1.222 +// There are multiple tests for 8, hence the multiple functions 1.223 +// Bug 426166 section 1.224 +function() { 1.225 + print("TEST-INFO | Test 8.1a: same count, same date"); 1.226 + setBookmark(uri3); 1.227 + setBookmark(uri4); 1.228 + ensure_results([uri4, uri3], "a"); 1.229 +}, 1.230 +function() { 1.231 + print("TEST-INFO | Test 8.1b: same count, same date"); 1.232 + setBookmark(uri3); 1.233 + setBookmark(uri4); 1.234 + ensure_results([uri4, uri3], "aa"); 1.235 +}, 1.236 +function() { 1.237 + print("TEST-INFO | Test 8.2: same count, same date"); 1.238 + setBookmark(uri3); 1.239 + setBookmark(uri4); 1.240 + ensure_results([uri4, uri3], "aaa"); 1.241 +}, 1.242 +function() { 1.243 + print("TEST-INFO | Test 8.3: same count, same date"); 1.244 + setBookmark(uri3); 1.245 + setBookmark(uri4); 1.246 + ensure_results([uri4, uri3], "aaaa"); 1.247 +}, 1.248 +function() { 1.249 + print("TEST-INFO | Test 8.4: same count, same date"); 1.250 + setBookmark(uri3); 1.251 + setBookmark(uri4); 1.252 + ensure_results([uri4, uri3], "aaa"); 1.253 +}, 1.254 +function() { 1.255 + print("TEST-INFO | Test 8.5: same count, same date"); 1.256 + setBookmark(uri3); 1.257 + setBookmark(uri4); 1.258 + ensure_results([uri4, uri3], "aa"); 1.259 +}, 1.260 +function() { 1.261 + print("TEST-INFO | Test 8.6: same count, same date"); 1.262 + setBookmark(uri3); 1.263 + setBookmark(uri4); 1.264 + ensure_results([uri4, uri3], "a"); 1.265 +} 1.266 +]; 1.267 + 1.268 +/** 1.269 + * This deferred object contains a promise that is resolved when the 1.270 + * ensure_results_internal function has finished its execution. 1.271 + */ 1.272 +let deferEnsureResults; 1.273 + 1.274 +/** 1.275 + * Test adaptive autocomplete 1.276 + */ 1.277 +function run_test() 1.278 +{ 1.279 + run_next_test(); 1.280 +} 1.281 + 1.282 +add_task(function test_frecency() 1.283 +{ 1.284 + // always search in history + bookmarks, no matter what the default is 1.285 + var prefs = Cc["@mozilla.org/preferences-service;1"]. 1.286 + getService(Ci.nsIPrefBranch); 1.287 + prefs.setIntPref("browser.urlbar.search.sources", 3); 1.288 + prefs.setIntPref("browser.urlbar.default.behavior", 0); 1.289 + for (let [, test] in Iterator(tests)) { 1.290 + remove_all_bookmarks(); 1.291 + yield promiseClearHistory(); 1.292 + 1.293 + deferEnsureResults = Promise.defer(); 1.294 + yield test(); 1.295 + yield deferEnsureResults.promise; 1.296 + } 1.297 +});