mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-06 00:45:32 +00:00
198 lines
No EOL
7.8 KiB
JavaScript
198 lines
No EOL
7.8 KiB
JavaScript
import { assert } from 'chai';
|
||
import fs from 'fs';
|
||
|
||
import { createRequire } from 'module';
|
||
const require = createRequire(import.meta.url);
|
||
|
||
import { Codes, KeyboardInterface, KeyEvent, MinimalKeymanGlobal, Mock } from '@keymanapp/keyboard-processor';
|
||
import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader';
|
||
|
||
// Compare and contrast the unit tests here with those for app/browser key-event unit testing
|
||
// in the hardware-event-processing set; the output objects there should have the same format
|
||
// as the event object inputs used here.
|
||
|
||
describe('Engine - rule processing', function() {
|
||
const ipaPath = require.resolve('@keymanapp/common-test-resources/keyboards/sil_ipa.js');
|
||
const armenianPath = require.resolve('@keymanapp/common-test-resources/keyboards/armenian.js');
|
||
|
||
let device = {
|
||
formFactor: 'desktop',
|
||
OS: 'windows',
|
||
browser: 'native'
|
||
}
|
||
|
||
describe('for mnemonic keyboards (via `sil_ipa`)', function () {
|
||
let keyboardWithHarness;
|
||
|
||
before(async () => {
|
||
// -- START: Standard keyboard unit test loading boilerplate --
|
||
let harness = new KeyboardInterface({}, MinimalKeymanGlobal);
|
||
let keyboardLoader = new NodeKeyboardLoader(harness);
|
||
let keyboard = await keyboardLoader.loadKeyboardFromPath(ipaPath);
|
||
// -- END: Standard keyboard unit test loading boilerplate --
|
||
|
||
// This part provides extra assurance that the keyboard properly loaded.
|
||
assert.equal(keyboard.id, "Keyboard_sil_ipa");
|
||
|
||
harness.activeKeyboard = keyboard;
|
||
keyboardWithHarness = harness;
|
||
});
|
||
|
||
it('matches rules with mnemonic-specced KeyEvents', () => {
|
||
// Note: plain 'n' is produced from default key outputs for sil_ipa, not a keyboard rule.
|
||
let mockMnemonic = new Mock('n');
|
||
let mnemonicEvent = new KeyEvent({
|
||
// sil_ipa is a mnenomic keyboard: it expects codes based on the key's standard character output.
|
||
Lcode: '>'.charCodeAt(0), // 62
|
||
Lmodifiers: Codes.modifierCodes.SHIFT, // '>' is shift-layer.
|
||
Lstates: Codes.modifierCodes.NO_CAPS | Codes.modifierCodes.NO_NUM_LOCK | Codes.modifierCodes.NO_SCROLL_LOCK,
|
||
LisVirtualKey: true,
|
||
kName: '',
|
||
vkCode: Codes.keyCodes.K_N,
|
||
device: device
|
||
});
|
||
|
||
const mnemonicResult = keyboardWithHarness.processKeystroke(mockMnemonic, mnemonicEvent);
|
||
|
||
assert.isOk(mnemonicResult);
|
||
assert.isFalse(mnemonicResult.triggerKeyDefault);
|
||
assert.equal(mockMnemonic.getText(), 'ŋ');
|
||
});
|
||
|
||
it('requires correct modifiers', () => {
|
||
// Note: plain 'n' is produced from default key outputs for sil_ipa, not a keyboard rule.
|
||
let mockMnemonic = new Mock('n');
|
||
let mnemonicEvent = new KeyEvent({
|
||
// sil_ipa is a mnenomic keyboard: it expects codes based on the key's standard character output.
|
||
Lcode: '>'.charCodeAt(0), // 62
|
||
Lmodifiers: 0, // '>' is shift-layer, not default - and this matters for context matching.
|
||
Lstates: Codes.modifierCodes.NO_CAPS | Codes.modifierCodes.NO_NUM_LOCK | Codes.modifierCodes.NO_SCROLL_LOCK,
|
||
LisVirtualKey: true,
|
||
kName: '',
|
||
vkCode: Codes.keyCodes.K_N,
|
||
device: device
|
||
});
|
||
|
||
const mnemonicResult = keyboardWithHarness.processKeystroke(mockMnemonic, mnemonicEvent);
|
||
|
||
assert.isOk(mnemonicResult);
|
||
assert.isTrue(mnemonicResult.triggerKeyDefault);
|
||
});
|
||
|
||
it('does not match rules with positional-specced KeyEvents', () => {
|
||
let mockPositional = new Mock('n');
|
||
let positionalEvent = new KeyEvent({
|
||
// If it were positional, we'd use this instead:
|
||
Lcode: Codes.keyCodes.K_COMMA, // 188
|
||
Lmodifiers: Codes.modifierCodes.SHIFT, // '>' is shift-layer.
|
||
Lstates: Codes.modifierCodes.NO_CAPS | Codes.modifierCodes.NO_NUM_LOCK | Codes.modifierCodes.NO_SCROLL_LOCK,
|
||
LisVirtualKey: true,
|
||
kName: '',
|
||
vkCode: Codes.keyCodes.K_N,
|
||
device: device
|
||
});
|
||
|
||
const positionalResult = keyboardWithHarness.processKeystroke(mockPositional, positionalEvent);
|
||
|
||
assert.isOk(positionalResult);
|
||
assert.isTrue(positionalResult.triggerKeyDefault);
|
||
assert.notEqual(mockPositional.getText(), 'ŋ');
|
||
});
|
||
});
|
||
|
||
describe('for KMW 1.0 legacy keyboards (via `armenian`)', function () {
|
||
let keyboardWithHarness;
|
||
|
||
before(async () => {
|
||
// -- START: Standard keyboard unit test loading boilerplate --
|
||
let harness = new KeyboardInterface({}, MinimalKeymanGlobal);
|
||
let keyboardLoader = new NodeKeyboardLoader(harness);
|
||
let keyboard = await keyboardLoader.loadKeyboardFromPath(armenianPath);
|
||
// -- END: Standard keyboard unit test loading boilerplate --
|
||
|
||
// This part provides extra assurance that the keyboard properly loaded.
|
||
assert.equal(keyboard.id, "Keyboard_armenian");
|
||
|
||
harness.activeKeyboard = keyboard;
|
||
keyboardWithHarness = harness;
|
||
});
|
||
|
||
it('matches rules with legacy-specced KeyEvents', () => {
|
||
let mockLegacy = new Mock('');
|
||
let legacyEvent = new KeyEvent({
|
||
// armenian is a KMW 1.0 keyboard: it expects codes based on the key's standard character output.
|
||
Lcode: 'a'.charCodeAt(0),
|
||
Lmodifiers: 0,
|
||
Lstates: Codes.modifierCodes.NO_CAPS | Codes.modifierCodes.NO_NUM_LOCK | Codes.modifierCodes.NO_SCROLL_LOCK,
|
||
LisVirtualKey: false,
|
||
kName: '',
|
||
vkCode: Codes.keyCodes.K_N,
|
||
device: device
|
||
});
|
||
|
||
const legacyResult = keyboardWithHarness.processKeystroke(mockLegacy, legacyEvent);
|
||
|
||
assert.isOk(legacyResult);
|
||
assert.isFalse(legacyResult.triggerKeyDefault);
|
||
assert.equal(mockLegacy.getText(), 'ա');
|
||
});
|
||
|
||
it('ignores current modifiers and states', () => {
|
||
let mockLegacy = new Mock('');
|
||
let legacyEvent = new KeyEvent({
|
||
// armenian is a KMW 1.0 keyboard: it expects codes based on the key's standard character output.
|
||
Lcode: 'a'.charCodeAt(0),
|
||
Lmodifiers: 27,
|
||
Lstates: Codes.modifierCodes.CAPS | Codes.modifierCodes.NO_NUM_LOCK | Codes.modifierCodes.SCROLL_LOCK | 0x5C00,
|
||
LisVirtualKey: false,
|
||
kName: '',
|
||
vkCode: Codes.keyCodes.K_N,
|
||
device: device
|
||
});
|
||
|
||
const legacyResult = keyboardWithHarness.processKeystroke(mockLegacy, legacyEvent);
|
||
|
||
assert.isOk(legacyResult);
|
||
assert.isFalse(legacyResult.triggerKeyDefault);
|
||
assert.equal(mockLegacy.getText(), 'ա');
|
||
});
|
||
|
||
it('does not match rules with mnemonic-specced KeyEvents', () => {
|
||
let mockMnemonic = new Mock('');
|
||
let mnemonicEvent = new KeyEvent({
|
||
// armenian is a KMW 1.0 keyboard: it expects codes based on the key's standard character output.
|
||
Lcode: 'a'.charCodeAt(0),
|
||
Lmodifiers: 0,
|
||
Lstates: Codes.modifierCodes.NO_CAPS | Codes.modifierCodes.NO_NUM_LOCK | Codes.modifierCodes.NO_SCROLL_LOCK,
|
||
LisVirtualKey: true,
|
||
kName: '',
|
||
vkCode: Codes.keyCodes.K_N,
|
||
device: device
|
||
});
|
||
|
||
const mnemonicResult = keyboardWithHarness.processKeystroke(mockMnemonic, mnemonicEvent);
|
||
|
||
assert.isOk(mnemonicResult);
|
||
assert.isTrue(mnemonicResult.triggerKeyDefault);
|
||
});
|
||
|
||
it('does not match rules with positional-specced KeyEvents', () => {
|
||
let mockPositional = new Mock('');
|
||
let positionalEvent = new KeyEvent({
|
||
// If it were positional, we'd use this instead:
|
||
Lcode: Codes.keyCodes.K_A,
|
||
Lmodifiers: 0,
|
||
Lstates: Codes.modifierCodes.NO_CAPS | Codes.modifierCodes.NO_NUM_LOCK | Codes.modifierCodes.NO_SCROLL_LOCK,
|
||
LisVirtualKey: true,
|
||
kName: '',
|
||
vkCode: Codes.keyCodes.K_N,
|
||
device: device
|
||
});
|
||
|
||
const positionalResult = keyboardWithHarness.processKeystroke(mockPositional, positionalEvent);
|
||
|
||
assert.isOk(positionalResult);
|
||
assert.isTrue(positionalResult.triggerKeyDefault);
|
||
});
|
||
});
|
||
}); |