123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
- "use strict";
- var isOSX = Services.appinfo.OS === "Darwin";
- add_task(function* () {
- let shortcuts = new KeyShortcuts({
- window
- });
- yield testSimple(shortcuts);
- yield testNonLetterCharacter(shortcuts);
- yield testPlusCharacter(shortcuts);
- yield testFunctionKey(shortcuts);
- yield testMixup(shortcuts);
- yield testLooseDigits(shortcuts);
- yield testExactModifiers(shortcuts);
- yield testLooseShiftModifier(shortcuts);
- yield testStrictLetterShiftModifier(shortcuts);
- yield testAltModifier(shortcuts);
- yield testCommandOrControlModifier(shortcuts);
- yield testCtrlModifier(shortcuts);
- yield testInvalidShortcutString(shortcuts);
- yield testCmdShiftShortcut(shortcuts);
- shortcuts.destroy();
- yield testTarget();
- });
- // Test helper to listen to the next key press for a given key,
- // returning a promise to help using Tasks.
- function once(shortcuts, key, listener) {
- let called = false;
- return new Promise(done => {
- let onShortcut = (key2, event) => {
- shortcuts.off(key, onShortcut);
- ok(!called, "once listener called only once (i.e. off() works)");
- is(key, key2, "listener first argument match the key we listen");
- called = true;
- listener(key2, event);
- done();
- };
- shortcuts.on(key, onShortcut);
- });
- }
- function* testSimple(shortcuts) {
- info("Test simple key shortcuts");
- let onKey = once(shortcuts, "0", (key, event) => {
- is(event.key, "0");
- // Display another key press to ensure that once() correctly stop listening
- EventUtils.synthesizeKey("0", {}, window);
- });
- EventUtils.synthesizeKey("0", {}, window);
- yield onKey;
- }
- function* testNonLetterCharacter(shortcuts) {
- info("Test non-naive character key shortcuts");
- let onKey = once(shortcuts, "[", (key, event) => {
- is(event.key, "[");
- });
- EventUtils.synthesizeKey("[", {}, window);
- yield onKey;
- }
- function* testFunctionKey(shortcuts) {
- info("Test function key shortcuts");
- let onKey = once(shortcuts, "F12", (key, event) => {
- is(event.key, "F12");
- });
- EventUtils.synthesizeKey("F12", { keyCode: 123 }, window);
- yield onKey;
- }
- // Plus is special. It's keycode is the one for "=". That's because it requires
- // shift to be pressed and is behind "=" key. So it should be considered as a
- // character key
- function* testPlusCharacter(shortcuts) {
- info("Test 'Plus' key shortcuts");
- let onKey = once(shortcuts, "Plus", (key, event) => {
- is(event.key, "+");
- });
- EventUtils.synthesizeKey("+", { keyCode: 61, shiftKey: true }, window);
- yield onKey;
- }
- // Test they listeners are not mixed up between shortcuts
- function* testMixup(shortcuts) {
- info("Test possible listener mixup");
- let hitFirst = false, hitSecond = false;
- let onFirstKey = once(shortcuts, "0", (key, event) => {
- is(event.key, "0");
- hitFirst = true;
- });
- let onSecondKey = once(shortcuts, "Alt+A", (key, event) => {
- is(event.key, "a");
- ok(event.altKey);
- hitSecond = true;
- });
- // Dispatch the first shortcut and expect only this one to be notified
- ok(!hitFirst, "First shortcut isn't notified before firing the key event");
- EventUtils.synthesizeKey("0", {}, window);
- yield onFirstKey;
- ok(hitFirst, "Got the first shortcut notified");
- ok(!hitSecond, "No mixup, second shortcut is still not notified (1/2)");
- // Wait an extra time, just to be sure this isn't racy
- yield new Promise(done => {
- window.setTimeout(done, 0);
- });
- ok(!hitSecond, "No mixup, second shortcut is still not notified (2/2)");
- // Finally dispatch the second shortcut
- EventUtils.synthesizeKey("a", { altKey: true }, window);
- yield onSecondKey;
- ok(hitSecond, "Got the second shortcut notified once it is actually fired");
- }
- // On azerty keyboard, digits are only available by pressing Shift/Capslock,
- // but we accept them even if we omit doing that.
- function* testLooseDigits(shortcuts) {
- info("Test Loose digits");
- let onKey = once(shortcuts, "0", (key, event) => {
- is(event.key, "à");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(!event.shiftKey);
- });
- // Simulate a press on the "0" key, without shift pressed on a french
- // keyboard
- EventUtils.synthesizeKey(
- "à",
- { keyCode: 48 },
- window);
- yield onKey;
- onKey = once(shortcuts, "0", (key, event) => {
- is(event.key, "0");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(event.shiftKey);
- });
- // Simulate the same press with shift pressed
- EventUtils.synthesizeKey(
- "0",
- { keyCode: 48, shiftKey: true },
- window);
- yield onKey;
- }
- // Test that shortcuts is notified only when the modifiers match exactly
- function* testExactModifiers(shortcuts) {
- info("Test exact modifiers match");
- let hit = false;
- let onKey = once(shortcuts, "Alt+A", (key, event) => {
- is(event.key, "a");
- ok(event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(!event.shiftKey);
- hit = true;
- });
- // Dispatch with unexpected set of modifiers
- ok(!hit, "Shortcut isn't notified before firing the key event");
- EventUtils.synthesizeKey("a",
- { accelKey: true, altKey: true, shiftKey: true },
- window);
- EventUtils.synthesizeKey(
- "a",
- { accelKey: true, altKey: false, shiftKey: false },
- window);
- EventUtils.synthesizeKey(
- "a",
- { accelKey: false, altKey: false, shiftKey: true },
- window);
- EventUtils.synthesizeKey(
- "a",
- { accelKey: false, altKey: false, shiftKey: false },
- window);
- // Wait an extra time to let a chance to call the listener
- yield new Promise(done => {
- window.setTimeout(done, 0);
- });
- ok(!hit, "Listener isn't called when modifiers aren't exactly matching");
- // Dispatch the expected modifiers
- EventUtils.synthesizeKey("a", { accelKey: false, altKey: true, shiftKey: false},
- window);
- yield onKey;
- ok(hit, "Got shortcut notified once it is actually fired");
- }
- // Some keys are only accessible via shift and listener should also be called
- // even if the key didn't explicitely requested Shift modifier.
- // For example, `%` on french keyboards is only accessible via Shift.
- // Same thing for `@` on US keybords.
- function* testLooseShiftModifier(shortcuts) {
- info("Test Loose shift modifier");
- let onKey = once(shortcuts, "%", (key, event) => {
- is(event.key, "%");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(event.shiftKey);
- });
- EventUtils.synthesizeKey(
- "%",
- { accelKey: false, altKey: false, ctrlKey: false, shiftKey: true},
- window);
- yield onKey;
- onKey = once(shortcuts, "@", (key, event) => {
- is(event.key, "@");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(event.shiftKey);
- });
- EventUtils.synthesizeKey(
- "@",
- { accelKey: false, altKey: false, ctrlKey: false, shiftKey: true},
- window);
- yield onKey;
- }
- // But Shift modifier is strict on all letter characters (a to Z)
- function* testStrictLetterShiftModifier(shortcuts) {
- info("Test strict shift modifier on letters");
- let hitFirst = false;
- let onKey = once(shortcuts, "a", (key, event) => {
- is(event.key, "a");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(!event.shiftKey);
- hitFirst = true;
- });
- let onShiftKey = once(shortcuts, "Shift+a", (key, event) => {
- is(event.key, "a");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(event.shiftKey);
- });
- EventUtils.synthesizeKey(
- "a",
- { shiftKey: true},
- window);
- yield onShiftKey;
- ok(!hitFirst, "Didn't fire the explicit shift+a");
- EventUtils.synthesizeKey(
- "a",
- { shiftKey: false},
- window);
- yield onKey;
- }
- function* testAltModifier(shortcuts) {
- info("Test Alt modifier");
- let onKey = once(shortcuts, "Alt+F1", (key, event) => {
- is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
- ok(event.altKey);
- ok(!event.ctrlKey);
- ok(!event.metaKey);
- ok(!event.shiftKey);
- });
- EventUtils.synthesizeKey(
- "VK_F1",
- { altKey: true },
- window);
- yield onKey;
- }
- function* testCommandOrControlModifier(shortcuts) {
- info("Test CommandOrControl modifier");
- let onKey = once(shortcuts, "CommandOrControl+F1", (key, event) => {
- is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
- ok(!event.altKey);
- if (isOSX) {
- ok(!event.ctrlKey);
- ok(event.metaKey);
- } else {
- ok(event.ctrlKey);
- ok(!event.metaKey);
- }
- ok(!event.shiftKey);
- });
- let onKeyAlias = once(shortcuts, "CmdOrCtrl+F1", (key, event) => {
- is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
- ok(!event.altKey);
- if (isOSX) {
- ok(!event.ctrlKey);
- ok(event.metaKey);
- } else {
- ok(event.ctrlKey);
- ok(!event.metaKey);
- }
- ok(!event.shiftKey);
- });
- if (isOSX) {
- EventUtils.synthesizeKey(
- "VK_F1",
- { metaKey: true },
- window);
- } else {
- EventUtils.synthesizeKey(
- "VK_F1",
- { ctrlKey: true },
- window);
- }
- yield onKey;
- yield onKeyAlias;
- }
- function* testCtrlModifier(shortcuts) {
- info("Test Ctrl modifier");
- let onKey = once(shortcuts, "Ctrl+F1", (key, event) => {
- is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
- ok(!event.altKey);
- ok(event.ctrlKey);
- ok(!event.metaKey);
- ok(!event.shiftKey);
- });
- let onKeyAlias = once(shortcuts, "Control+F1", (key, event) => {
- is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
- ok(!event.altKey);
- ok(event.ctrlKey);
- ok(!event.metaKey);
- ok(!event.shiftKey);
- });
- EventUtils.synthesizeKey(
- "VK_F1",
- { ctrlKey: true },
- window);
- yield onKey;
- yield onKeyAlias;
- }
- function* testCmdShiftShortcut(shortcuts) {
- if (!isOSX) {
- // This test is OSX only (Bug 1300458).
- return;
- }
- let onCmdKey = once(shortcuts, "CmdOrCtrl+[", (key, event) => {
- is(event.key, "[");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(event.metaKey);
- ok(!event.shiftKey);
- });
- let onCmdShiftKey = once(shortcuts, "CmdOrCtrl+Shift+[", (key, event) => {
- is(event.key, "[");
- ok(!event.altKey);
- ok(!event.ctrlKey);
- ok(event.metaKey);
- ok(event.shiftKey);
- });
- EventUtils.synthesizeKey(
- "[",
- { metaKey: true, shiftKey: true },
- window);
- EventUtils.synthesizeKey(
- "[",
- { metaKey: true },
- window);
- yield onCmdKey;
- yield onCmdShiftKey;
- }
- function* testTarget() {
- info("Test KeyShortcuts with target argument");
- let target = document.createElementNS("http://www.w3.org/1999/xhtml",
- "input");
- document.documentElement.appendChild(target);
- target.focus();
- let shortcuts = new KeyShortcuts({
- window,
- target
- });
- let onKey = once(shortcuts, "0", (key, event) => {
- is(event.key, "0");
- is(event.target, target);
- });
- EventUtils.synthesizeKey("0", {}, window);
- yield onKey;
- target.remove();
- shortcuts.destroy();
- }
- function testInvalidShortcutString(shortcuts) {
- info("Test wrong shortcut string");
- let shortcut = KeyShortcuts.parseElectronKey(window, "Cmmd+F");
- ok(!shortcut, "Passing a invalid shortcut string should return a null object");
- shortcuts.on("Cmmd+F", function () {});
- ok(true, "on() shouldn't throw when passing invalid shortcut string");
- }
|