diff options
Diffstat (limited to 'toolkit/content/tests/chrome/test_menulist_keynav.xul')
-rw-r--r-- | toolkit/content/tests/chrome/test_menulist_keynav.xul | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/toolkit/content/tests/chrome/test_menulist_keynav.xul b/toolkit/content/tests/chrome/test_menulist_keynav.xul new file mode 100644 index 000000000..c2e404c09 --- /dev/null +++ b/toolkit/content/tests/chrome/test_menulist_keynav.xul @@ -0,0 +1,272 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> + +<window title="Menulist Key Navigation Tests" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + +<button id="button1" label="One"/> +<menulist id="list"> + <menupopup id="popup" onpopupshowing="return gShowPopup;"> + <menuitem id="i1" label="One"/> + <menuitem id="i2" label="Two"/> + <menuitem id="i2b" disabled="true" label="Two and a Half"/> + <menuitem id="i3" label="Three"/> + <menuitem id="i4" label="Four"/> + </menupopup> +</menulist> +<button id="button2" label="Two"/> +<menulist id="list2"> + <menupopup id="popup" onpopupshown="checkCursorNavigation();"> + <menuitem id="b1" label="One"/> + <menuitem id="b2" label="Two" selected="true"/> + <menuitem id="b3" label="Three"/> + <menuitem id="b4" label="Four"/> + </menupopup> +</menulist> + +<script class="testbody" type="application/javascript"> +<![CDATA[ + +SimpleTest.waitForExplicitFinish(); + +var gShowPopup = false; +var gModifiers = 0; +var gOpenPhase = false; + +var list = $("list"); +let expectCommandEvent; + +var iswin = (navigator.platform.indexOf("Win") == 0); +var ismac = (navigator.platform.indexOf("Mac") == 0); + +function runTests() +{ + list.focus(); + + // on Mac, up and cursor keys open the menu, but on other platforms, the + // cursor keys navigate between items without opening the menu + if (navigator.platform.indexOf("Mac") == -1) { + expectCommandEvent = true; + keyCheck(list, "VK_DOWN", 2, "cursor down"); + keyCheck(list, "VK_DOWN", 3, "cursor down skip disabled"); + keyCheck(list, "VK_UP", 2, "cursor up skip disabled"); + keyCheck(list, "VK_UP", 1, "cursor up"); + keyCheck(list, "VK_UP", 4, "cursor up wrap"); + keyCheck(list, "VK_DOWN", 1, "cursor down wrap"); + } + + // check that attempting to open the menulist does not change the selection + synthesizeKey("VK_DOWN", { altKey: navigator.platform.indexOf("Mac") == -1 }); + is(list.selectedItem, $("i1"), "open menulist down selectedItem"); + synthesizeKey("VK_UP", { altKey: navigator.platform.indexOf("Mac") == -1 }); + is(list.selectedItem, $("i1"), "open menulist up selectedItem"); + + list.selectedItem = $("i1"); + + pressLetter(); +} + +function pressLetter() +{ + // A command event should be fired only if the menulist is closed, or on Windows, + // where items are selected immediately. + expectCommandEvent = !gOpenPhase || iswin; + + synthesizeKey("G", { }); + is(list.selectedItem, $("i1"), "letter pressed not found selectedItem"); + + keyCheck(list, "T", 2, "letter pressed"); + + if (!gOpenPhase) { + SpecialPowers.setIntPref("ui.menu.incremental_search.timeout", 0); // prevent to timeout + keyCheck(list, "T", 2, "same letter pressed"); + SpecialPowers.clearUserPref("ui.menu.incremental_search.timeout"); + } + + setTimeout(pressedAgain, 1200); +} + +function pressedAgain() +{ + keyCheck(list, "T", 3, "letter pressed again"); + SpecialPowers.setIntPref("ui.menu.incremental_search.timeout", 0); // prevent to timeout + keyCheck(list, "W", 2, "second letter pressed"); + SpecialPowers.clearUserPref("ui.menu.incremental_search.timeout"); + setTimeout(differentPressed, 1200); +} + +function differentPressed() +{ + keyCheck(list, "O", 1, "different letter pressed"); + + if (gOpenPhase) { + list.open = false; + tabAndScroll(); + } + else { + // Run the letter tests again with the popup open + info("list open phase"); + + list.selectedItem = $("i1"); + + // Hide and show the list to avoid using any existing incremental key state. + list.hidden = true; + list.clientWidth; + list.hidden = false; + + gShowPopup = true; + gOpenPhase = true; + + list.addEventListener("popupshown", function popupShownListener() { + list.removeEventListener("popupshown", popupShownListener, false); + pressLetter(); + }, false); + + list.open = true; + } +} + +function tabAndScroll() +{ + list = $("list"); + + if (navigator.platform.indexOf("Mac") == -1) { + $("button1").focus(); + synthesizeKeyExpectEvent("VK_TAB", { }, list, "focus", "focus to menulist"); + synthesizeKeyExpectEvent("VK_TAB", { }, $("button2"), "focus", "focus to button"); + is(document.activeElement, $("button2"), "tab from menulist focused button"); + } + + // now make sure that using a key scrolls the menu correctly + + for (let i = 0; i < 65; i++) { + list.appendItem("Item" + i, "item" + i); + } + list.open = true; + is(list.getBoundingClientRect().width, list.firstChild.getBoundingClientRect().width, + "menu and popup width match"); + var minScrollbarWidth = window.matchMedia("(-moz-overlay-scrollbars)").matches ? 0 : 3; + ok(list.getBoundingClientRect().width >= list.getItemAtIndex(0).getBoundingClientRect().width + minScrollbarWidth, + "menuitem width accounts for scrollbar"); + list.open = false; + + list.menupopup.maxHeight = 100; + list.open = true; + + var rowdiff = list.getItemAtIndex(1).getBoundingClientRect().top - + list.getItemAtIndex(0).getBoundingClientRect().top; + + var item = list.getItemAtIndex(10); + var originalPosition = item.getBoundingClientRect().top; + + list.menuBoxObject.activeChild = item; + ok(item.getBoundingClientRect().top < originalPosition, + "position of item 1: " + item.getBoundingClientRect().top + " -> " + originalPosition); + + originalPosition = item.getBoundingClientRect().top; + + synthesizeKey("VK_DOWN", { }); + is(item.getBoundingClientRect().top, originalPosition - rowdiff, "position of item 10"); + + list.open = false; + + checkEnter(); +} + +function keyCheck(list, key, index, testname) +{ + var item = $("i" + index); + synthesizeKeyExpectEvent(key, { }, item, expectCommandEvent ? "command" : "!command", testname); + is(list.selectedItem, expectCommandEvent ? item : $("i1"), testname + " selectedItem"); +} + +function checkModifiers(event) +{ + var expectedModifiers = (gModifiers == 1); + is(event.shiftKey, expectedModifiers, "shift key pressed"); + is(event.ctrlKey, expectedModifiers, "ctrl key pressed"); + is(event.altKey, expectedModifiers, "alt key pressed"); + is(event.metaKey, expectedModifiers, "meta key pressed"); + gModifiers++; +} + +function checkEnter() +{ + list.addEventListener("popuphidden", checkEnterWithModifiers, false); + list.addEventListener("command", checkModifiers, false); + list.open = true; + synthesizeKey("VK_RETURN", { }); +} + +function checkEnterWithModifiers() +{ + is(gModifiers, 1, "modifiers checked when not set"); + + ok(!list.open, "list closed on enter press"); + list.removeEventListener("popuphidden", checkEnterWithModifiers, false); + + list.addEventListener("popuphidden", verifyPopupOnClose, false); + list.open = true; + + synthesizeKey("VK_RETURN", { shiftKey: true, ctrlKey: true, altKey: true, metaKey: true }); +} + +function verifyPopupOnClose() +{ + is(gModifiers, 2, "modifiers checked when set"); + + ok(!list.open, "list closed on enter press with modifiers"); + list.removeEventListener("popuphidden", verifyPopupOnClose, false); + + list = $("list2"); + list.focus(); + list.open = true; +} + +function checkCursorNavigation() +{ + var commandEventsCount = 0; + list.addEventListener("command", event => { + is(event.target, list.selectedItem, "command event fired on selected item"); + commandEventsCount++; + }, false); + + is(list.selectedIndex, 1, "selectedIndex before cursor down"); + synthesizeKey("VK_DOWN", { }); + is(list.selectedIndex, iswin ? 2 : 1, "selectedIndex after cursor down"); + is(commandEventsCount, iswin ? 1 : 0, "selectedIndex after cursor down command event"); + is(list.menupopup.state, "open", "cursor down popup state"); + synthesizeKey("VK_PAGE_DOWN", { }); + is(list.selectedIndex, iswin ? 3 : 1, "selectedIndex after page down"); + is(commandEventsCount, iswin ? 2 : 0, "selectedIndex after page down command event"); + is(list.menupopup.state, "open", "page down popup state"); + + synthesizeKey("VK_UP", { altKey: true }); + is(list.open, ismac, "alt+up closes popup"); + + if (ismac) { + list.open = false; + } + + SimpleTest.finish(); +} + +SimpleTest.waitForFocus(runTests); + +]]> +</script> + +<body xmlns="http://www.w3.org/1999/xhtml"> +<p id="display"> +</p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +</pre> +</body> + +</window> |