-
-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10475 from keymanapp/feat/web/key-event-rule-proc…
…essing-tests feat(web): key-event rule processing unit tests for mnemonic, KMW 1.0 keyboards 🧓
- Loading branch information
Showing
10 changed files
with
243 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"id": "armenian", | ||
"name":"Armenian Unicode", | ||
"languages":{ | ||
"id":"hy", | ||
"name": "Armenian", | ||
"region": "Asia" | ||
}, | ||
"filename":"resources/keyboards/armenian.js" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"id": "sil_ipa", | ||
"name":"IPA (SIL)", | ||
"languages":{ | ||
"id":"und-fonipa", | ||
"name": "Undetermined", | ||
"region": "World" | ||
}, | ||
"filename":"resources/keyboards/sil_ipa.js" | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
From the legacy section of the keyboards repo - is a KMW 1.0 keyboard, thus is neither positional nor mnemonic. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
From the keyboards repo, release section - version 1.8.6, before any KMW 17.0 gestures were added. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
198 changes: 198 additions & 0 deletions
198
common/web/keyboard-processor/tests/node/non-positional-rules.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
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); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters