michael@0: /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * Dummy nsIAutoCompleteInput source that returns michael@0: * the given list of AutoCompleteSearch names. michael@0: * michael@0: * Implements only the methods needed for this test. michael@0: */ michael@0: function AutoCompleteInput(aSearches) { michael@0: this.searches = aSearches; michael@0: } michael@0: AutoCompleteInput.prototype = { michael@0: constructor: AutoCompleteInput, michael@0: michael@0: // Array of AutoCompleteSearch names michael@0: searches: null, michael@0: michael@0: minResultsForPopup: 0, michael@0: timeout: 10, michael@0: searchParam: "", michael@0: textValue: "", michael@0: disableAutoComplete: false, michael@0: completeDefaultIndex: false, michael@0: michael@0: get searchCount() { michael@0: return this.searches.length; michael@0: }, michael@0: michael@0: getSearchAt: function(aIndex) { michael@0: return this.searches[aIndex]; michael@0: }, michael@0: michael@0: onSearchBegin: function() {}, michael@0: onSearchComplete: function() {}, michael@0: michael@0: popupOpen: false, michael@0: michael@0: popup: { michael@0: setSelectedIndex: function(aIndex) {}, michael@0: invalidate: function() {}, michael@0: michael@0: // nsISupports implementation michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsISupports) || michael@0: iid.equals(Ci.nsIAutoCompletePopup)) michael@0: return this; michael@0: michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: } michael@0: }, michael@0: michael@0: // nsISupports implementation michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsISupports) || michael@0: iid.equals(Ci.nsIAutoCompleteInput)) michael@0: return this; michael@0: michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: } michael@0: } michael@0: michael@0: michael@0: michael@0: /** michael@0: * nsIAutoCompleteResult implementation michael@0: */ michael@0: function AutoCompleteResult(aValues, aComments, aStyles) { michael@0: this._values = aValues; michael@0: this._comments = aComments; michael@0: this._styles = aStyles; michael@0: } michael@0: AutoCompleteResult.prototype = { michael@0: constructor: AutoCompleteResult, michael@0: michael@0: // Arrays michael@0: _values: null, michael@0: _comments: null, michael@0: _styles: null, michael@0: michael@0: searchString: "", michael@0: searchResult: null, michael@0: michael@0: defaultIndex: 0, michael@0: michael@0: get matchCount() { michael@0: return this._values.length; michael@0: }, michael@0: michael@0: getValueAt: function(aIndex) { michael@0: return this._values[aIndex]; michael@0: }, michael@0: michael@0: getLabelAt: function(aIndex) { michael@0: return this.getValueAt(aIndex); michael@0: }, michael@0: michael@0: getCommentAt: function(aIndex) { michael@0: return this._comments[aIndex]; michael@0: }, michael@0: michael@0: getStyleAt: function(aIndex) { michael@0: return this._styles[aIndex]; michael@0: }, michael@0: michael@0: getImageAt: function(aIndex) { michael@0: return ""; michael@0: }, michael@0: michael@0: getFinalCompleteValueAt: function(aIndex) { michael@0: return this.getValueAt(aIndex); michael@0: }, michael@0: michael@0: removeValueAt: function (aRowIndex, aRemoveFromDb) {}, michael@0: michael@0: // nsISupports implementation michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsISupports) || michael@0: iid.equals(Ci.nsIAutoCompleteResult)) michael@0: return this; michael@0: michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: } michael@0: } michael@0: michael@0: michael@0: michael@0: /** michael@0: * nsIAutoCompleteSearch implementation that always returns michael@0: * the same result set. michael@0: */ michael@0: function AutoCompleteSearch(aName, aResult) { michael@0: this.name = aName; michael@0: this._result = aResult; michael@0: } michael@0: AutoCompleteSearch.prototype = { michael@0: constructor: AutoCompleteSearch, michael@0: michael@0: // Search name. Used by AutoCompleteController michael@0: name: null, michael@0: michael@0: // AutoCompleteResult michael@0: _result:null, michael@0: michael@0: michael@0: /** michael@0: * Return the same result set for every search michael@0: */ michael@0: startSearch: function(aSearchString, michael@0: aSearchParam, michael@0: aPreviousResult, michael@0: aListener) michael@0: { michael@0: var result = this._result; michael@0: if (result._values.length > 0) { michael@0: result.searchResult = Ci.nsIAutoCompleteResult.RESULT_SUCCESS_ONGOING; michael@0: } else { michael@0: result.searchResult = Ci.nsIAutoCompleteResult.RESULT_NOMATCH_ONGOING; michael@0: } michael@0: aListener.onSearchResult(this, result); michael@0: michael@0: if (result._values.length > 0) { michael@0: result.searchResult = Ci.nsIAutoCompleteResult.RESULT_SUCCESS; michael@0: } else { michael@0: result.searchResult = Ci.nsIAutoCompleteResult.RESULT_NOMATCH; michael@0: } michael@0: aListener.onSearchResult(this, result); michael@0: }, michael@0: michael@0: stopSearch: function() {}, michael@0: michael@0: // nsISupports implementation michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsISupports) || michael@0: iid.equals(Ci.nsIFactory) || michael@0: iid.equals(Ci.nsIAutoCompleteSearch)) michael@0: return this; michael@0: michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: // nsIFactory implementation michael@0: createInstance: function(outer, iid) { michael@0: return this.QueryInterface(iid); michael@0: } michael@0: } michael@0: michael@0: michael@0: michael@0: /** michael@0: * Helper to register an AutoCompleteSearch with the given name. michael@0: * Allows the AutoCompleteController to find the search. michael@0: */ michael@0: function registerAutoCompleteSearch(aSearch) { michael@0: var name = "@mozilla.org/autocomplete/search;1?name=" + aSearch.name; michael@0: michael@0: var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]. michael@0: getService(Ci.nsIUUIDGenerator); michael@0: var cid = uuidGenerator.generateUUID(); michael@0: michael@0: var desc = "Test AutoCompleteSearch"; michael@0: michael@0: var componentManager = Components.manager michael@0: .QueryInterface(Ci.nsIComponentRegistrar); michael@0: componentManager.registerFactory(cid, desc, name, aSearch); michael@0: michael@0: // Keep the id on the object so we can unregister later michael@0: aSearch.cid = cid; michael@0: } michael@0: michael@0: michael@0: michael@0: /** michael@0: * Helper to unregister an AutoCompleteSearch. michael@0: */ michael@0: function unregisterAutoCompleteSearch(aSearch) { michael@0: var componentManager = Components.manager michael@0: .QueryInterface(Ci.nsIComponentRegistrar); michael@0: componentManager.unregisterFactory(aSearch.cid, aSearch); michael@0: } michael@0: michael@0: michael@0: michael@0: /** michael@0: * Test AutoComplete with multiple AutoCompleteSearch sources. michael@0: */ michael@0: function run_test() { michael@0: var expected1 = ["1","2","3"]; michael@0: var expected2 = ["a","b","c"]; michael@0: var search1 = new AutoCompleteSearch("search1", michael@0: new AutoCompleteResult(expected1, [], [])); michael@0: var search2 = new AutoCompleteSearch("search2", michael@0: new AutoCompleteResult(expected2, [], [])); michael@0: michael@0: // Register searches so AutoCompleteController can find them michael@0: registerAutoCompleteSearch(search1); michael@0: registerAutoCompleteSearch(search2); michael@0: michael@0: var controller = Components.classes["@mozilla.org/autocomplete/controller;1"]. michael@0: getService(Components.interfaces.nsIAutoCompleteController); michael@0: michael@0: // Make an AutoCompleteInput that uses our searches michael@0: // and confirms results on search complete michael@0: var input = new AutoCompleteInput([search1.name, search2.name]); michael@0: var numSearchesStarted = 0; michael@0: michael@0: input.onSearchBegin = function() { michael@0: numSearchesStarted++; michael@0: do_check_eq(numSearchesStarted, 1); michael@0: }; michael@0: michael@0: input.onSearchComplete = function() { michael@0: michael@0: do_check_eq(numSearchesStarted, 1); michael@0: michael@0: do_check_eq(controller.searchStatus, michael@0: Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH); michael@0: do_check_eq(controller.matchCount, expected1.length + expected2.length); michael@0: michael@0: // Unregister searches michael@0: unregisterAutoCompleteSearch(search1); michael@0: unregisterAutoCompleteSearch(search2); michael@0: michael@0: do_test_finished(); michael@0: }; michael@0: michael@0: controller.input = input; michael@0: michael@0: // Search is asynchronous, so don't let the test finish immediately michael@0: do_test_pending(); michael@0: michael@0: controller.startSearch("test"); michael@0: }