diff options
Diffstat (limited to 'browser/base/content/test/general/browser_contentSearchUI.js')
-rw-r--r-- | browser/base/content/test/general/browser_contentSearchUI.js | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/browser/base/content/test/general/browser_contentSearchUI.js b/browser/base/content/test/general/browser_contentSearchUI.js new file mode 100644 index 000000000..003f80aff --- /dev/null +++ b/browser/base/content/test/general/browser_contentSearchUI.js @@ -0,0 +1,771 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const TEST_PAGE_BASENAME = "contentSearchUI.html"; +const TEST_CONTENT_SCRIPT_BASENAME = "contentSearchUI.js"; +const TEST_ENGINE_PREFIX = "browser_searchSuggestionEngine"; +const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml"; +const TEST_ENGINE_2_BASENAME = "searchSuggestionEngine2.xml"; + +const TEST_MSG = "ContentSearchUIControllerTest"; + +requestLongerTimeout(2); + +add_task(function* emptyInput() { + yield setUp(); + + let state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("key", "VK_BACK_SPACE"); + checkState(state, "", [], -1); + + yield msg("reset"); +}); + +add_task(function* blur() { + yield setUp(); + + let state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("blur"); + checkState(state, "x", [], -1); + + yield msg("reset"); +}); + +add_task(function* upDownKeys() { + yield setUp(); + + let state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + // Cycle down the suggestions starting from no selection. + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoo", ["xfoo", "xbar"], 0); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xbar", ["xfoo", "xbar"], 1); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "x", ["xfoo", "xbar"], 2); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "x", ["xfoo", "xbar"], 3); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "x", ["xfoo", "xbar"], -1); + + // Cycle up starting from no selection. + state = yield msg("key", "VK_UP"); + checkState(state, "x", ["xfoo", "xbar"], 3); + + state = yield msg("key", "VK_UP"); + checkState(state, "x", ["xfoo", "xbar"], 2); + + state = yield msg("key", "VK_UP"); + checkState(state, "xbar", ["xfoo", "xbar"], 1); + + state = yield msg("key", "VK_UP"); + checkState(state, "xfoo", ["xfoo", "xbar"], 0); + + state = yield msg("key", "VK_UP"); + checkState(state, "x", ["xfoo", "xbar"], -1); + + yield msg("reset"); +}); + +add_task(function* rightLeftKeys() { + yield setUp(); + + let state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("key", "VK_LEFT"); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("key", "VK_LEFT"); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("key", "VK_RIGHT"); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("key", "VK_RIGHT"); + checkState(state, "x", [], -1); + + state = yield msg("key", { key: "VK_DOWN", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoo", ["xfoo", "xbar"], 0); + + // This should make the xfoo suggestion sticky. To make sure it sticks, + // trigger suggestions again and cycle through them by pressing Down until + // nothing is selected again. + state = yield msg("key", "VK_RIGHT"); + checkState(state, "xfoo", [], -1); + + state = yield msg("key", { key: "VK_DOWN", waitForSuggestions: true }); + checkState(state, "xfoo", ["xfoofoo", "xfoobar"], -1); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoofoo", ["xfoofoo", "xfoobar"], 0); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoobar", ["xfoofoo", "xfoobar"], 1); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoo", ["xfoofoo", "xfoobar"], 2); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoo", ["xfoofoo", "xfoobar"], 3); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoo", ["xfoofoo", "xfoobar"], -1); + + yield msg("reset"); +}); + +add_task(function* tabKey() { + yield setUp(); + yield msg("key", { key: "x", waitForSuggestions: true }); + + let state = yield msg("key", "VK_TAB"); + checkState(state, "x", ["xfoo", "xbar"], 2); + + state = yield msg("key", "VK_TAB"); + checkState(state, "x", ["xfoo", "xbar"], 3); + + state = yield msg("key", { key: "VK_TAB", modifiers: { shiftKey: true }}); + checkState(state, "x", ["xfoo", "xbar"], 2); + + state = yield msg("key", { key: "VK_TAB", modifiers: { shiftKey: true }}); + checkState(state, "x", [], -1); + + yield setUp(); + + yield msg("key", { key: "VK_DOWN", waitForSuggestions: true }); + + for (let i = 0; i < 3; ++i) { + state = yield msg("key", "VK_TAB"); + } + checkState(state, "x", [], -1); + + yield setUp(); + + yield msg("key", { key: "VK_DOWN", waitForSuggestions: true }); + state = yield msg("key", "VK_DOWN"); + checkState(state, "xfoo", ["xfoo", "xbar"], 0); + + state = yield msg("key", "VK_TAB"); + checkState(state, "xfoo", ["xfoo", "xbar"], 0, 0); + + state = yield msg("key", "VK_TAB"); + checkState(state, "xfoo", ["xfoo", "xbar"], 0, 1); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 1); + + state = yield msg("key", "VK_DOWN"); + checkState(state, "x", ["xfoo", "xbar"], 2); + + state = yield msg("key", "VK_UP"); + checkState(state, "xbar", ["xfoo", "xbar"], 1); + + state = yield msg("key", "VK_TAB"); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 0); + + state = yield msg("key", "VK_TAB"); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 1); + + state = yield msg("key", "VK_TAB"); + checkState(state, "xbar", [], -1); + + yield msg("reset"); +}); + +add_task(function* cycleSuggestions() { + yield setUp(); + yield msg("key", { key: "x", waitForSuggestions: true }); + + let cycle = Task.async(function* (aSelectedButtonIndex) { + let modifiers = { + shiftKey: true, + accelKey: true, + }; + + let state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex); + + state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, aSelectedButtonIndex); + + state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex); + + state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, aSelectedButtonIndex); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex); + }); + + yield cycle(); + + // Repeat with a one-off selected. + let state = yield msg("key", "VK_TAB"); + checkState(state, "x", ["xfoo", "xbar"], 2); + yield cycle(0); + + // Repeat with the settings button selected. + state = yield msg("key", "VK_TAB"); + checkState(state, "x", ["xfoo", "xbar"], 3); + yield cycle(1); + + yield msg("reset"); +}); + +add_task(function* cycleOneOffs() { + yield setUp(); + yield msg("key", { key: "x", waitForSuggestions: true }); + + yield msg("addDuplicateOneOff"); + + let state = yield msg("key", "VK_DOWN"); + state = yield msg("key", "VK_DOWN"); + checkState(state, "xbar", ["xfoo", "xbar"], 1); + + let modifiers = { + altKey: true, + }; + + state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 0); + + state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 1); + + state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 1); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 0); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1); + + // If the settings button is selected, pressing alt+up/down should select the + // last/first one-off respectively (and deselect the settings button). + yield msg("key", "VK_TAB"); + yield msg("key", "VK_TAB"); + state = yield msg("key", "VK_TAB"); // Settings button selected. + checkState(state, "xbar", ["xfoo", "xbar"], 1, 2); + + state = yield msg("key", { key: "VK_UP", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 1); + + state = yield msg("key", "VK_TAB"); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 2); + + state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers }); + checkState(state, "xbar", ["xfoo", "xbar"], 1, 0); + + yield msg("removeLastOneOff"); + yield msg("reset"); +}); + +add_task(function* mouse() { + yield setUp(); + + let state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("mousemove", 0); + checkState(state, "x", ["xfoo", "xbar"], 0); + + state = yield msg("mousemove", 1); + checkState(state, "x", ["xfoo", "xbar"], 1); + + state = yield msg("mousemove", 2); + checkState(state, "x", ["xfoo", "xbar"], 1, 0); + + state = yield msg("mousemove", 3); + checkState(state, "x", ["xfoo", "xbar"], 1, 1); + + state = yield msg("mousemove", -1); + checkState(state, "x", ["xfoo", "xbar"], 1); + + yield msg("reset"); + yield setUp(); + + state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + state = yield msg("mousemove", 0); + checkState(state, "x", ["xfoo", "xbar"], 0); + + state = yield msg("mousemove", 2); + checkState(state, "x", ["xfoo", "xbar"], 0, 0); + + state = yield msg("mousemove", -1); + checkState(state, "x", ["xfoo", "xbar"], 0); + + yield msg("reset"); +}); + +add_task(function* formHistory() { + yield setUp(); + + // Type an X and add it to form history. + let state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + // Wait for Satchel to say it's been added to form history. + let deferred = Promise.defer(); + Services.obs.addObserver(function onAdd(subj, topic, data) { + if (data == "formhistory-add") { + Services.obs.removeObserver(onAdd, "satchel-storage-changed"); + executeSoon(() => deferred.resolve()); + } + }, "satchel-storage-changed", false); + yield Promise.all([msg("addInputValueToFormHistory"), deferred.promise]); + + // Reset the input. + state = yield msg("reset"); + checkState(state, "", [], -1); + + // Type an X again. The form history entry should appear. + state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", [{ str: "x", type: "formHistory" }, "xfoo", "xbar"], + -1); + + // Select the form history entry and delete it. + state = yield msg("key", "VK_DOWN"); + checkState(state, "x", [{ str: "x", type: "formHistory" }, "xfoo", "xbar"], + 0); + + // Wait for Satchel. + deferred = Promise.defer(); + Services.obs.addObserver(function onRemove(subj, topic, data) { + if (data == "formhistory-remove") { + Services.obs.removeObserver(onRemove, "satchel-storage-changed"); + executeSoon(() => deferred.resolve()); + } + }, "satchel-storage-changed", false); + + state = yield msg("key", "VK_DELETE"); + checkState(state, "x", ["xfoo", "xbar"], -1); + + yield deferred.promise; + + // Reset the input. + state = yield msg("reset"); + checkState(state, "", [], -1); + + // Type an X again. The form history entry should still be gone. + state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + yield msg("reset"); +}); + +add_task(function* cycleEngines() { + yield setUp(); + yield msg("key", { key: "VK_DOWN", waitForSuggestions: true }); + + let promiseEngineChange = function(newEngineName) { + let deferred = Promise.defer(); + Services.obs.addObserver(function resolver(subj, topic, data) { + if (data != "engine-current") { + return; + } + SimpleTest.is(subj.name, newEngineName, "Engine cycled correctly"); + Services.obs.removeObserver(resolver, "browser-search-engine-modified"); + deferred.resolve(); + }, "browser-search-engine-modified", false); + return deferred.promise; + } + + let p = promiseEngineChange(TEST_ENGINE_PREFIX + " " + TEST_ENGINE_2_BASENAME); + yield msg("key", { key: "VK_DOWN", modifiers: { accelKey: true }}); + yield p; + + p = promiseEngineChange(TEST_ENGINE_PREFIX + " " + TEST_ENGINE_BASENAME); + yield msg("key", { key: "VK_UP", modifiers: { accelKey: true }}); + yield p; + + yield msg("reset"); +}); + +add_task(function* search() { + yield setUp(); + + let modifiers = {}; + ["altKey", "ctrlKey", "metaKey", "shiftKey"].forEach(k => modifiers[k] = true); + + // Test typing a query and pressing enter. + let p = msg("waitForSearch"); + yield msg("key", { key: "x", waitForSuggestions: true }); + yield msg("key", { key: "VK_RETURN", modifiers: modifiers }); + let mesg = yield p; + let eventData = { + engineName: TEST_ENGINE_PREFIX + " " + TEST_ENGINE_BASENAME, + searchString: "x", + healthReportKey: "test", + searchPurpose: "test", + originalEvent: modifiers, + }; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Test typing a query, then selecting a suggestion and pressing enter. + p = msg("waitForSearch"); + yield msg("key", { key: "x", waitForSuggestions: true }); + yield msg("key", "VK_DOWN"); + yield msg("key", "VK_DOWN"); + yield msg("key", { key: "VK_RETURN", modifiers: modifiers }); + mesg = yield p; + eventData.searchString = "xfoo"; + eventData.engineName = TEST_ENGINE_PREFIX + " " + TEST_ENGINE_BASENAME; + eventData.selection = { + index: 1, + kind: "key", + } + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Test typing a query, then selecting a one-off button and pressing enter. + p = msg("waitForSearch"); + yield msg("key", { key: "x", waitForSuggestions: true }); + yield msg("key", "VK_UP"); + yield msg("key", "VK_UP"); + yield msg("key", { key: "VK_RETURN", modifiers: modifiers }); + mesg = yield p; + delete eventData.selection; + eventData.searchString = "x"; + eventData.engineName = TEST_ENGINE_PREFIX + " " + TEST_ENGINE_2_BASENAME; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Test typing a query and clicking the search engine header. + p = msg("waitForSearch"); + modifiers.button = 0; + yield msg("key", { key: "x", waitForSuggestions: true }); + yield msg("mousemove", -1); + yield msg("click", { eltIdx: -1, modifiers: modifiers }); + mesg = yield p; + eventData.originalEvent = modifiers; + eventData.engineName = TEST_ENGINE_PREFIX + " " + TEST_ENGINE_BASENAME; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Test typing a query and then clicking a suggestion. + yield msg("key", { key: "x", waitForSuggestions: true }); + p = msg("waitForSearch"); + yield msg("mousemove", 1); + yield msg("click", { eltIdx: 1, modifiers: modifiers }); + mesg = yield p; + eventData.searchString = "xfoo"; + eventData.selection = { + index: 1, + kind: "mouse", + }; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Test typing a query and then clicking a one-off button. + yield msg("key", { key: "x", waitForSuggestions: true }); + p = msg("waitForSearch"); + yield msg("mousemove", 3); + yield msg("click", { eltIdx: 3, modifiers: modifiers }); + mesg = yield p; + eventData.searchString = "x"; + eventData.engineName = TEST_ENGINE_PREFIX + " " + TEST_ENGINE_2_BASENAME; + delete eventData.selection; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Test selecting a suggestion, then clicking a one-off without deselecting the + // suggestion. + yield msg("key", { key: "x", waitForSuggestions: true }); + p = msg("waitForSearch"); + yield msg("mousemove", 1); + yield msg("mousemove", 3); + yield msg("click", { eltIdx: 3, modifiers: modifiers }); + mesg = yield p; + eventData.searchString = "xfoo" + eventData.selection = { + index: 1, + kind: "mouse", + }; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Same as above, but with the keyboard. + delete modifiers.button; + yield msg("key", { key: "x", waitForSuggestions: true }); + p = msg("waitForSearch"); + yield msg("key", "VK_DOWN"); + yield msg("key", "VK_DOWN"); + yield msg("key", "VK_TAB"); + yield msg("key", { key: "VK_RETURN", modifiers: modifiers }); + mesg = yield p; + eventData.selection = { + index: 1, + kind: "key", + }; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Test searching when using IME composition. + let state = yield msg("startComposition", { data: "" }); + checkState(state, "", [], -1); + state = yield msg("changeComposition", { data: "x", waitForSuggestions: true }); + checkState(state, "x", [{ str: "x", type: "formHistory" }, + { str: "xfoo", type: "formHistory" }, "xbar"], -1); + yield msg("commitComposition"); + delete modifiers.button; + p = msg("waitForSearch"); + yield msg("key", { key: "VK_RETURN", modifiers: modifiers }); + mesg = yield p; + eventData.searchString = "x" + eventData.originalEvent = modifiers; + eventData.engineName = TEST_ENGINE_PREFIX + " " + TEST_ENGINE_BASENAME; + delete eventData.selection; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + state = yield msg("startComposition", { data: "" }); + checkState(state, "", [], -1); + state = yield msg("changeComposition", { data: "x", waitForSuggestions: true }); + checkState(state, "x", [{ str: "x", type: "formHistory" }, + { str: "xfoo", type: "formHistory" }, "xbar"], -1); + + // Mouse over the first suggestion. + state = yield msg("mousemove", 0); + checkState(state, "x", [{ str: "x", type: "formHistory" }, + { str: "xfoo", type: "formHistory" }, "xbar"], 0); + + // Mouse over the second suggestion. + state = yield msg("mousemove", 1); + checkState(state, "x", [{ str: "x", type: "formHistory" }, + { str: "xfoo", type: "formHistory" }, "xbar"], 1); + + modifiers.button = 0; + p = msg("waitForSearch"); + yield msg("click", { eltIdx: 1, modifiers: modifiers }); + mesg = yield p; + eventData.searchString = "xfoo"; + eventData.originalEvent = modifiers; + eventData.selection = { + index: 1, + kind: "mouse", + }; + SimpleTest.isDeeply(eventData, mesg, "Search event data"); + + yield promiseTab(); + yield setUp(); + + // Remove form history entries. + // Wait for Satchel. + let deferred = Promise.defer(); + let historyCount = 2; + Services.obs.addObserver(function onRemove(subj, topic, data) { + if (data == "formhistory-remove") { + if (--historyCount) { + return; + } + Services.obs.removeObserver(onRemove, "satchel-storage-changed"); + executeSoon(() => deferred.resolve()); + } + }, "satchel-storage-changed", false); + + yield msg("key", { key: "x", waitForSuggestions: true }); + yield msg("key", "VK_DOWN"); + yield msg("key", "VK_DOWN"); + yield msg("key", "VK_DELETE"); + yield msg("key", "VK_DOWN"); + yield msg("key", "VK_DELETE"); + yield deferred.promise; + + yield msg("reset"); + state = yield msg("key", { key: "x", waitForSuggestions: true }); + checkState(state, "x", ["xfoo", "xbar"], -1); + + yield promiseTab(); + yield setUp(); + yield msg("reset"); +}); + +add_task(function* settings() { + yield setUp(); + yield msg("key", { key: "VK_DOWN", waitForSuggestions: true }); + yield msg("key", "VK_UP"); + let p = msg("waitForSearchSettings"); + yield msg("key", "VK_RETURN"); + yield p; + + yield msg("reset"); +}); + +var gDidInitialSetUp = false; + +function setUp(aNoEngine) { + return Task.spawn(function* () { + if (!gDidInitialSetUp) { + Cu.import("resource:///modules/ContentSearch.jsm"); + let originalOnMessageSearch = ContentSearch._onMessageSearch; + let originalOnMessageManageEngines = ContentSearch._onMessageManageEngines; + ContentSearch._onMessageSearch = () => {}; + ContentSearch._onMessageManageEngines = () => {}; + registerCleanupFunction(() => { + ContentSearch._onMessageSearch = originalOnMessageSearch; + ContentSearch._onMessageManageEngines = originalOnMessageManageEngines; + }); + yield setUpEngines(); + yield promiseTab(); + gDidInitialSetUp = true; + } + yield msg("focus"); + }); +} + +function msg(type, data=null) { + gMsgMan.sendAsyncMessage(TEST_MSG, { + type: type, + data: data, + }); + let deferred = Promise.defer(); + gMsgMan.addMessageListener(TEST_MSG, function onMsg(msgObj) { + if (msgObj.data.type != type) { + return; + } + gMsgMan.removeMessageListener(TEST_MSG, onMsg); + deferred.resolve(msgObj.data.data); + }); + return deferred.promise; +} + +function checkState(actualState, expectedInputVal, expectedSuggestions, + expectedSelectedIdx, expectedSelectedButtonIdx) { + expectedSuggestions = expectedSuggestions.map(sugg => { + return typeof(sugg) == "object" ? sugg : { + str: sugg, + type: "remote", + }; + }); + + if (expectedSelectedIdx == -1 && expectedSelectedButtonIdx != undefined) { + expectedSelectedIdx = expectedSuggestions.length + expectedSelectedButtonIdx; + } + + let expectedState = { + selectedIndex: expectedSelectedIdx, + numSuggestions: expectedSuggestions.length, + suggestionAtIndex: expectedSuggestions.map(s => s.str), + isFormHistorySuggestionAtIndex: + expectedSuggestions.map(s => s.type == "formHistory"), + + tableHidden: expectedSuggestions.length == 0, + + inputValue: expectedInputVal, + ariaExpanded: expectedSuggestions.length == 0 ? "false" : "true", + }; + if (expectedSelectedButtonIdx != undefined) { + expectedState.selectedButtonIndex = expectedSelectedButtonIdx; + } + else if (expectedSelectedIdx < expectedSuggestions.length) { + expectedState.selectedButtonIndex = -1; + } + else { + expectedState.selectedButtonIndex = expectedSelectedIdx - expectedSuggestions.length; + } + + SimpleTest.isDeeply(actualState, expectedState, "State"); +} + +var gMsgMan; + +function* promiseTab() { + let deferred = Promise.defer(); + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser); + registerCleanupFunction(() => BrowserTestUtils.removeTab(tab)); + let pageURL = getRootDirectory(gTestPath) + TEST_PAGE_BASENAME; + tab.linkedBrowser.addEventListener("load", function onLoad(event) { + tab.linkedBrowser.removeEventListener("load", onLoad, true); + gMsgMan = tab.linkedBrowser.messageManager; + gMsgMan.sendAsyncMessage("ContentSearch", { + type: "AddToWhitelist", + data: [pageURL], + }); + promiseMsg("ContentSearch", "AddToWhitelistAck", gMsgMan).then(() => { + let jsURL = getRootDirectory(gTestPath) + TEST_CONTENT_SCRIPT_BASENAME; + gMsgMan.loadFrameScript(jsURL, false); + deferred.resolve(msg("init")); + }); + }, true, true); + openUILinkIn(pageURL, "current"); + return deferred.promise; +} + +function promiseMsg(name, type, msgMan) { + let deferred = Promise.defer(); + info("Waiting for " + name + " message " + type + "..."); + msgMan.addMessageListener(name, function onMsg(msgObj) { + info("Received " + name + " message " + msgObj.data.type + "\n"); + if (msgObj.data.type == type) { + msgMan.removeMessageListener(name, onMsg); + deferred.resolve(msgObj); + } + }); + return deferred.promise; +} + +function setUpEngines() { + return Task.spawn(function* () { + info("Removing default search engines"); + let currentEngineName = Services.search.currentEngine.name; + let currentEngines = Services.search.getVisibleEngines(); + info("Adding test search engines"); + let engine1 = yield promiseNewSearchEngine(TEST_ENGINE_BASENAME); + yield promiseNewSearchEngine(TEST_ENGINE_2_BASENAME); + Services.search.currentEngine = engine1; + for (let engine of currentEngines) { + Services.search.removeEngine(engine); + } + registerCleanupFunction(() => { + Services.search.restoreDefaultEngines(); + Services.search.currentEngine = Services.search.getEngineByName(currentEngineName); + }); + }); +} |