diff options
Diffstat (limited to 'browser/base/content/test/general/contentSearchUI.js')
-rw-r--r-- | browser/base/content/test/general/contentSearchUI.js | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/browser/base/content/test/general/contentSearchUI.js b/browser/base/content/test/general/contentSearchUI.js new file mode 100644 index 000000000..0e46230a2 --- /dev/null +++ b/browser/base/content/test/general/contentSearchUI.js @@ -0,0 +1,209 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +(function () { + +const TEST_MSG = "ContentSearchUIControllerTest"; +const ENGINE_NAME = "browser_searchSuggestionEngine searchSuggestionEngine.xml"; +var gController; + +addMessageListener(TEST_MSG, msg => { + messageHandlers[msg.data.type](msg.data.data); +}); + +var messageHandlers = { + + init: function() { + Services.search.currentEngine = Services.search.getEngineByName(ENGINE_NAME); + let input = content.document.querySelector("input"); + gController = + new content.ContentSearchUIController(input, input.parentNode, "test", "test"); + content.addEventListener("ContentSearchService", function listener(aEvent) { + if (aEvent.detail.type == "State" && + gController.defaultEngine.name == ENGINE_NAME) { + content.removeEventListener("ContentSearchService", listener); + ack("init"); + } + }); + gController.remoteTimeout = 5000; + }, + + key: function (arg) { + let keyName = typeof(arg) == "string" ? arg : arg.key; + content.synthesizeKey(keyName, arg.modifiers || {}); + let wait = arg.waitForSuggestions ? waitForSuggestions : cb => cb(); + wait(ack.bind(null, "key")); + }, + + startComposition: function (arg) { + content.synthesizeComposition({ type: "compositionstart", data: "" }); + ack("startComposition"); + }, + + changeComposition: function (arg) { + let data = typeof(arg) == "string" ? arg : arg.data; + content.synthesizeCompositionChange({ + composition: { + string: data, + clauses: [ + { length: data.length, attr: content.COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + caret: { start: data.length, length: 0 } + }); + let wait = arg.waitForSuggestions ? waitForSuggestions : cb => cb(); + wait(ack.bind(null, "changeComposition")); + }, + + commitComposition: function () { + content.synthesizeComposition({ type: "compositioncommitasis" }); + ack("commitComposition"); + }, + + focus: function () { + gController.input.focus(); + ack("focus"); + }, + + blur: function () { + gController.input.blur(); + ack("blur"); + }, + + waitForSearch: function () { + waitForContentSearchEvent("Search", aData => ack("waitForSearch", aData)); + }, + + waitForSearchSettings: function () { + waitForContentSearchEvent("ManageEngines", + aData => ack("waitForSearchSettings", aData)); + }, + + mousemove: function (itemIndex) { + let row; + if (itemIndex == -1) { + row = gController._table.firstChild; + } + else { + let allElts = [...gController._suggestionsList.children, + ...gController._oneOffButtons, + content.document.getElementById("contentSearchSettingsButton")]; + row = allElts[itemIndex]; + } + let event = { + type: "mousemove", + clickcount: 0, + } + row.addEventListener("mousemove", function handler() { + row.removeEventListener("mousemove", handler); + ack("mousemove"); + }); + content.synthesizeMouseAtCenter(row, event); + }, + + click: function (arg) { + let eltIdx = typeof(arg) == "object" ? arg.eltIdx : arg; + let row; + if (eltIdx == -1) { + row = gController._table.firstChild; + } + else { + let allElts = [...gController._suggestionsList.children, + ...gController._oneOffButtons, + content.document.getElementById("contentSearchSettingsButton")]; + row = allElts[eltIdx]; + } + let event = arg.modifiers || {}; + // synthesizeMouseAtCenter defaults to sending a mousedown followed by a + // mouseup if the event type is not specified. + content.synthesizeMouseAtCenter(row, event); + ack("click"); + }, + + addInputValueToFormHistory: function () { + gController.addInputValueToFormHistory(); + ack("addInputValueToFormHistory"); + }, + + addDuplicateOneOff: function () { + let btn = gController._oneOffButtons[gController._oneOffButtons.length - 1]; + let newBtn = btn.cloneNode(true); + btn.parentNode.appendChild(newBtn); + gController._oneOffButtons.push(newBtn); + ack("addDuplicateOneOff"); + }, + + removeLastOneOff: function () { + gController._oneOffButtons.pop().remove(); + ack("removeLastOneOff"); + }, + + reset: function () { + // Reset both the input and suggestions by select all + delete. If there was + // no text entered, this won't have any effect, so also escape to ensure the + // suggestions table is closed. + gController.input.focus(); + content.synthesizeKey("a", { accelKey: true }); + content.synthesizeKey("VK_DELETE", {}); + content.synthesizeKey("VK_ESCAPE", {}); + ack("reset"); + }, +}; + +function ack(aType, aData) { + sendAsyncMessage(TEST_MSG, { type: aType, data: aData || currentState() }); +} + +function waitForSuggestions(cb) { + let observer = new content.MutationObserver(() => { + if (gController.input.getAttribute("aria-expanded") == "true") { + observer.disconnect(); + cb(); + } + }); + observer.observe(gController.input, { + attributes: true, + attributeFilter: ["aria-expanded"], + }); +} + +function waitForContentSearchEvent(messageType, cb) { + let mm = content.SpecialPowers.Cc["@mozilla.org/globalmessagemanager;1"]. + getService(content.SpecialPowers.Ci.nsIMessageListenerManager); + mm.addMessageListener("ContentSearch", function listener(aMsg) { + if (aMsg.data.type != messageType) { + return; + } + mm.removeMessageListener("ContentSearch", listener); + cb(aMsg.data.data); + }); +} + +function currentState() { + let state = { + selectedIndex: gController.selectedIndex, + selectedButtonIndex: gController.selectedButtonIndex, + numSuggestions: gController._table.hidden ? 0 : gController.numSuggestions, + suggestionAtIndex: [], + isFormHistorySuggestionAtIndex: [], + + tableHidden: gController._table.hidden, + + inputValue: gController.input.value, + ariaExpanded: gController.input.getAttribute("aria-expanded"), + }; + + if (state.numSuggestions) { + for (let i = 0; i < gController.numSuggestions; i++) { + state.suggestionAtIndex.push(gController.suggestionAtIndex(i)); + state.isFormHistorySuggestionAtIndex.push( + gController.isFormHistorySuggestionAtIndex(i)); + } + } + + return state; +} + +})(); |