Files
vscode/src/vs/platform/keybinding/test/common/keybindingService.test.ts
T
2015-11-19 12:56:08 +01:00

312 lines
11 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import assert = require('assert');
import {CommonKeybindingResolver} from 'vs/platform/keybinding/common/commonKeybindingResolver';
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
import {KeybindingsUtils} from 'vs/platform/keybinding/common/keybindingsUtils';
import Platform = require('vs/base/common/platform');
import {IKeybindingContextRule, IKeybindingItem} from 'vs/platform/keybinding/common/keybindingService';
import {KeyMod, KeyCode, BinaryKeybindings} from 'vs/base/common/keyCodes';
suite('Keybinding Service', () => {
test('resolve key', function() {
var keybinding = KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z;
var contextRules = [{
key: 'bar',
operator: 'equal',
operand: 'baz'
}]
var keybindingItem: IKeybindingItem = {
command: 'yes',
context: contextRules,
keybinding: keybinding,
weight1: 0,
weight2: 0
};
assert.equal(CommonKeybindingResolver.contextMatchesRules({ bar: 'baz' }, contextRules), true);
assert.equal(CommonKeybindingResolver.contextMatchesRules({ bar: 'bz' }, contextRules), false);
var resolver = new CommonKeybindingResolver([keybindingItem], []);
assert.equal(resolver.resolve({ bar: 'baz' }, 0, keybinding).commandId, 'yes');
assert.equal(resolver.resolve({ bar: 'bz' }, 0, keybinding), null);
});
function createEqualContextRule(key: string, operand: any): IKeybindingContextRule {
return {
key: key,
operator: KeybindingsRegistry.KEYBINDING_CONTEXT_OPERATOR_EQUAL,
operand: operand
};
}
function createNotEqualContextRule(key: string, operand: any): IKeybindingContextRule {
return {
key: key,
operator: KeybindingsRegistry.KEYBINDING_CONTEXT_OPERATOR_NOT_EQUAL,
operand: operand
};
}
test('normalizeRule', function () {
var key1IsTrue = createEqualContextRule('key1', true);
var key1IsNotFalse = createNotEqualContextRule('key1', false);
var key1IsFalse = createEqualContextRule('key1', false);
var key1IsNotTrue = createNotEqualContextRule('key1', true);
assert.deepEqual(CommonKeybindingResolver.normalizeRule(key1IsTrue), key1IsTrue);
assert.deepEqual(CommonKeybindingResolver.normalizeRule(key1IsNotFalse), key1IsTrue);
assert.deepEqual(CommonKeybindingResolver.normalizeRule(key1IsFalse), key1IsFalse);
assert.deepEqual(CommonKeybindingResolver.normalizeRule(key1IsNotTrue), key1IsFalse);
});
test('contextIsEntirelyIncluded', function () {
var assertIsIncluded = (a: IKeybindingContextRule[], b: IKeybindingContextRule[]) => {
assert.equal(CommonKeybindingResolver.contextIsEntirelyIncluded(false, a, b), true);
};
var assertIsNotIncluded = (a: IKeybindingContextRule[], b: IKeybindingContextRule[]) => {
assert.equal(CommonKeybindingResolver.contextIsEntirelyIncluded(false, a, b), false);
};
var key1IsTrue = createEqualContextRule('key1', true);
var key1IsNotFalse = createNotEqualContextRule('key1', false);
var key1IsFalse = createEqualContextRule('key1', false);
var key1IsNotTrue = createNotEqualContextRule('key1', true);
var key2IsTrue = createEqualContextRule('key2', true);
var key2IsNotFalse = createNotEqualContextRule('key2', false);
var key3IsTrue = createEqualContextRule('key3', true);
var key4IsTrue = createEqualContextRule('key4', true);
assertIsIncluded([key1IsTrue], null);
assertIsIncluded([key1IsTrue], []);
assertIsIncluded([key1IsTrue], [key1IsTrue]);
assertIsIncluded([key1IsTrue], [key1IsNotFalse]);
assertIsIncluded([key1IsFalse], []);
assertIsIncluded([key1IsFalse], [key1IsFalse]);
assertIsIncluded([key1IsFalse], [key1IsNotTrue]);
assertIsIncluded([key2IsNotFalse], []);
assertIsIncluded([key2IsNotFalse], [key2IsNotFalse]);
assertIsIncluded([key2IsNotFalse], [key2IsTrue]);
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key2IsTrue]);
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key2IsNotFalse]);
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key1IsTrue]);
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key1IsNotFalse]);
assertIsIncluded([key1IsTrue, key2IsNotFalse], []);
assertIsNotIncluded([key1IsTrue], [key1IsFalse]);
assertIsNotIncluded([key1IsTrue], [key1IsNotTrue]);
assertIsNotIncluded([key1IsNotFalse], [key1IsFalse]);
assertIsNotIncluded([key1IsNotFalse], [key1IsNotTrue]);
assertIsNotIncluded([key1IsFalse], [key1IsTrue]);
assertIsNotIncluded([key1IsFalse], [key1IsNotFalse]);
assertIsNotIncluded([key1IsNotTrue], [key1IsTrue]);
assertIsNotIncluded([key1IsNotTrue], [key1IsNotFalse]);
assertIsNotIncluded([key1IsTrue, key2IsNotFalse], [key3IsTrue]);
assertIsNotIncluded([key1IsTrue, key2IsNotFalse], [key4IsTrue]);
assertIsNotIncluded([key1IsTrue], [key2IsTrue]);
assertIsNotIncluded([], [key2IsTrue]);
assertIsNotIncluded(null, [key2IsTrue]);
});
test('resolve command', function () {
var items: IKeybindingItem[] = [
// This one will never match because its context is always overwritten by another one
{
keybinding: KeyCode.KEY_X,
context: [{
key: 'key1',
operator: KeybindingsRegistry.KEYBINDING_CONTEXT_OPERATOR_EQUAL,
operand: true
}, {
key: 'key2',
operator: KeybindingsRegistry.KEYBINDING_CONTEXT_OPERATOR_NOT_EQUAL,
operand: false
}],
command: 'first',
weight1: 1,
weight2: 0
},
// This one always overwrites first
{
keybinding: KeyCode.KEY_X,
context: [{
key: 'key2',
operator: KeybindingsRegistry.KEYBINDING_CONTEXT_OPERATOR_EQUAL,
operand: true
}],
command: 'second',
weight1: 2,
weight2: 0
},
// This one is a secondary mapping for `second`
{
keybinding: KeyCode.KEY_Z,
context: [],
command: 'second',
weight1: 2.5,
weight2: 0
},
// This one sometimes overwrites first
{
keybinding: KeyCode.KEY_X,
context: [{
key: 'key3',
operator: KeybindingsRegistry.KEYBINDING_CONTEXT_OPERATOR_EQUAL,
operand: true
}],
command: 'third',
weight1: 3,
weight2: 0
},
// This one is always overwritten by another one
{
keybinding: KeyMod.CtrlCmd | KeyCode.KEY_Y,
context: [{
key: 'key4',
operator: KeybindingsRegistry.KEYBINDING_CONTEXT_OPERATOR_EQUAL,
operand: true
}],
command: 'fourth',
weight1: 4,
weight2: 0
},
// This one overwrites with a chord the previous one
{
keybinding: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z),
context: [],
command: 'fifth',
weight1: 5,
weight2: 0
},
// This one has no keybinding
{
keybinding: 0,
context: [],
command: 'sixth',
weight1: 6,
weight2: 0
},
{
keybinding: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U),
context: [],
command: 'seventh',
weight1: 6.5,
weight2: 0
},
{
keybinding: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K),
context: [],
command: 'seventh',
weight1: 6.5,
weight2: 0
},
{
keybinding: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U),
context: [],
command: 'uncomment lines',
weight1: 7,
weight2: 0
},
{
keybinding: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C),
context: [],
command: 'comment lines',
weight1: 8,
weight2: 0
},
{
keybinding: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_G, KeyMod.CtrlCmd | KeyCode.KEY_C),
context: [],
command: 'unreachablechord',
weight1: 10,
weight2: 0
},
{
keybinding: KeyMod.CtrlCmd | KeyCode.KEY_G,
context: [],
command: 'eleven',
weight1: 11,
weight2: 0
}
];
var resolver = new CommonKeybindingResolver(items, []);
var testKey = (commandId: string, expectedKeys: number[]) => {
// Test lookup
var lookupResult = resolver.lookupKeybinding(commandId);
assert.equal(lookupResult.length, expectedKeys.length, 'Length mismatch @ commandId ' + commandId + '; GOT: ' + JSON.stringify(lookupResult, null, '\t'));
for (let i = 0, len = lookupResult.length; i < len; i++) {
assert.equal(lookupResult[i].value, expectedKeys[i]);
}
};
var testResolve = (ctx:any, expectedKey:number, commandId:string) => {
if (BinaryKeybindings.hasChord(expectedKey)) {
let firstPart = BinaryKeybindings.extractFirstPart(expectedKey);
let chordPart = BinaryKeybindings.extractChordPart(expectedKey);
let result = resolver.resolve(ctx, 0, firstPart);
assert.ok(result !== null, 'Enters chord for ' + commandId);
assert.equal(result.commandId, null, 'Enters chord for ' + commandId);
assert.equal(result.enterChord, firstPart, 'Enters chord for ' + commandId);
result = resolver.resolve(ctx, firstPart, chordPart);
assert.ok(result !== null, 'Enters chord for ' + commandId);
assert.equal(result.commandId, commandId, 'Finds chorded command ' + commandId);
assert.equal(result.enterChord, 0, 'Finds chorded command ' + commandId);
} else {
let result = resolver.resolve(ctx, 0, expectedKey);
assert.ok(result !== null, 'Finds command ' + commandId);
assert.equal(result.commandId, commandId, 'Finds command ' + commandId);
assert.equal(result.enterChord, 0, 'Finds command ' + commandId);
}
}
testKey('first', []);
testKey('second', [KeyCode.KEY_Z, KeyCode.KEY_X]);
testResolve({key2: true}, KeyCode.KEY_X, 'second');
testResolve({}, KeyCode.KEY_Z, 'second');
testKey('third', [KeyCode.KEY_X]);
testResolve({key3:true}, KeyCode.KEY_X, 'third');
testKey('fourth', []);
testKey('fifth', [KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z)]);
testResolve({}, KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z), 'fifth');
testKey('seventh', [KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K)]);
testResolve({}, KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K), 'seventh');
testKey('uncomment lines', [KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U)]);
testResolve({}, KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U), 'uncomment lines');
testKey('comment lines', [KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C)]);
testResolve({}, KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C), 'comment lines');
testKey('unreachablechord', []);
testKey('eleven', [KeyMod.CtrlCmd | KeyCode.KEY_G]);
testResolve({}, KeyMod.CtrlCmd | KeyCode.KEY_G, 'eleven');
testKey('sixth', []);
});
});