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: const TEST_URI = "data:text/html;charset=utf-8,

bug 585991 - autocomplete popup keyboard usage test"; michael@0: let HUD, popup, jsterm, inputNode, completeNode; michael@0: michael@0: function test() { michael@0: addTab(TEST_URI); michael@0: browser.addEventListener("load", function onLoad() { michael@0: browser.removeEventListener("load", onLoad, true); michael@0: openConsole(null, consoleOpened); michael@0: }, true); michael@0: } michael@0: michael@0: function consoleOpened(aHud) { michael@0: HUD = aHud; michael@0: info("web console opened"); michael@0: michael@0: jsterm = HUD.jsterm; michael@0: michael@0: jsterm.execute("window.foobarBug585991={" + michael@0: "'item0': 'value0'," + michael@0: "'item1': 'value1'," + michael@0: "'item2': 'value2'," + michael@0: "'item3': 'value3'" + michael@0: "}"); michael@0: popup = jsterm.autocompletePopup; michael@0: completeNode = jsterm.completeNode; michael@0: inputNode = jsterm.inputNode; michael@0: michael@0: ok(!popup.isOpen, "popup is not open"); michael@0: michael@0: popup._panel.addEventListener("popupshown", function onShown() { michael@0: popup._panel.removeEventListener("popupshown", onShown, false); michael@0: michael@0: ok(popup.isOpen, "popup is open"); michael@0: michael@0: // 4 values, and the following properties: michael@0: // __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__ michael@0: // hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString michael@0: // toSource unwatch valueOf watch constructor. michael@0: is(popup.itemCount, 18, "popup.itemCount is correct"); michael@0: michael@0: let sameItems = popup.getItems().reverse().map(function(e) {return e.label;}); michael@0: ok(sameItems.every(function(prop, index) { michael@0: return [ michael@0: "__defineGetter__", michael@0: "__defineSetter__", michael@0: "__lookupGetter__", michael@0: "__lookupSetter__", michael@0: "constructor", michael@0: "hasOwnProperty", michael@0: "isPrototypeOf", michael@0: "item0", michael@0: "item1", michael@0: "item2", michael@0: "item3", michael@0: "propertyIsEnumerable", michael@0: "toLocaleString", michael@0: "toSource", michael@0: "toString", michael@0: "unwatch", michael@0: "valueOf", michael@0: "watch", michael@0: ][index] === prop}), "getItems returns the items we expect"); michael@0: michael@0: is(popup.selectedIndex, 17, michael@0: "Index of the first item from bottom is selected."); michael@0: EventUtils.synthesizeKey("VK_DOWN", {}); michael@0: michael@0: let prefix = jsterm.inputNode.value.replace(/[\S]/g, " "); michael@0: michael@0: is(popup.selectedIndex, 0, "index 0 is selected"); michael@0: is(popup.selectedItem.label, "watch", "watch is selected"); michael@0: is(completeNode.value, prefix + "watch", michael@0: "completeNode.value holds watch"); michael@0: michael@0: EventUtils.synthesizeKey("VK_DOWN", {}); michael@0: michael@0: is(popup.selectedIndex, 1, "index 1 is selected"); michael@0: is(popup.selectedItem.label, "valueOf", "valueOf is selected"); michael@0: is(completeNode.value, prefix + "valueOf", michael@0: "completeNode.value holds valueOf"); michael@0: michael@0: EventUtils.synthesizeKey("VK_UP", {}); michael@0: michael@0: is(popup.selectedIndex, 0, "index 0 is selected"); michael@0: is(popup.selectedItem.label, "watch", "watch is selected"); michael@0: is(completeNode.value, prefix + "watch", michael@0: "completeNode.value holds watch"); michael@0: michael@0: let currentSelectionIndex = popup.selectedIndex; michael@0: michael@0: EventUtils.synthesizeKey("VK_PAGE_DOWN", {}); michael@0: michael@0: ok(popup.selectedIndex > currentSelectionIndex, michael@0: "Index is greater after PGDN"); michael@0: michael@0: currentSelectionIndex = popup.selectedIndex; michael@0: EventUtils.synthesizeKey("VK_PAGE_UP", {}); michael@0: michael@0: ok(popup.selectedIndex < currentSelectionIndex, "Index is less after Page UP"); michael@0: michael@0: info("press Tab and wait for popup to hide"); michael@0: popup._panel.addEventListener("popuphidden", popupHideAfterTab, false); michael@0: EventUtils.synthesizeKey("VK_TAB", {}); michael@0: }, false); michael@0: michael@0: info("wait for completion: window.foobarBug585991."); michael@0: jsterm.setInputValue("window.foobarBug585991"); michael@0: EventUtils.synthesizeKey(".", {}); michael@0: } michael@0: michael@0: function popupHideAfterTab() michael@0: { michael@0: // At this point the completion suggestion should be accepted. michael@0: popup._panel.removeEventListener("popuphidden", popupHideAfterTab, false); michael@0: michael@0: ok(!popup.isOpen, "popup is not open"); michael@0: michael@0: is(inputNode.value, "window.foobarBug585991.watch", michael@0: "completion was successful after VK_TAB"); michael@0: michael@0: ok(!completeNode.value, "completeNode is empty"); michael@0: michael@0: popup._panel.addEventListener("popupshown", function onShown() { michael@0: popup._panel.removeEventListener("popupshown", onShown, false); michael@0: michael@0: ok(popup.isOpen, "popup is open"); michael@0: michael@0: is(popup.itemCount, 18, "popup.itemCount is correct"); michael@0: michael@0: is(popup.selectedIndex, 17, "First index from bottom is selected"); michael@0: EventUtils.synthesizeKey("VK_DOWN", {}); michael@0: michael@0: let prefix = jsterm.inputNode.value.replace(/[\S]/g, " "); michael@0: michael@0: is(popup.selectedIndex, 0, "index 0 is selected"); michael@0: is(popup.selectedItem.label, "watch", "watch is selected"); michael@0: is(completeNode.value, prefix + "watch", michael@0: "completeNode.value holds watch"); michael@0: michael@0: popup._panel.addEventListener("popuphidden", function onHidden() { michael@0: popup._panel.removeEventListener("popuphidden", onHidden, false); michael@0: michael@0: ok(!popup.isOpen, "popup is not open after VK_ESCAPE"); michael@0: michael@0: is(inputNode.value, "window.foobarBug585991.", michael@0: "completion was cancelled"); michael@0: michael@0: ok(!completeNode.value, "completeNode is empty"); michael@0: michael@0: executeSoon(testReturnKey); michael@0: }, false); michael@0: michael@0: info("press Escape to close the popup"); michael@0: executeSoon(function() { michael@0: EventUtils.synthesizeKey("VK_ESCAPE", {}); michael@0: }); michael@0: }, false); michael@0: michael@0: info("wait for completion: window.foobarBug585991."); michael@0: executeSoon(function() { michael@0: jsterm.setInputValue("window.foobarBug585991"); michael@0: EventUtils.synthesizeKey(".", {}); michael@0: }); michael@0: } michael@0: michael@0: function testReturnKey() michael@0: { michael@0: popup._panel.addEventListener("popupshown", function onShown() { michael@0: popup._panel.removeEventListener("popupshown", onShown, false); michael@0: michael@0: ok(popup.isOpen, "popup is open"); michael@0: michael@0: is(popup.itemCount, 18, "popup.itemCount is correct"); michael@0: michael@0: is(popup.selectedIndex, 17, "First index from bottom is selected"); michael@0: EventUtils.synthesizeKey("VK_DOWN", {}); michael@0: michael@0: let prefix = jsterm.inputNode.value.replace(/[\S]/g, " "); michael@0: michael@0: is(popup.selectedIndex, 0, "index 0 is selected"); michael@0: is(popup.selectedItem.label, "watch", "watch is selected"); michael@0: is(completeNode.value, prefix + "watch", michael@0: "completeNode.value holds watch"); michael@0: michael@0: EventUtils.synthesizeKey("VK_DOWN", {}); michael@0: michael@0: is(popup.selectedIndex, 1, "index 1 is selected"); michael@0: is(popup.selectedItem.label, "valueOf", "valueOf is selected"); michael@0: is(completeNode.value, prefix + "valueOf", michael@0: "completeNode.value holds valueOf"); michael@0: michael@0: popup._panel.addEventListener("popuphidden", function onHidden() { michael@0: popup._panel.removeEventListener("popuphidden", onHidden, false); michael@0: michael@0: ok(!popup.isOpen, "popup is not open after VK_RETURN"); michael@0: michael@0: is(inputNode.value, "window.foobarBug585991.valueOf", michael@0: "completion was successful after VK_RETURN"); michael@0: michael@0: ok(!completeNode.value, "completeNode is empty"); michael@0: michael@0: dontShowArrayNumbers(); michael@0: }, false); michael@0: michael@0: info("press Return to accept suggestion. wait for popup to hide"); michael@0: michael@0: executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {})); michael@0: }, false); michael@0: michael@0: info("wait for completion suggestions: window.foobarBug585991."); michael@0: michael@0: executeSoon(function() { michael@0: jsterm.setInputValue("window.foobarBug58599"); michael@0: EventUtils.synthesizeKey("1", {}); michael@0: EventUtils.synthesizeKey(".", {}); michael@0: }); michael@0: } michael@0: michael@0: function dontShowArrayNumbers() michael@0: { michael@0: info("dontShowArrayNumbers"); michael@0: content.wrappedJSObject.foobarBug585991 = ["Sherlock Holmes"]; michael@0: michael@0: let jsterm = HUD.jsterm; michael@0: let popup = jsterm.autocompletePopup; michael@0: let completeNode = jsterm.completeNode; michael@0: michael@0: popup._panel.addEventListener("popupshown", function onShown() { michael@0: popup._panel.removeEventListener("popupshown", onShown, false); michael@0: michael@0: let sameItems = popup.getItems().map(function(e) {return e.label;}); michael@0: ok(!sameItems.some(function(prop, index) { prop === "0"; }), michael@0: "Completing on an array doesn't show numbers."); michael@0: michael@0: popup._panel.addEventListener("popuphidden", testReturnWithNoSelection, false); michael@0: michael@0: info("wait for popup to hide"); michael@0: executeSoon(() => EventUtils.synthesizeKey("VK_ESCAPE", {})); michael@0: }, false); michael@0: michael@0: info("wait for popup to show"); michael@0: executeSoon(() => { michael@0: jsterm.setInputValue("window.foobarBug585991"); michael@0: EventUtils.synthesizeKey(".", {}); michael@0: }); michael@0: } michael@0: michael@0: function testReturnWithNoSelection() michael@0: { michael@0: popup._panel.removeEventListener("popuphidden", testReturnWithNoSelection, false); michael@0: michael@0: info("test pressing return with open popup, but no selection, see bug 873250"); michael@0: content.wrappedJSObject.testBug873250a = "hello world"; michael@0: content.wrappedJSObject.testBug873250b = "hello world 2"; michael@0: michael@0: popup._panel.addEventListener("popupshown", function onShown() { michael@0: popup._panel.removeEventListener("popupshown", onShown); michael@0: michael@0: ok(popup.isOpen, "popup is open"); michael@0: is(popup.itemCount, 2, "popup.itemCount is correct"); michael@0: isnot(popup.selectedIndex, -1, "popup.selectedIndex is correct"); michael@0: michael@0: info("press Return and wait for popup to hide"); michael@0: popup._panel.addEventListener("popuphidden", popupHideAfterReturnWithNoSelection); michael@0: executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {})); michael@0: }); michael@0: michael@0: executeSoon(() => { michael@0: info("wait for popup to show"); michael@0: jsterm.setInputValue("window.testBu"); michael@0: EventUtils.synthesizeKey("g", {}); michael@0: }); michael@0: } michael@0: michael@0: function popupHideAfterReturnWithNoSelection() michael@0: { michael@0: popup._panel.removeEventListener("popuphidden", popupHideAfterReturnWithNoSelection); michael@0: michael@0: ok(!popup.isOpen, "popup is not open after VK_RETURN"); michael@0: michael@0: is(inputNode.value, "", "inputNode is empty after VK_RETURN"); michael@0: is(completeNode.value, "", "completeNode is empty"); michael@0: is(jsterm.history[jsterm.history.length-1], "window.testBug", michael@0: "jsterm history is correct"); michael@0: michael@0: executeSoon(testCompletionInText); michael@0: } michael@0: michael@0: function testCompletionInText() michael@0: { michael@0: info("test that completion works inside text, see bug 812618"); michael@0: michael@0: popup._panel.addEventListener("popupshown", function onShown() { michael@0: popup._panel.removeEventListener("popupshown", onShown); michael@0: michael@0: ok(popup.isOpen, "popup is open"); michael@0: is(popup.itemCount, 2, "popup.itemCount is correct"); michael@0: michael@0: EventUtils.synthesizeKey("VK_DOWN", {}); michael@0: is(popup.selectedIndex, 0, "popup.selectedIndex is correct"); michael@0: ok(!completeNode.value, "completeNode.value is empty"); michael@0: michael@0: let items = popup.getItems().reverse().map(e => e.label); michael@0: let sameItems = items.every((prop, index) => michael@0: ["testBug873250a", "testBug873250b"][index] === prop); michael@0: ok(sameItems, "getItems returns the items we expect"); michael@0: michael@0: info("press Tab and wait for popup to hide"); michael@0: popup._panel.addEventListener("popuphidden", popupHideAfterCompletionInText); michael@0: EventUtils.synthesizeKey("VK_TAB", {}); michael@0: }); michael@0: michael@0: jsterm.setInputValue("dump(window.testBu)"); michael@0: inputNode.selectionStart = inputNode.selectionEnd = 18; michael@0: EventUtils.synthesizeKey("g", {}); michael@0: } michael@0: michael@0: function popupHideAfterCompletionInText() michael@0: { michael@0: // At this point the completion suggestion should be accepted. michael@0: popup._panel.removeEventListener("popuphidden", popupHideAfterCompletionInText); michael@0: michael@0: ok(!popup.isOpen, "popup is not open"); michael@0: is(inputNode.value, "dump(window.testBug873250b)", michael@0: "completion was successful after VK_TAB"); michael@0: is(inputNode.selectionStart, 26, "cursor location is correct"); michael@0: is(inputNode.selectionStart, inputNode.selectionEnd, "cursor location (confirmed)"); michael@0: ok(!completeNode.value, "completeNode is empty"); michael@0: michael@0: finishUp(); michael@0: } michael@0: michael@0: function finishUp() { michael@0: HUD = popup = jsterm = inputNode = completeNode = null; michael@0: finishTest(); michael@0: }