Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'linux' OR os == 'android' OR headless
- Manifest: dom/tests/mochitest/keyhandling/mochitest.toml
<head>
<title>input key handling</title>
<script type="text/javascript" src="http://mochi.test:8888/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="http://mochi.test:8888/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="http://mochi.test:8888/tests/SimpleTest/NativeKeyCodes.js"></script>
<script type="text/javascript">
const IS_MAC = navigator.platform.indexOf("Mac") == 0;
const VK = {};
const CHARS = {};
if (IS_MAC) {
VK.LEFT = MAC_VK_LeftArrow;
CHARS.LEFT = "\uF702";
VK.RIGHT = MAC_VK_RightArrow;
CHARS.RIGHT = "\uF703";
VK.UP = MAC_VK_UpArrow;
CHARS.UP = "\uF700";
VK.DOWN = MAC_VK_DownArrow;
CHARS.DOWN = "\uF701";
VK.X = MAC_VK_ANSI_X;
VK.V = MAC_VK_ANSI_V;
VK.A = MAC_VK_ANSI_A;
VK.F = MAC_VK_ANSI_F;
VK.O = MAC_VK_ANSI_O;
VK.BACKSPACE = MAC_VK_PC_Backspace;
CHARS.BACKSPACE = "\u007F";
VK.Z = MAC_VK_ANSI_Z;
VK.SPACE = MAC_VK_Space;
} else {
VK.LEFT = WIN_VK_LEFT;
CHARS.LEFT = "";
VK.RIGHT = WIN_VK_RIGHT;
CHARS.RIGHT = "";
VK.UP = WIN_VK_UP;
CHARS.UP = "";
VK.DOWN = WIN_VK_DOWN;
CHARS.DOWN = "";
VK.X = WIN_VK_X;
VK.V = WIN_VK_V;
VK.A = WIN_VK_A;
VK.F = WIN_VK_F;
VK.O = WIN_VK_O;
VK.END = WIN_VK_END;
CHARS.END = "";
VK.HOME = WIN_VK_HOME;
CHARS.HOME = "";
VK.BACKSPACE = WIN_VK_BACK;
CHARS.BACKSPACE = "";
VK.Z = WIN_VK_Z;
VK.SPACE = WIN_VK_SPACE;
}
if (window.arguments && window.arguments[0]) {
ok = window.arguments[0].ok;
is = window.arguments[0].is;
}
function synthesizeKey(keyCode, modifiers, chars, event = "keyup") {
return new Promise((resolve, reject) => {
window.addEventListener(event, resolve, { once: true });
if (!synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, keyCode, modifiers, chars, chars)) {
reject();
}
});
}
async function checkElement(element, start, end, content = "Test text") {
isReady = () => {
if (start != element.selectionStart) {
return false;
}
if (end != element.selectionEnd) {
return false;
}
if (content != element.value) {
return false;
}
return true;
};
for (let i = 0; i < 10; i++) {
if (isReady()) {
return;
}
SimpleTest.requestFlakyTimeout("Polling for changes to apply");
await new Promise(resolve => setTimeout(resolve, 50));
}
ok(false, "Timed out waiting for state");
is(element.selectionStart, start, "Should have the right selectionStart");
is(element.selectionEnd, end, "Should have the right selectionEnd");
is(element.value, content, "Should have the right value");
}
async function startTest() {
let input = document.getElementById("input");
input.focus();
await checkElement(input, 0, 0);
info("right");
await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
await checkElement(input, 1, 1);
info("shift+right");
await synthesizeKey(VK.RIGHT, { shiftKey: true }, CHARS.RIGHT);
await checkElement(input, 1, 2);
info("shift+right");
await synthesizeKey(VK.RIGHT, { shiftKey: true }, CHARS.RIGHT);
await checkElement(input, 1, 3);
info("shift+left");
await synthesizeKey(VK.LEFT, { shiftKey: true }, CHARS.LEFT);
await checkElement(input, 1, 2);
info("shift+left");
await synthesizeKey(VK.LEFT, { shiftKey: true }, CHARS.LEFT);
await checkElement(input, 1, 1);
info("shift+left");
await synthesizeKey(VK.LEFT, { shiftKey: true }, CHARS.LEFT);
await checkElement(input, 0, 1);
info("shift+right");
await synthesizeKey(VK.RIGHT, { shiftKey: true }, CHARS.RIGHT);
await checkElement(input, 1, 1);
info("left");
await synthesizeKey(VK.LEFT, {}, CHARS.LEFT);
await checkElement(input, 0, 0);
if (IS_MAC) {
info("down");
await synthesizeKey(VK.DOWN, { shiftKey: true }, CHARS.DOWN);
} else {
info("end");
await synthesizeKey(VK.END, { shiftKey: true }, CHARS.END);
}
await checkElement(input, 0, 9);
info("cut");
await synthesizeKey(VK.X, { accelKey: true }, "x", "input");
await checkElement(input, 0, 0, "");
let text = SpecialPowers.getClipboardData("text/plain");
is(text, "Test text", "Should have cut to the clipboard");
SpecialPowers.clipboardCopyString("New text");
info("paste");
await synthesizeKey(VK.V, { accelKey: true }, "v", "input");
await checkElement(input, 8, 8, "New text");
if (IS_MAC) {
info("up");
await synthesizeKey(VK.UP, {}, CHARS.UP);
} else {
info("home");
await synthesizeKey(VK.HOME, {}, CHARS.HOME);
}
await checkElement(input, 0, 0, "New text");
info("select all");
await synthesizeKey(VK.A, { accelKey: true}, "a", "select");
await checkElement(input, 0, 8, "New text");
info("right");
await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
await checkElement(input, 8, 8, "New text");
info("word left");
if (IS_MAC) {
await synthesizeKey(VK.LEFT, { altKey: true }, CHARS.LEFT);
} else {
await synthesizeKey(VK.LEFT, { ctrlKey: true }, CHARS.LEFT);
}
await checkElement(input, 4, 4, "New text");
info("delete word left");
if (IS_MAC) {
await synthesizeKey(VK.BACKSPACE, { altKey: true }, CHARS.BACKSPACE);
} else {
await synthesizeKey(VK.BACKSPACE, { ctrlKey: true }, CHARS.BACKSPACE);
}
await checkElement(input, 0, 0, "text");
info("undo");
await synthesizeKey(VK.Z, { accelKey: true }, "", "input");
await checkElement(input, 4, 4, "New text");
info("redo");
await synthesizeKey(VK.Z, { accelKey: true, shiftKey: true }, "", "input");
await checkElement(input, 0, 0, "text");
info("typing");
await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
await synthesizeKey(VK.SPACE, {}, " ");
await synthesizeKey(VK.F, {}, "f");
await synthesizeKey(VK.O, {}, "o");
await synthesizeKey(VK.O, {}, "o");
await checkElement(input, 8, 8, "text foo");
}
async function runTest() {
// When running in windowed mode the caller will start the test once we have
// focus.
if (window.arguments && window.arguments[0]) {
return;
}
SimpleTest.waitForExplicitFinish();
await startTest();
SimpleTest.finish();
}
</script>
</head>
<body onload="runTest();">
<input id=input value="Test text"/>
</body>
</html>