summaryrefslogtreecommitdiffstats
path: root/toolkit/content/tests/chrome/test_menulist_keynav.xul
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/tests/chrome/test_menulist_keynav.xul')
-rw-r--r--toolkit/content/tests/chrome/test_menulist_keynav.xul272
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>