mirror of
https://github.com/google/blockly.git
synced 2026-01-08 17:40:09 +01:00
* chore: change goog.module to goog.declareModuleId * chore: change test helper exports to esmod exports * chore: change test helpers to use esmodule imports * chore: convert imports of test helpers to esmodule imports * chore: convert other imports in tests to esm imports * fix: make imports use built files * chore: add blockly imports to a bunch of tests * fix: reference Blockly.Blocks instead of Blocks' * fix: properly import generators * chore: fix lint * chore: cleanup from rebase * chore: cleanup from rebase * chore: fix blocks tests
393 lines
15 KiB
JavaScript
393 lines
15 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2020 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.declareModuleId('Blockly.test.shortcutRegistry');
|
|
|
|
import {createKeyDownEvent} from './test_helpers/user_input.js';
|
|
import {sharedTestSetup, sharedTestTeardown} from './test_helpers/setup_teardown.js';
|
|
|
|
|
|
suite('Keyboard Shortcut Registry Test', function() {
|
|
setup(function() {
|
|
sharedTestSetup.call(this);
|
|
this.registry = Blockly.ShortcutRegistry.registry;
|
|
this.registry.reset();
|
|
Blockly.ShortcutItems.registerDefaultShortcuts();
|
|
});
|
|
teardown(function() {
|
|
sharedTestTeardown.call(this);
|
|
});
|
|
|
|
suite('Registering', function() {
|
|
test('Registering a shortcut', function() {
|
|
const testShortcut = {'name': 'test_shortcut'};
|
|
this.registry.register(testShortcut, true);
|
|
const shortcut = this.registry.registry_['test_shortcut'];
|
|
chai.assert.equal(shortcut.name, 'test_shortcut');
|
|
});
|
|
test('Registers shortcut with same name', function() {
|
|
const registry = this.registry;
|
|
const testShortcut = {'name': 'test_shortcut'};
|
|
|
|
registry.registry_['test_shortcut'] = [testShortcut];
|
|
|
|
const shouldThrow = function() {
|
|
registry.register(testShortcut);
|
|
};
|
|
chai.assert.throws(
|
|
shouldThrow, Error,
|
|
'Shortcut with name "test_shortcut" already exists.');
|
|
});
|
|
test(
|
|
'Registers shortcut with same name opt_allowOverrides=true',
|
|
function() {
|
|
const registry = this.registry;
|
|
const testShortcut = {'name': 'test_shortcut'};
|
|
const otherShortcut = {
|
|
'name': 'test_shortcut',
|
|
'callback': function() {},
|
|
};
|
|
|
|
registry.registry_['test_shortcut'] = [testShortcut];
|
|
|
|
const shouldNotThrow = function() {
|
|
registry.register(otherShortcut, true);
|
|
};
|
|
chai.assert.doesNotThrow(shouldNotThrow);
|
|
chai.assert.exists(registry.registry_['test_shortcut'].callback);
|
|
});
|
|
test('Registering a shortcut with keycodes', function() {
|
|
const shiftA = this.registry.createSerializedKey(
|
|
'65', [Blockly.ShortcutRegistry.modifierKeys.Shift]);
|
|
const testShortcut = {
|
|
'name': 'test_shortcut',
|
|
'keyCodes': ['65', 66, shiftA],
|
|
};
|
|
this.registry.register(testShortcut, true);
|
|
chai.assert.lengthOf(this.registry.keyMap_[shiftA], 1);
|
|
chai.assert.lengthOf(this.registry.keyMap_['65'], 1);
|
|
chai.assert.lengthOf(this.registry.keyMap_['66'], 1);
|
|
});
|
|
test('Registering a shortcut with allowCollision', function() {
|
|
const testShortcut = {
|
|
'name': 'test_shortcut',
|
|
'keyCodes': ['65'],
|
|
};
|
|
const duplicateShortcut = {
|
|
'name': 'duplicate_shortcut',
|
|
'keyCodes': ['65'],
|
|
'allowCollision': true,
|
|
};
|
|
this.registry.register(testShortcut);
|
|
const registry = this.registry;
|
|
const shouldNotThrow = function() {
|
|
registry.register(duplicateShortcut);
|
|
};
|
|
chai.assert.doesNotThrow(shouldNotThrow);
|
|
});
|
|
});
|
|
|
|
suite('Unregistering', function() {
|
|
test('Unregistering a shortcut', function() {
|
|
const testShortcut = {'name': 'test_shortcut'};
|
|
this.registry.registry_['test'] = [testShortcut];
|
|
chai.assert.isOk(this.registry.registry_['test']);
|
|
this.registry.unregister('test', 'test_shortcut');
|
|
chai.assert.isUndefined(this.registry.registry_['test']);
|
|
});
|
|
test('Unregistering a nonexistent shortcut', function() {
|
|
const consoleStub = sinon.stub(console, 'warn');
|
|
chai.assert.isUndefined(this.registry.registry_['test']);
|
|
|
|
const registry = this.registry;
|
|
chai.assert.isFalse(registry.unregister('test', 'test_shortcut'));
|
|
sinon.assert.calledOnceWithExactly(consoleStub, 'Keyboard shortcut with name "test" not found.');
|
|
});
|
|
test('Unregistering a shortcut with key mappings', function() {
|
|
const testShortcut = {'name': 'test_shortcut'};
|
|
this.registry.keyMap_['keyCode'] = ['test_shortcut'];
|
|
this.registry.registry_['test_shortcut'] = testShortcut;
|
|
|
|
this.registry.unregister('test_shortcut');
|
|
|
|
const shortcut = this.registry.registry_['test'];
|
|
const keyMappings = this.registry.keyMap_['keyCode'];
|
|
chai.assert.isUndefined(shortcut);
|
|
chai.assert.isUndefined(keyMappings);
|
|
});
|
|
test('Unregistering a shortcut with colliding key mappings', function() {
|
|
const testShortcut = {'name': 'test_shortcut'};
|
|
this.registry.keyMap_['keyCode'] = ['test_shortcut', 'other_shortcutt'];
|
|
this.registry.registry_['test_shortcut'] = testShortcut;
|
|
|
|
this.registry.unregister('test_shortcut');
|
|
|
|
const shortcut = this.registry.registry_['test'];
|
|
const keyMappings = this.registry.keyMap_['keyCode'];
|
|
chai.assert.lengthOf(keyMappings, 1);
|
|
chai.assert.isUndefined(shortcut);
|
|
});
|
|
});
|
|
|
|
suite('addKeyMapping', function() {
|
|
test('Adds a key mapping', function() {
|
|
this.registry.registry_['test_shortcut'] = {'name': 'test_shortcut'};
|
|
|
|
this.registry.addKeyMapping('keyCode', 'test_shortcut');
|
|
|
|
const shortcutNames = this.registry.keyMap_['keyCode'];
|
|
chai.assert.lengthOf(shortcutNames, 1);
|
|
chai.assert.equal(shortcutNames[0], 'test_shortcut');
|
|
});
|
|
test('Adds a colliding key mapping - opt_allowCollision=true', function() {
|
|
this.registry.registry_['test_shortcut'] = {'name': 'test_shortcut'};
|
|
this.registry.keyMap_['keyCode'] = ['test_shortcut_2'];
|
|
|
|
this.registry.addKeyMapping('keyCode', 'test_shortcut', true);
|
|
|
|
const shortcutNames = this.registry.keyMap_['keyCode'];
|
|
chai.assert.lengthOf(shortcutNames, 2);
|
|
chai.assert.equal(shortcutNames[0], 'test_shortcut');
|
|
chai.assert.equal(shortcutNames[1], 'test_shortcut_2');
|
|
});
|
|
test('Adds a colliding key mapping - opt_allowCollision=false', function() {
|
|
this.registry.registry_['test_shortcut'] = {'name': 'test_shortcut'};
|
|
this.registry.keyMap_['keyCode'] = ['test_shortcut_2'];
|
|
|
|
const registry = this.registry;
|
|
const shouldThrow = function() {
|
|
registry.addKeyMapping('keyCode', 'test_shortcut');
|
|
};
|
|
chai.assert.throws(
|
|
shouldThrow, Error,
|
|
'Shortcut with name "test_shortcut" collides with shortcuts test_shortcut_2');
|
|
});
|
|
});
|
|
|
|
suite('removeKeyMapping', function() {
|
|
test('Removes a key mapping', function() {
|
|
this.registry.registry_['test_shortcut'] = {'name': 'test_shortcut'};
|
|
this.registry.keyMap_['keyCode'] = ['test_shortcut', 'test_shortcut_2'];
|
|
|
|
const isRemoved =
|
|
this.registry.removeKeyMapping('keyCode', 'test_shortcut');
|
|
|
|
const shortcutNames = this.registry.keyMap_['keyCode'];
|
|
chai.assert.lengthOf(shortcutNames, 1);
|
|
chai.assert.equal(shortcutNames[0], 'test_shortcut_2');
|
|
chai.assert.isTrue(isRemoved);
|
|
});
|
|
test('Removes last key mapping for a key', function() {
|
|
this.registry.registry_['test_shortcut'] = {'name': 'test_shortcut'};
|
|
this.registry.keyMap_['keyCode'] = ['test_shortcut'];
|
|
|
|
this.registry.removeKeyMapping('keyCode', 'test_shortcut');
|
|
|
|
const shortcutNames = this.registry.keyMap_['keyCode'];
|
|
chai.assert.isUndefined(shortcutNames);
|
|
});
|
|
test('Removes a key map that does not exist opt_quiet=false', function() {
|
|
const consoleStub = sinon.stub(console, 'warn');
|
|
this.registry.keyMap_['keyCode'] = ['test_shortcut_2'];
|
|
|
|
const isRemoved =
|
|
this.registry.removeKeyMapping('keyCode', 'test_shortcut');
|
|
|
|
chai.assert.isFalse(isRemoved);
|
|
sinon.assert.calledOnceWithExactly(
|
|
consoleStub,
|
|
'No keyboard shortcut with name "test_shortcut" registered with key code "keyCode"');
|
|
});
|
|
test(
|
|
'Removes a key map that does not exist from empty key mapping opt_quiet=false',
|
|
function() {
|
|
const consoleStub = sinon.stub(console, 'warn');
|
|
|
|
const isRemoved =
|
|
this.registry.removeKeyMapping('keyCode', 'test_shortcut');
|
|
|
|
chai.assert.isFalse(isRemoved);
|
|
sinon.assert.calledOnceWithExactly(
|
|
consoleStub,
|
|
'No keyboard shortcut with name "test_shortcut" registered with key code "keyCode"');
|
|
});
|
|
});
|
|
|
|
suite('Setters/Getters', function() {
|
|
test('Sets the key map', function() {
|
|
this.registry.setKeyMap({'keyCode': ['test_shortcut']});
|
|
chai.assert.lengthOf(Object.keys(this.registry.keyMap_), 1);
|
|
chai.assert.equal(this.registry.keyMap_['keyCode'][0], 'test_shortcut');
|
|
});
|
|
test('Gets a copy of the key map', function() {
|
|
this.registry.keyMap_['keyCode'] = ['a'];
|
|
const keyMapCopy = this.registry.getKeyMap();
|
|
keyMapCopy['keyCode'] = ['b'];
|
|
chai.assert.equal(this.registry.keyMap_['keyCode'][0], 'a');
|
|
});
|
|
test('Gets a copy of the registry', function() {
|
|
this.registry.registry_['shortcutName'] = {'name': 'shortcutName'};
|
|
const registrycopy = this.registry.getRegistry();
|
|
registrycopy['shortcutName']['name'] = 'shortcutName1';
|
|
chai.assert.equal(
|
|
this.registry.registry_['shortcutName']['name'], 'shortcutName');
|
|
});
|
|
test('Gets keyboard shortcuts from a key code', function() {
|
|
this.registry.keyMap_['keyCode'] = ['shortcutName'];
|
|
const shortcutNames = this.registry.getShortcutNamesByKeyCode('keyCode');
|
|
chai.assert.equal(shortcutNames[0], 'shortcutName');
|
|
});
|
|
test('Gets keycodes by shortcut name', function() {
|
|
this.registry.keyMap_['keyCode'] = ['shortcutName'];
|
|
this.registry.keyMap_['keyCode1'] = ['shortcutName'];
|
|
const shortcutNames =
|
|
this.registry.getKeyCodesByShortcutName('shortcutName');
|
|
chai.assert.lengthOf(shortcutNames, 2);
|
|
chai.assert.equal(shortcutNames[0], 'keyCode');
|
|
chai.assert.equal(shortcutNames[1], 'keyCode1');
|
|
});
|
|
});
|
|
|
|
suite('onKeyDown', function() {
|
|
function addShortcut(registry, shortcut, keyCode, returns) {
|
|
registry.register(shortcut, true);
|
|
registry.addKeyMapping(keyCode, shortcut.name, true);
|
|
return sinon.stub(shortcut, 'callback').returns(returns);
|
|
}
|
|
|
|
setup(function() {
|
|
this.testShortcut = {
|
|
'name': 'test_shortcut',
|
|
'callback': function() {
|
|
return true;
|
|
},
|
|
'precondition': function() {
|
|
return true;
|
|
},
|
|
};
|
|
this.callBackStub =
|
|
addShortcut(this.registry, this.testShortcut, Blockly.utils.KeyCodes.C, true);
|
|
});
|
|
test('Execute a shortcut from event', function() {
|
|
const event = createKeyDownEvent(Blockly.utils.KeyCodes.C);
|
|
chai.assert.isTrue(this.registry.onKeyDown(this.workspace, event));
|
|
sinon.assert.calledOnce(this.callBackStub);
|
|
});
|
|
test('No shortcut executed from event', function() {
|
|
const event = createKeyDownEvent(Blockly.utils.KeyCodes.D);
|
|
chai.assert.isFalse(this.registry.onKeyDown(this.workspace, event));
|
|
});
|
|
test('No precondition available - execute callback', function() {
|
|
delete this.testShortcut['precondition'];
|
|
const event = createKeyDownEvent(Blockly.utils.KeyCodes.C);
|
|
chai.assert.isTrue(this.registry.onKeyDown(this.workspace, event));
|
|
sinon.assert.calledOnce(this.callBackStub);
|
|
});
|
|
test('Execute all shortcuts in list', function() {
|
|
const event = createKeyDownEvent(Blockly.utils.KeyCodes.C);
|
|
const testShortcut2 = {
|
|
'name': 'test_shortcut_2',
|
|
'callback': function() {
|
|
return false;
|
|
},
|
|
'precondition': function() {
|
|
return false;
|
|
},
|
|
};
|
|
const testShortcut2Stub =
|
|
addShortcut(this.registry, testShortcut2, Blockly.utils.KeyCodes.C, false);
|
|
chai.assert.isTrue(this.registry.onKeyDown(this.workspace, event));
|
|
sinon.assert.calledOnce(testShortcut2Stub);
|
|
sinon.assert.calledOnce(this.callBackStub);
|
|
});
|
|
test('Stop executing shortcut when event is handled', function() {
|
|
const event = createKeyDownEvent(Blockly.utils.KeyCodes.C);
|
|
const testShortcut2 = {
|
|
'name': 'test_shortcut_2',
|
|
'callback': function() {
|
|
return false;
|
|
},
|
|
'precondition': function() {
|
|
return false;
|
|
},
|
|
};
|
|
const testShortcut2Stub =
|
|
addShortcut(this.registry, testShortcut2, Blockly.utils.KeyCodes.C, true);
|
|
chai.assert.isTrue(this.registry.onKeyDown(this.workspace, event));
|
|
sinon.assert.calledOnce(testShortcut2Stub);
|
|
sinon.assert.notCalled(this.callBackStub);
|
|
});
|
|
});
|
|
|
|
suite('createSerializedKey', function() {
|
|
test('Serialize key', function() {
|
|
const serializedKey =
|
|
this.registry.createSerializedKey(Blockly.utils.KeyCodes.A);
|
|
chai.assert.equal(serializedKey, '65');
|
|
});
|
|
|
|
test('Serialize key code and modifier', function() {
|
|
const serializedKey = this.registry.createSerializedKey(
|
|
Blockly.utils.KeyCodes.A, [Blockly.utils.KeyCodes.CTRL]);
|
|
chai.assert.equal(serializedKey, 'Control+65');
|
|
});
|
|
test('Serialize only a modifier', function() {
|
|
const serializedKey = this.registry.createSerializedKey(
|
|
null, [Blockly.utils.KeyCodes.CTRL]);
|
|
chai.assert.equal(serializedKey, 'Control');
|
|
});
|
|
test('Serialize multiple modifiers', function() {
|
|
const serializedKey = this.registry.createSerializedKey(
|
|
null, [Blockly.utils.KeyCodes.CTRL, Blockly.utils.KeyCodes.SHIFT]);
|
|
chai.assert.equal(serializedKey, 'Shift+Control');
|
|
});
|
|
test('Order of modifiers should result in same serialized key', function() {
|
|
const serializedKey = this.registry.createSerializedKey(
|
|
null, [Blockly.utils.KeyCodes.CTRL, Blockly.utils.KeyCodes.SHIFT]);
|
|
chai.assert.equal(serializedKey, 'Shift+Control');
|
|
const serializedKeyNewOrder = this.registry.createSerializedKey(
|
|
null, [Blockly.utils.KeyCodes.SHIFT, Blockly.utils.KeyCodes.CTRL]);
|
|
chai.assert.equal(serializedKeyNewOrder, 'Shift+Control');
|
|
});
|
|
});
|
|
|
|
suite('serializeKeyEvent', function() {
|
|
test('Serialize key', function() {
|
|
const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.A);
|
|
const serializedKey = this.registry.serializeKeyEvent_(mockEvent);
|
|
chai.assert.equal(serializedKey, '65');
|
|
});
|
|
test('Serialize key code and modifier', function() {
|
|
const mockEvent = createKeyDownEvent(
|
|
Blockly.utils.KeyCodes.A, [Blockly.utils.KeyCodes.CTRL]);
|
|
const serializedKey = this.registry.serializeKeyEvent_(mockEvent);
|
|
chai.assert.equal(serializedKey, 'Control+65');
|
|
});
|
|
test('Serialize only a modifier', function() {
|
|
const mockEvent =
|
|
createKeyDownEvent(null, [Blockly.utils.KeyCodes.CTRL]);
|
|
const serializedKey = this.registry.serializeKeyEvent_(mockEvent);
|
|
chai.assert.equal(serializedKey, 'Control');
|
|
});
|
|
test('Serialize multiple modifiers', function() {
|
|
const mockEvent = createKeyDownEvent(
|
|
null,
|
|
[Blockly.utils.KeyCodes.CTRL, Blockly.utils.KeyCodes.SHIFT]);
|
|
const serializedKey = this.registry.serializeKeyEvent_(mockEvent);
|
|
chai.assert.equal(serializedKey, 'Shift+Control');
|
|
});
|
|
test('Throw error when incorrect modifier', function() {
|
|
const registry = this.registry;
|
|
const shouldThrow = function() {
|
|
registry.createSerializedKey(Blockly.utils.KeyCodes.K, ['s']);
|
|
};
|
|
chai.assert.throws(shouldThrow, Error, 's is not a valid modifier key.');
|
|
});
|
|
});
|
|
|
|
teardown(function() {});
|
|
});
|