diff -r 000000000000 -r 6474c204b198 toolkit/components/places/tests/inline/head_autocomplete.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolkit/components/places/tests/inline/head_autocomplete.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,199 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +} + +// Put any other stuff relative to this test folder below. + +XPCOMUtils.defineLazyServiceGetter(this, "gHistory", + "@mozilla.org/browser/history;1", + "mozIAsyncHistory"); + +/** + * @param aSearches + * Array of AutoCompleteSearch names. + */ +function AutoCompleteInput(aSearches) { + this.searches = aSearches; +} +AutoCompleteInput.prototype = { + searches: null, + minResultsForPopup: 0, + timeout: 10, + searchParam: "", + textValue: "", + disableAutoComplete: false, + + completeDefaultIndex: true, + defaultIndex: 0, + + // Text selection range + _selStart: 0, + _selEnd: 0, + get selectionStart() { + return this._selStart; + }, + get selectionEnd() { + return this._selEnd; + }, + selectTextRange: function(aStart, aEnd) { + this._selStart = aStart; + this._selEnd = aEnd; + }, + + onTextEntered: function() false, + onTextReverted: function() false, + + get searchCount() { + return this.searches.length; + }, + getSearchAt: function(aIndex) { + return this.searches[aIndex]; + }, + + onSearchBegin: function () {}, + onSearchComplete: function () {}, + + popupOpen: false, + + popup: { + selectedIndex: -1, + invalidate: function () {}, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompletePopup]) + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteInput]) +} + +/** + * @param aSearchString + * String to search. + * @param aExpectedValue + * Expected value returned by autoFill. + * May be a string, or an object like + * { + * autoFilled: the value suggested by autofill, + * completed: the value completed on user's confirmation + * } + * In the latter case this will also check that on user's confirmation + * the result's casing is correctly applied. + */ +function ensure_results(aSearchString, aExpectedValue) { + let autoFilledValue, completedValue; + if (typeof(aExpectedValue) == "string") { + autoFilledValue = aExpectedValue; + } + else { + autoFilledValue = aExpectedValue.autoFilled; + completedValue = aExpectedValue.completed; + } + + // Make an AutoCompleteInput that uses our searches and confirms results. + let input = new AutoCompleteInput(["urlinline"]); + input.textValue = aSearchString; + + // Caret must be at the end for autoFill to happen. + let strLen = aSearchString.length; + input.selectTextRange(strLen, strLen); + do_check_eq(input.selectionStart, strLen); + do_check_eq(input.selectionEnd, strLen); + + let controller = Cc["@mozilla.org/autocomplete/controller;1"]. + getService(Ci.nsIAutoCompleteController); + controller.input = input; + + let numSearchesStarted = 0; + input.onSearchBegin = function() { + numSearchesStarted++; + do_check_eq(numSearchesStarted, 1); + }; + + input.onSearchComplete = function() { + // We should be running only one query. + do_check_eq(numSearchesStarted, 1); + + // Check the autoFilled result. + do_check_eq(input.textValue, autoFilledValue); + + if (completedValue) { + // Now force completion and check correct casing of the result. + // This ensures the controller is able to do its magic case-preserving + // stuff and correct replacement of the user's casing with result's one. + controller.handleEnter(false); + do_check_eq(input.textValue, completedValue); + } + + waitForCleanup(run_next_test); + }; + + do_log_info("Searching for: '" + aSearchString + "'"); + controller.startSearch(aSearchString); +} + +function run_test() { + do_register_cleanup(function () { + Services.prefs.clearUserPref("browser.urlbar.autocomplete.enabled"); + Services.prefs.clearUserPref("browser.urlbar.autoFill"); + Services.prefs.clearUserPref("browser.urlbar.autoFill.typed"); + }); + + gAutoCompleteTests.forEach(function (testData) { + let [description, searchString, expectedValue, setupFunc] = testData; + add_test(function () { + do_log_info(description); + Services.prefs.setBoolPref("browser.urlbar.autocomplete.enabled", true); + Services.prefs.setBoolPref("browser.urlbar.autoFill", true); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + + if (setupFunc) { + setupFunc(); + } + + // At this point frecency could still be updating due to latest pages + // updates. + // This is not a problem in real life, but autocomplete tests should + // return reliable resultsets, thus we have to wait. + promiseAsyncUpdates().then(function () ensure_results(searchString, + expectedValue)); + }) + }, this); + + run_next_test(); +} + +let gAutoCompleteTests = []; +function add_autocomplete_test(aTestData) { + gAutoCompleteTests.push(aTestData); +} + +function waitForCleanup(aCallback) { + remove_all_bookmarks(); + promiseClearHistory().then(aCallback); +} + +function addBookmark(aBookmarkObj) { + do_check_true(!!aBookmarkObj.url); + let parentId = aBookmarkObj.parentId ? aBookmarkObj.parentId + : PlacesUtils.unfiledBookmarksFolderId; + let itemId = PlacesUtils.bookmarks + .insertBookmark(parentId, + NetUtil.newURI(aBookmarkObj.url), + PlacesUtils.bookmarks.DEFAULT_INDEX, + "A bookmark"); + if (aBookmarkObj.keyword) { + PlacesUtils.bookmarks.setKeywordForBookmark(itemId, aBookmarkObj.keyword); + } +}