Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,737 @@
|
||||
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('goog.ui.KeyboardShortcutHandlerTest');
|
||||
goog.setTestOnly('goog.ui.KeyboardShortcutHandlerTest');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.events.KeyCodes');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.PropertyReplacer');
|
||||
goog.require('goog.testing.StrictMock');
|
||||
goog.require('goog.testing.events');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.ui.KeyboardShortcutHandler');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
var Modifiers = goog.ui.KeyboardShortcutHandler.Modifiers;
|
||||
var KeyCodes = goog.events.KeyCodes;
|
||||
|
||||
var handler;
|
||||
var targetDiv;
|
||||
var listener;
|
||||
var mockClock;
|
||||
var stubs = new goog.testing.PropertyReplacer();
|
||||
|
||||
|
||||
/**
|
||||
* Fires a keypress on the target div.
|
||||
* @return {boolean} The returnValue of the sequence: false if
|
||||
* preventDefault() was called on any of the events, true otherwise.
|
||||
*/
|
||||
function fire(keycode, opt_extraProperties, opt_element) {
|
||||
return goog.testing.events.fireKeySequence(
|
||||
opt_element || targetDiv, keycode, opt_extraProperties);
|
||||
}
|
||||
|
||||
function fireAltGraphKey(keycode, keyPressKeyCode, opt_extraProperties,
|
||||
opt_element) {
|
||||
return goog.testing.events.fireNonAsciiKeySequence(
|
||||
opt_element || targetDiv, keycode, keyPressKeyCode,
|
||||
opt_extraProperties);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
targetDiv = goog.dom.getElement('targetDiv');
|
||||
handler = new goog.ui.KeyboardShortcutHandler(
|
||||
goog.dom.getElement('rootDiv'));
|
||||
|
||||
// Create a mock event listener in order to set expectations on what
|
||||
// events are fired. We create a fake class whose only method is
|
||||
// shortcutFired(shortcut identifier).
|
||||
listener = new goog.testing.StrictMock(
|
||||
{shortcutFired: goog.nullFunction});
|
||||
goog.events.listen(
|
||||
handler,
|
||||
goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED,
|
||||
function(event) { listener.shortcutFired(event.identifier); });
|
||||
|
||||
// Set up a fake clock, because keyboard shortcuts *are* time
|
||||
// sensitive.
|
||||
mockClock = new goog.testing.MockClock(true);
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
mockClock.uninstall();
|
||||
handler.dispose();
|
||||
stubs.reset();
|
||||
}
|
||||
|
||||
function testAllowsSingleLetterKeyBindingsSpecifiedAsString() {
|
||||
listener.shortcutFired('lettergee');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergee', 'g');
|
||||
fire(KeyCodes.G);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsSingleLetterKeyBindingsSpecifiedAsKeyCode() {
|
||||
listener.shortcutFired('lettergee');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergee', KeyCodes.G);
|
||||
fire(KeyCodes.G);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testDoesntFireWhenWrongKeyIsPressed() {
|
||||
listener.$replay(); // no events expected
|
||||
|
||||
handler.registerShortcut('letterjay', 'j');
|
||||
fire(KeyCodes.G);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsControlAndLetterSpecifiedAsAString() {
|
||||
listener.shortcutFired('lettergee');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergee', 'ctrl+g');
|
||||
fire(KeyCodes.G, {ctrlKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsControlAndLetterSpecifiedAsArgSequence() {
|
||||
listener.shortcutFired('lettergeectrl');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergeectrl',
|
||||
KeyCodes.G, Modifiers.CTRL);
|
||||
fire(KeyCodes.G, {ctrlKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsControlAndLetterSpecifiedAsArray() {
|
||||
listener.shortcutFired('lettergeectrl');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergeectrl',
|
||||
[KeyCodes.G, Modifiers.CTRL]);
|
||||
fire(KeyCodes.G, {ctrlKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsShift() {
|
||||
listener.shortcutFired('lettergeeshift');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergeeshift',
|
||||
[KeyCodes.G, Modifiers.SHIFT]);
|
||||
fire(KeyCodes.G, {shiftKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsAlt() {
|
||||
listener.shortcutFired('lettergeealt');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergeealt',
|
||||
[KeyCodes.G, Modifiers.ALT]);
|
||||
fire(KeyCodes.G, {altKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsMeta() {
|
||||
listener.shortcutFired('lettergeemeta');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergeemeta',
|
||||
[KeyCodes.G, Modifiers.META]);
|
||||
fire(KeyCodes.G, {metaKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsMultipleModifiers() {
|
||||
listener.shortcutFired('lettergeectrlaltshift');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergeectrlaltshift',
|
||||
KeyCodes.G, Modifiers.CTRL | Modifiers.ALT | Modifiers.SHIFT);
|
||||
fire(KeyCodes.G, {ctrlKey: true, altKey: true, shiftKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsMultipleModifiersSpecifiedAsString() {
|
||||
listener.shortcutFired('lettergeectrlaltshiftmeta');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('lettergeectrlaltshiftmeta',
|
||||
'ctrl+shift+alt+meta+g');
|
||||
fire(KeyCodes.G,
|
||||
{ctrlKey: true, altKey: true, shiftKey: true, metaKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testPreventsDefaultOnReturnFalse() {
|
||||
listener.shortcutFired('x');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('x', 'x');
|
||||
var key = goog.events.listen(handler,
|
||||
goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED,
|
||||
function(event) { return false });
|
||||
|
||||
assertFalse('return false in listener must prevent default',
|
||||
fire(KeyCodes.X));
|
||||
|
||||
listener.$verify();
|
||||
|
||||
goog.events.unlistenByKey(key);
|
||||
}
|
||||
|
||||
function testPreventsDefaultWhenExceptionThrown() {
|
||||
handler.registerShortcut('x', 'x');
|
||||
handler.setAlwaysPreventDefault(true);
|
||||
goog.events.listenOnce(handler,
|
||||
goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED,
|
||||
function(event) { throw new Error('x'); });
|
||||
|
||||
// We can't use the standard infrastructure to detect that
|
||||
// the event was preventDefaulted, because of the exception.
|
||||
var callCount = 0;
|
||||
stubs.set(goog.events.BrowserEvent.prototype, 'preventDefault',
|
||||
function() {
|
||||
callCount++;
|
||||
});
|
||||
|
||||
var e = assertThrows(goog.partial(fire, KeyCodes.X));
|
||||
assertEquals('x', e.message);
|
||||
|
||||
assertEquals(1, callCount);
|
||||
}
|
||||
|
||||
function testDoesntFireWhenUserForgetsRequiredModifier() {
|
||||
listener.$replay(); // no events expected
|
||||
|
||||
handler.registerShortcut('lettergeectrl',
|
||||
KeyCodes.G, Modifiers.CTRL);
|
||||
fire(KeyCodes.G);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testDoesntFireIfTooManyModifiersPressed() {
|
||||
listener.$replay(); // no events expected
|
||||
|
||||
handler.registerShortcut('lettergeectrl',
|
||||
KeyCodes.G, Modifiers.CTRL);
|
||||
fire(KeyCodes.G, {ctrlKey: true, metaKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testDoesntFireIfAnyRequiredModifierForgotten() {
|
||||
listener.$replay(); // no events expected
|
||||
|
||||
handler.registerShortcut('lettergeectrlaltshift',
|
||||
KeyCodes.G, Modifiers.CTRL | Modifiers.ALT | Modifiers.SHIFT);
|
||||
fire(KeyCodes.G, {altKey: true, shiftKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsMultiKeySequenceSpecifiedAsArray() {
|
||||
listener.shortcutFired('quitemacs');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('quitemacs',
|
||||
[KeyCodes.X, Modifiers.CTRL,
|
||||
KeyCodes.C]);
|
||||
assertFalse(fire(KeyCodes.X, {ctrlKey: true}));
|
||||
fire(KeyCodes.C);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsMultiKeySequenceSpecifiedAsArguments() {
|
||||
listener.shortcutFired('quitvi');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('quitvi',
|
||||
KeyCodes.SEMICOLON, Modifiers.SHIFT,
|
||||
KeyCodes.Q, Modifiers.NONE,
|
||||
KeyCodes.NUM_ONE, Modifiers.SHIFT);
|
||||
var shiftProperties = { shiftKey: true };
|
||||
assertFalse(fire(KeyCodes.SEMICOLON, shiftProperties));
|
||||
assertFalse(fire(KeyCodes.Q));
|
||||
fire(KeyCodes.NUM_ONE, shiftProperties);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testMultiKeyEventIsNotFiredIfUserIsTooSlow() {
|
||||
listener.$replay(); // no events expected
|
||||
|
||||
handler.registerShortcut('quitemacs',
|
||||
[KeyCodes.X, Modifiers.CTRL,
|
||||
KeyCodes.C]);
|
||||
|
||||
fire(KeyCodes.X, {ctrlKey: true});
|
||||
|
||||
// Wait 3 seconds before hitting C. Although the actual limit is 1500
|
||||
// at time of writing, it's best not to over-specify functionality.
|
||||
mockClock.tick(3000);
|
||||
|
||||
fire(KeyCodes.C);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testAllowsMultipleAHandlers() {
|
||||
listener.shortcutFired('quitvi');
|
||||
listener.shortcutFired('letterex');
|
||||
listener.shortcutFired('quitemacs');
|
||||
listener.$replay();
|
||||
|
||||
// register 3 handlers in 3 diferent ways
|
||||
handler.registerShortcut('quitvi',
|
||||
KeyCodes.SEMICOLON, Modifiers.SHIFT,
|
||||
KeyCodes.Q, Modifiers.NONE,
|
||||
KeyCodes.NUM_ONE, Modifiers.SHIFT);
|
||||
handler.registerShortcut('quitemacs',
|
||||
[KeyCodes.X, Modifiers.CTRL,
|
||||
KeyCodes.C]);
|
||||
handler.registerShortcut('letterex', 'x');
|
||||
|
||||
|
||||
// quit vi
|
||||
var shiftProperties = { shiftKey: true };
|
||||
fire(KeyCodes.SEMICOLON, shiftProperties);
|
||||
fire(KeyCodes.Q);
|
||||
fire(KeyCodes.NUM_ONE, shiftProperties);
|
||||
|
||||
// then press the letter x
|
||||
fire(KeyCodes.X);
|
||||
|
||||
// then quit emacs
|
||||
fire(KeyCodes.X, {ctrlKey: true});
|
||||
fire(KeyCodes.C);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testCanRemoveOneHandler() {
|
||||
listener.shortcutFired('letterex');
|
||||
listener.$replay();
|
||||
|
||||
// register 2 handlers, then remove quitvi
|
||||
handler.registerShortcut('quitvi',
|
||||
KeyCodes.COLON, Modifiers.NONE,
|
||||
KeyCodes.Q, Modifiers.NONE,
|
||||
KeyCodes.EXCLAMATION, Modifiers.NONE);
|
||||
handler.registerShortcut('letterex', 'x');
|
||||
handler.unregisterShortcut(
|
||||
KeyCodes.COLON, Modifiers.NONE,
|
||||
KeyCodes.Q, Modifiers.NONE,
|
||||
KeyCodes.EXCLAMATION, Modifiers.NONE);
|
||||
|
||||
// call the "quit VI" keycodes, even though it is removed
|
||||
fire(KeyCodes.COLON);
|
||||
fire(KeyCodes.Q);
|
||||
fire(KeyCodes.EXCLAMATION);
|
||||
|
||||
// press the letter x
|
||||
fire(KeyCodes.X);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testCanRemoveTwoHandlers() {
|
||||
listener.$replay(); // no events expected
|
||||
|
||||
handler.registerShortcut('quitemacs',
|
||||
[KeyCodes.X, Modifiers.CTRL,
|
||||
KeyCodes.C]);
|
||||
handler.registerShortcut('letterex', 'x');
|
||||
handler.unregisterShortcut(
|
||||
[KeyCodes.X, Modifiers.CTRL,
|
||||
KeyCodes.C]);
|
||||
handler.unregisterShortcut('x');
|
||||
|
||||
fire(KeyCodes.X, {ctrlKey: true});
|
||||
fire(KeyCodes.C);
|
||||
fire(KeyCodes.X);
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testIsShortcutRegistered_single() {
|
||||
assertFalse(handler.isShortcutRegistered('x'));
|
||||
handler.registerShortcut('letterex', 'x');
|
||||
assertTrue(handler.isShortcutRegistered('x'));
|
||||
handler.unregisterShortcut('x');
|
||||
assertFalse(handler.isShortcutRegistered('x'));
|
||||
}
|
||||
|
||||
function testIsShortcutRegistered_multi() {
|
||||
assertFalse(handler.isShortcutRegistered('a'));
|
||||
assertFalse(handler.isShortcutRegistered('a b'));
|
||||
assertFalse(handler.isShortcutRegistered('a b c'));
|
||||
|
||||
handler.registerShortcut('ab', 'a b');
|
||||
|
||||
assertFalse(handler.isShortcutRegistered('a'));
|
||||
assertTrue(handler.isShortcutRegistered('a b'));
|
||||
assertFalse(handler.isShortcutRegistered('a b c'));
|
||||
|
||||
handler.unregisterShortcut('a b');
|
||||
|
||||
assertFalse(handler.isShortcutRegistered('a'));
|
||||
assertFalse(handler.isShortcutRegistered('a b'));
|
||||
assertFalse(handler.isShortcutRegistered('a b c'));
|
||||
}
|
||||
|
||||
function testUnregister_subsequence() {
|
||||
// Unregistering a partial sequence should not orphan shortcuts further in the
|
||||
// sequence.
|
||||
handler.registerShortcut('abc', 'a b c');
|
||||
handler.unregisterShortcut('a b');
|
||||
assertTrue(handler.isShortcutRegistered('a b c'));
|
||||
}
|
||||
|
||||
function testUnregister_supersequence() {
|
||||
// Unregistering a sequence that extends beyond a registered sequence should
|
||||
// do nothing.
|
||||
handler.registerShortcut('ab', 'a b');
|
||||
handler.unregisterShortcut('a b c');
|
||||
assertTrue(handler.isShortcutRegistered('a b'));
|
||||
}
|
||||
|
||||
function testUnregister_partialMatchSequence() {
|
||||
// Unregistering a sequence that partially matches a registered sequence
|
||||
// should do nothing.
|
||||
handler.registerShortcut('abc', 'a b c');
|
||||
handler.unregisterShortcut('a b x');
|
||||
assertTrue(handler.isShortcutRegistered('a b c'));
|
||||
}
|
||||
|
||||
function testUnregister_deadBranch() {
|
||||
// Unregistering a sequence should prune any dead branches in the tree.
|
||||
handler.registerShortcut('abc', 'a b c');
|
||||
handler.unregisterShortcut('a b c');
|
||||
// Default is not should not be prevented in the A key stroke because the A
|
||||
// branch has been removed from the tree.
|
||||
assertTrue(fire(KeyCodes.A));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a slew of keyboard shortcuts to test each primary category
|
||||
* of shortcuts.
|
||||
*/
|
||||
function registerEnterSpaceXF1AltY() {
|
||||
// Enter and space are specially handled keys.
|
||||
handler.registerShortcut('enter', KeyCodes.ENTER);
|
||||
handler.registerShortcut('space', KeyCodes.SPACE);
|
||||
// 'x' should be treated as text in many contexts
|
||||
handler.registerShortcut('x', 'x');
|
||||
// F1 is a global shortcut.
|
||||
handler.registerShortcut('global', KeyCodes.F1);
|
||||
// Alt-Y has modifiers, which pass through most form elements.
|
||||
handler.registerShortcut('withAlt', 'alt+y');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fires enter, space, X, F1, and Alt-Y keys on a widget.
|
||||
* @param {Element} target The element on which to fire the events.
|
||||
*/
|
||||
function fireEnterSpaceXF1AltY(target) {
|
||||
fire(KeyCodes.ENTER, undefined, target);
|
||||
fire(KeyCodes.SPACE, undefined, target);
|
||||
fire(KeyCodes.X, undefined, target);
|
||||
fire(KeyCodes.F1, undefined, target);
|
||||
fire(KeyCodes.Y, {altKey: true}, target);
|
||||
}
|
||||
|
||||
function testIgnoreNonGlobalShortcutsInSelect() {
|
||||
var targetSelect = goog.dom.getElement('targetSelect');
|
||||
|
||||
listener.shortcutFired('global');
|
||||
listener.shortcutFired('withAlt');
|
||||
listener.$replay();
|
||||
|
||||
registerEnterSpaceXF1AltY();
|
||||
fireEnterSpaceXF1AltY(goog.dom.getElement('targetSelect'));
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testIgnoreNonGlobalShortcutsInTextArea() {
|
||||
listener.shortcutFired('global');
|
||||
listener.shortcutFired('withAlt');
|
||||
listener.$replay();
|
||||
|
||||
registerEnterSpaceXF1AltY();
|
||||
fireEnterSpaceXF1AltY(goog.dom.getElement('targetTextArea'));
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks that the shortcuts are fired on each target.
|
||||
* @param {Array<string>} shortcuts A list of shortcut identifiers.
|
||||
* @param {Array<string>} targets A list of element IDs.
|
||||
* @param {function(Element)} fireEvents Function that fires events.
|
||||
*/
|
||||
function expectShortcutsOnTargets(shortcuts, targets, fireEvents) {
|
||||
for (var i = 0, ii = targets.length; i < ii; i++) {
|
||||
for (var j = 0, jj = shortcuts.length; j < jj; j++) {
|
||||
listener.shortcutFired(shortcuts[j]);
|
||||
}
|
||||
listener.$replay();
|
||||
fireEvents(goog.dom.getElement(targets[i]));
|
||||
listener.$verify();
|
||||
listener.$reset();
|
||||
}
|
||||
}
|
||||
|
||||
function testIgnoreShortcutsExceptEnterInTextInputFields() {
|
||||
var targets = [
|
||||
'targetColor',
|
||||
'targetDate',
|
||||
'targetDateTime',
|
||||
'targetDateTimeLocal',
|
||||
'targetEmail',
|
||||
'targetMonth',
|
||||
'targetNumber',
|
||||
'targetPassword',
|
||||
'targetSearch',
|
||||
'targetTel',
|
||||
'targetText',
|
||||
'targetTime',
|
||||
'targetUrl',
|
||||
'targetWeek'
|
||||
];
|
||||
registerEnterSpaceXF1AltY();
|
||||
expectShortcutsOnTargets(
|
||||
['enter', 'global', 'withAlt'], targets, fireEnterSpaceXF1AltY);
|
||||
}
|
||||
|
||||
function testIgnoreSpaceInCheckBoxAndButton() {
|
||||
registerEnterSpaceXF1AltY();
|
||||
expectShortcutsOnTargets(
|
||||
['enter', 'x', 'global', 'withAlt'],
|
||||
['targetCheckBox', 'targetButton'],
|
||||
fireEnterSpaceXF1AltY);
|
||||
}
|
||||
|
||||
function testIgnoreNonGlobalShortcutsInContentEditable() {
|
||||
// Don't set design mode in later IE as javascripts don't run when in
|
||||
// that mode.
|
||||
var setDesignMode = !goog.userAgent.IE ||
|
||||
!goog.userAgent.isVersionOrHigher('9');
|
||||
try {
|
||||
if (setDesignMode) {
|
||||
document.designMode = 'on';
|
||||
}
|
||||
targetDiv.contentEditable = 'true';
|
||||
|
||||
// Expect only global shortcuts.
|
||||
listener.shortcutFired('global');
|
||||
listener.$replay();
|
||||
|
||||
registerEnterSpaceXF1AltY();
|
||||
fireEnterSpaceXF1AltY(targetDiv);
|
||||
|
||||
listener.$verify();
|
||||
} finally {
|
||||
if (setDesignMode) {
|
||||
document.designMode = 'off';
|
||||
}
|
||||
targetDiv.contentEditable = 'false';
|
||||
}
|
||||
}
|
||||
|
||||
function testSetAllShortcutsAreGlobal() {
|
||||
handler.setAllShortcutsAreGlobal(true);
|
||||
registerEnterSpaceXF1AltY();
|
||||
|
||||
expectShortcutsOnTargets(
|
||||
['enter', 'space', 'x', 'global', 'withAlt'], ['targetTextArea'],
|
||||
fireEnterSpaceXF1AltY);
|
||||
}
|
||||
|
||||
function testSetModifierShortcutsAreGlobalFalse() {
|
||||
handler.setModifierShortcutsAreGlobal(false);
|
||||
registerEnterSpaceXF1AltY();
|
||||
|
||||
expectShortcutsOnTargets(
|
||||
['global'], ['targetTextArea'], fireEnterSpaceXF1AltY);
|
||||
}
|
||||
|
||||
function testAltGraphKeyOnUSLayout() {
|
||||
// Windows does not assign printable characters to any ctrl+alt keys of
|
||||
// the US layout. This test verifies we fire shortcut events when typing
|
||||
// ctrl+alt keys on the US layout.
|
||||
listener.shortcutFired('letterOne');
|
||||
listener.shortcutFired('letterTwo');
|
||||
listener.shortcutFired('letterThree');
|
||||
listener.shortcutFired('letterFour');
|
||||
listener.shortcutFired('letterFive');
|
||||
if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('letterOne', 'ctrl+alt+1');
|
||||
handler.registerShortcut('letterTwo', 'ctrl+alt+2');
|
||||
handler.registerShortcut('letterThree', 'ctrl+alt+3');
|
||||
handler.registerShortcut('letterFour', 'ctrl+alt+4');
|
||||
handler.registerShortcut('letterFive', 'ctrl+alt+5');
|
||||
|
||||
// Send key events on the English (United States) layout.
|
||||
fireAltGraphKey(KeyCodes.ONE, 0, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.TWO, 0, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.THREE, 0, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.FOUR, 0, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.FIVE, 0, {ctrlKey: true, altKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
}
|
||||
|
||||
function testAltGraphKeyOnFrenchLayout() {
|
||||
// Windows assigns printable characters to ctrl+alt+[2-5] keys of the
|
||||
// French layout. This test verifies we fire shortcut events only when
|
||||
// we type ctrl+alt+1 keys on the French layout.
|
||||
listener.shortcutFired('letterOne');
|
||||
if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('letterOne', 'ctrl+alt+1');
|
||||
handler.registerShortcut('letterTwo', 'ctrl+alt+2');
|
||||
handler.registerShortcut('letterThree', 'ctrl+alt+3');
|
||||
handler.registerShortcut('letterFour', 'ctrl+alt+4');
|
||||
handler.registerShortcut('letterFive', 'ctrl+alt+5');
|
||||
|
||||
// Send key events on the French (France) layout.
|
||||
fireAltGraphKey(KeyCodes.ONE, 0, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.TWO, 0x0303, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.THREE, 0x0023, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.FOUR, 0x007b, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.FIVE, 0x205b, {ctrlKey: true, altKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
}
|
||||
|
||||
function testAltGraphKeyOnSpanishLayout() {
|
||||
// Windows assigns printable characters to ctrl+alt+[1-5] keys of the
|
||||
// Spanish layout. This test verifies we do not fire shortcut events at
|
||||
// all when typing ctrl+alt+[1-5] keys on the Spanish layout.
|
||||
if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('letterOne', 'ctrl+alt+1');
|
||||
handler.registerShortcut('letterTwo', 'ctrl+alt+2');
|
||||
handler.registerShortcut('letterThree', 'ctrl+alt+3');
|
||||
handler.registerShortcut('letterFour', 'ctrl+alt+4');
|
||||
handler.registerShortcut('letterFive', 'ctrl+alt+5');
|
||||
|
||||
// Send key events on the Spanish (Spain) layout.
|
||||
fireAltGraphKey(KeyCodes.ONE, 0x007c, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.TWO, 0x0040, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.THREE, 0x0023, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.FOUR, 0x0303, {ctrlKey: true, altKey: true});
|
||||
fireAltGraphKey(KeyCodes.FIVE, 0x20ac, {ctrlKey: true, altKey: true});
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
}
|
||||
|
||||
function testNumpadKeyShortcuts() {
|
||||
var testCases = [
|
||||
['letterNumpad0', 'num-0', KeyCodes.NUM_ZERO],
|
||||
['letterNumpad1', 'num-1', KeyCodes.NUM_ONE],
|
||||
['letterNumpad2', 'num-2', KeyCodes.NUM_TWO],
|
||||
['letterNumpad3', 'num-3', KeyCodes.NUM_THREE],
|
||||
['letterNumpad4', 'num-4', KeyCodes.NUM_FOUR],
|
||||
['letterNumpad5', 'num-5', KeyCodes.NUM_FIVE],
|
||||
['letterNumpad6', 'num-6', KeyCodes.NUM_SIX],
|
||||
['letterNumpad7', 'num-7', KeyCodes.NUM_SEVEN],
|
||||
['letterNumpad8', 'num-8', KeyCodes.NUM_EIGHT],
|
||||
['letterNumpad9', 'num-9', KeyCodes.NUM_NINE],
|
||||
['letterNumpadMultiply', 'num-multiply', KeyCodes.NUM_MULTIPLY],
|
||||
['letterNumpadPlus', 'num-plus', KeyCodes.NUM_PLUS],
|
||||
['letterNumpadMinus', 'num-minus', KeyCodes.NUM_MINUS],
|
||||
['letterNumpadPERIOD', 'num-period', KeyCodes.NUM_PERIOD],
|
||||
['letterNumpadDIVISION', 'num-division', KeyCodes.NUM_DIVISION]
|
||||
];
|
||||
for (var i = 0; i < testCases.length; ++i) {
|
||||
listener.shortcutFired(testCases[i][0]);
|
||||
}
|
||||
listener.$replay();
|
||||
|
||||
// Register shortcuts for numpad keys and send numpad-key events.
|
||||
for (var i = 0; i < testCases.length; ++i) {
|
||||
handler.registerShortcut(testCases[i][0], testCases[i][1]);
|
||||
fire(testCases[i][2]);
|
||||
}
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testGeckoShortcuts() {
|
||||
listener.shortcutFired('1');
|
||||
listener.$replay();
|
||||
|
||||
handler.registerShortcut('1', 'semicolon');
|
||||
|
||||
if (goog.userAgent.GECKO) {
|
||||
fire(goog.events.KeyCodes.FF_SEMICOLON);
|
||||
} else {
|
||||
fire(goog.events.KeyCodes.SEMICOLON);
|
||||
}
|
||||
|
||||
listener.$verify();
|
||||
}
|
||||
|
||||
function testRegisterShortcut_modifierOnly() {
|
||||
assertThrows('Registering a shortcut with just modifiers should fail.',
|
||||
goog.bind(handler.registerShortcut, handler, 'name', 'Shift'));
|
||||
}
|
||||
|
||||
function testParseStringShortcut_unknownKey() {
|
||||
assertThrows('Unknown keys should fail.', goog.bind(
|
||||
goog.ui.KeyboardShortcutHandler.parseStringShortcut, null, 'NotAKey'));
|
||||
}
|
||||
|
||||
// Regression test for failure to reset keyCode between strokes.
|
||||
function testParseStringShortcut_resetKeyCode() {
|
||||
var strokes = goog.ui.KeyboardShortcutHandler.parseStringShortcut('A Shift');
|
||||
assertNull('The second stroke only has a modifier key.', strokes[1].keyCode);
|
||||
}
|
||||
Reference in New Issue
Block a user