fune/browser/components/customizableui/test/browser_PanelMultiView_keyboard.js
2019-04-23 11:44:36 +00:00

272 lines
9.3 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test the keyboard behavior of PanelViews.
*/
const {PanelMultiView} = ChromeUtils.import("resource:///modules/PanelMultiView.jsm");
let gAnchor;
let gPanel;
let gPanelMultiView;
let gMainView;
let gMainButton1;
let gMainMenulist;
let gMainTextbox;
let gMainButton2;
let gMainButton3;
let gMainTabOrder;
let gMainArrowOrder;
let gSubView;
let gSubButton;
let gSubTextarea;
async function openPopup() {
let shown = BrowserTestUtils.waitForEvent(gMainView, "ViewShown");
PanelMultiView.openPopup(gPanel, gAnchor, "bottomcenter topright");
await shown;
}
async function hidePopup() {
let hidden = BrowserTestUtils.waitForEvent(gPanel, "popuphidden");
PanelMultiView.hidePopup(gPanel);
await hidden;
}
async function showSubView() {
let shown = BrowserTestUtils.waitForEvent(gSubView, "ViewShown");
gPanelMultiView.showSubView(gSubView);
await shown;
}
async function expectFocusAfterKey(aKey, aFocus) {
let res = aKey.match(/^(Shift\+)?(.+)$/);
let shift = Boolean(res[1]);
let key;
if (res[2].length == 1) {
key = res[2]; // Character.
} else {
key = "KEY_" + res[2]; // Tab, ArrowRight, etc.
}
info("Waiting for focus on " + aFocus.id);
let focused = BrowserTestUtils.waitForEvent(aFocus, "focus");
EventUtils.synthesizeKey(key, {shiftKey: shift});
await focused;
ok(true, aFocus.id + " focused after " + aKey + " pressed");
}
add_task(async function setup() {
let navBar = document.getElementById("nav-bar");
gAnchor = document.createXULElement("toolbarbutton");
navBar.appendChild(gAnchor);
gPanel = document.createXULElement("panel");
navBar.appendChild(gPanel);
gPanelMultiView = document.createXULElement("panelmultiview");
gPanelMultiView.setAttribute("mainViewId", "testMainView");
gPanel.appendChild(gPanelMultiView);
gMainView = document.createXULElement("panelview");
gMainView.id = "testMainView";
gPanelMultiView.appendChild(gMainView);
gMainButton1 = document.createXULElement("button");
gMainButton1.id = "gMainButton1";
gMainView.appendChild(gMainButton1);
gMainMenulist = document.createXULElement("menulist");
gMainMenulist.id = "gMainMenulist";
gMainView.appendChild(gMainMenulist);
let menuPopup = document.createXULElement("menupopup");
gMainMenulist.appendChild(menuPopup);
let item = document.createXULElement("menuitem");
item.setAttribute("value", "1");
item.setAttribute("selected", "true");
menuPopup.appendChild(item);
item = document.createXULElement("menuitem");
item.setAttribute("value", "2");
menuPopup.appendChild(item);
gMainTextbox = document.createXULElement("textbox");
gMainTextbox.id = "gMainTextbox";
gMainView.appendChild(gMainTextbox);
gMainTextbox.setAttribute("value", "value");
gMainButton2 = document.createXULElement("button");
gMainButton2.id = "gMainButton2";
gMainView.appendChild(gMainButton2);
gMainButton3 = document.createXULElement("button");
gMainButton3.id = "gMainButton3";
gMainView.appendChild(gMainButton3);
gMainTabOrder = [gMainButton1, gMainMenulist, gMainTextbox, gMainButton2,
gMainButton3];
gMainArrowOrder = [gMainButton1, gMainButton2, gMainButton3];
gSubView = document.createXULElement("panelview");
gSubView.id = "testSubView";
gPanelMultiView.appendChild(gSubView);
gSubButton = document.createXULElement("button");
gSubView.appendChild(gSubButton);
gSubTextarea = document.createElementNS("http://www.w3.org/1999/xhtml",
"textarea");
gSubTextarea.id = "gSubTextarea";
gSubView.appendChild(gSubTextarea);
gSubTextarea.value = "value";
registerCleanupFunction(() => {
gAnchor.remove();
gPanel.remove();
});
});
// Test that the tab key focuses all expected controls.
add_task(async function testTab() {
await openPopup();
for (let elem of gMainTabOrder) {
await expectFocusAfterKey("Tab", elem);
}
// Wrap around.
await expectFocusAfterKey("Tab", gMainTabOrder[0]);
await hidePopup();
});
// Test that the shift+tab key focuses all expected controls.
add_task(async function testShiftTab() {
await openPopup();
for (let i = gMainTabOrder.length - 1; i >= 0; --i) {
await expectFocusAfterKey("Shift+Tab", gMainTabOrder[i]);
}
// Wrap around.
await expectFocusAfterKey("Shift+Tab",
gMainTabOrder[gMainTabOrder.length - 1]);
await hidePopup();
});
// Test that the down arrow key skips menulists and textboxes.
add_task(async function testDownArrow() {
await openPopup();
for (let elem of gMainArrowOrder) {
await expectFocusAfterKey("ArrowDown", elem);
}
// Wrap around.
await expectFocusAfterKey("ArrowDown", gMainArrowOrder[0]);
await hidePopup();
});
// Test that the up arrow key skips menulists and textboxes.
add_task(async function testUpArrow() {
await openPopup();
for (let i = gMainArrowOrder.length - 1; i >= 0; --i) {
await expectFocusAfterKey("ArrowUp", gMainArrowOrder[i]);
}
// Wrap around.
await expectFocusAfterKey("ArrowUp",
gMainArrowOrder[gMainArrowOrder.length - 1]);
await hidePopup();
});
// Test that the home/end keys move to the first/last controls.
add_task(async function testHomeEnd() {
await openPopup();
await expectFocusAfterKey("Home", gMainArrowOrder[0]);
await expectFocusAfterKey("End",
gMainArrowOrder[gMainArrowOrder.length - 1]);
await hidePopup();
});
// Test that the up/down arrow keys work as expected in menulists.
add_task(async function testArrowsMenulist() {
await openPopup();
gMainMenulist.focus();
is(document.activeElement, gMainMenulist, "menulist focused");
is(gMainMenulist.value, "1", "menulist initial value 1");
if (AppConstants.platform == "macosx") {
// On Mac, down/up arrows just open the menulist.
let popup = gMainMenulist.menupopup;
for (let key of ["ArrowDown", "ArrowUp"]) {
let shown = BrowserTestUtils.waitForEvent(popup, "popupshown");
EventUtils.synthesizeKey("KEY_" + key);
await shown;
ok(gMainMenulist.open, "menulist open after " + key);
let hidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("KEY_Escape");
await hidden;
ok(!gMainMenulist.open, "menulist closed after Escape");
}
} else {
// On other platforms, down/up arrows change the value without opening the
// menulist.
EventUtils.synthesizeKey("KEY_ArrowDown");
is(document.activeElement, gMainMenulist,
"menulist still focused after ArrowDown");
is(gMainMenulist.value, "2", "menulist value 2 after ArrowDown");
EventUtils.synthesizeKey("KEY_ArrowUp");
is(document.activeElement, gMainMenulist,
"menulist still focused after ArrowUp");
is(gMainMenulist.value, "1", "menulist value 1 after ArrowUp");
}
await hidePopup();
});
// Test that pressing space in a textbox inserts a space (instead of trying to
// activate the control).
add_task(async function testSpaceTextbox() {
await openPopup();
gMainTextbox.focus();
gMainTextbox.selectionStart = gMainTextbox.selectionEnd = 0;
EventUtils.synthesizeKey(" ");
is(gMainTextbox.value, " value", "Space typed into textbox");
gMainTextbox.value = "value";
await hidePopup();
});
// Tests that the left arrow key normally moves back to the previous view.
add_task(async function testLeftArrow() {
await openPopup();
await showSubView();
let shown = BrowserTestUtils.waitForEvent(gMainView, "ViewShown");
EventUtils.synthesizeKey("KEY_ArrowLeft");
await shown;
ok("Moved to previous view after ArrowLeft");
await hidePopup();
});
// Tests that the left arrow key moves the caret in a textarea in a subview
// (instead of going back to the previous view).
add_task(async function testLeftArrowTextarea() {
await openPopup();
await showSubView();
gSubTextarea.focus();
is(document.activeElement, gSubTextarea, "textarea focused");
EventUtils.synthesizeKey("KEY_End");
is(gSubTextarea.selectionStart, 5, "selectionStart 5 after End");
EventUtils.synthesizeKey("KEY_ArrowLeft");
is(gSubTextarea.selectionStart, 4, "selectionStart 4 after ArrowLeft");
is(document.activeElement, gSubTextarea, "textarea still focused");
await hidePopup();
});
// Test navigation to a button which is initially disabled and later enabled.
add_task(async function testDynamicButton() {
gMainButton2.disabled = true;
await openPopup();
await expectFocusAfterKey("ArrowDown", gMainButton1);
await expectFocusAfterKey("ArrowDown", gMainButton3);
gMainButton2.disabled = false;
await expectFocusAfterKey("ArrowUp", gMainButton2);
await hidePopup();
});
add_task(async function testActivation() {
function checkActivated(elem, activationFn, reason) {
let activated = false;
elem.onclick = function() { activated = true; };
activationFn();
ok(activated, "Should have activated button after " + reason);
elem.onclick = null;
}
await openPopup();
await expectFocusAfterKey("ArrowDown", gMainButton1);
checkActivated(gMainButton1, () => EventUtils.synthesizeKey("KEY_Enter"), "pressing enter");
checkActivated(gMainButton1, () => EventUtils.synthesizeKey(" "), "pressing space");
checkActivated(gMainButton1, () => EventUtils.synthesizeKey("KEY_Enter", {code: "NumpadEnter"}), "pressing numpad enter");
await hidePopup();
});