change(common/web): converts common/web/recorder to ES modules

This commit is contained in:
Joshua A. Horton 2022-11-24 12:32:39 +07:00
parent 8a02ddc0f1
commit 6bc8ab579b
7 changed files with 914 additions and 929 deletions

View file

@ -22,16 +22,11 @@ builder_describe \
"@../keyman-version" \
configure \
clean \
build \
":module Builds recorder-core module" \
":proctor Builds headless-testing, node-oriented 'proctor' component"
build
builder_describe_outputs \
configure "/node_modules" \
configure:module "/node_modules" \
configure:proctor "/node_modules" \
build:module "build/index.js" \
build:proctor "build/nodeProctor/index.js"
configure "/node_modules" \
build "build/index.js"
builder_parse "$@"
@ -40,22 +35,12 @@ if builder_start_action configure; then
builder_finish_action success configure
fi
if builder_start_action clean:module; then
npm run tsc -- -b --clean "$THIS_SCRIPT_PATH/src/tsconfig.json"
builder_finish_action success clean:module
if builder_start_action clean; then
npm run tsc -- -b --clean "$THIS_SCRIPT_PATH/tsconfig.json"
builder_finish_action success clean
fi
if builder_start_action clean:proctor; then
npm run tsc -- -b --clean "$THIS_SCRIPT_PATH/src/nodeProctor.tsconfig.json"
builder_finish_action success clean:proctor
fi
if builder_start_action build:module; then
npm run tsc -- --build "$THIS_SCRIPT_PATH/src/tsconfig.json"
builder_finish_action success build:module
fi
if builder_start_action build:proctor; then
npm run tsc -- --build "$THIS_SCRIPT_PATH/src/nodeProctor.tsconfig.json"
builder_finish_action success build:proctor
if builder_start_action build; then
npm run tsc -- --build "$THIS_SCRIPT_PATH/tsconfig.json"
builder_finish_action success build
fi

File diff suppressed because it is too large Load diff

View file

@ -1,94 +1,105 @@
import Proctor, { AssertCallback } from "./proctor.js";
import {
KeyboardTest,
TestSet,
TestSequence,
RecordedKeystrokeSequence,
RecordedPhysicalKeystroke,
RecordedSyntheticKeystroke
} from "./index.js";
namespace KMWRecorder {
export class NodeProctor extends Proctor {
private keyboard: com.keyman.keyboards.Keyboard;
public __debug = false;
import Keyboard from "keyboard-processor/build/modules/keyboards/keyboard.js";
import type KeyEvent from "keyboard-processor/build/modules/text/keyEvent.js";
import KeyboardProcessor from "keyboard-processor/build/modules/text/keyboardProcessor.js";
import type OutputTarget from "keyboard-processor/build/modules/text/outputTarget.js";
import { Mock } from "keyboard-processor/build/modules/text/outputTarget.js";
constructor(keyboard: com.keyman.keyboards.Keyboard, device: com.keyman.utils.DeviceSpec, assert: AssertCallback) {
super(device, assert);
import DeviceSpec from "utils/build/modules/deviceSpec.js";
this.keyboard = keyboard;
}
export default class NodeProctor extends Proctor {
private keyboard: Keyboard;
public __debug = false;
beforeAll() {
//
}
before() {
//
}
compatibleWithSuite(testSuite: KeyboardTest): boolean {
// Original-version tests did not supply core-compatible KeyEvent data.
return !testSuite.specVersion.equals(KeyboardTest.FALLBACK_VERSION);
}
get debugMode(): boolean {
return this.__debug;
}
set debugMode(value: boolean) {
this.__debug = value;
}
matchesTestSet(testSet: TestSet<any>) {
// KeyboardProcessor is abstract enough to run tests aimed at any platform.
return true;
}
simulateSequence(sequence: TestSequence<any>, target?: com.keyman.text.OutputTarget): string {
// Start with an empty OutputTarget and a fresh KeyboardProcessor.
if(!target) {
target = new com.keyman.text.Mock();
}
// Establish a fresh processor, setting its keyboard appropriately for the test.
let processor = new com.keyman.text.KeyboardProcessor(this.device);
processor.activeKeyboard = this.keyboard;
if(sequence instanceof RecordedKeystrokeSequence) {
for(let keystroke of sequence.inputs) {
let keyEvent: com.keyman.text.KeyEvent;
if(keystroke instanceof RecordedPhysicalKeystroke) {
// Use the keystroke's stored data to reconstruct the KeyEvent.
keyEvent = {
Lcode: keystroke.keyCode,
Lmodifiers: keystroke.modifiers,
LmodifierChange: keystroke.modifierChanged,
vkCode: keystroke.vkCode,
Lstates: keystroke.states,
kName: '',
device: this.device,
isSynthetic: false,
LisVirtualKey: this.keyboard.definesPositionalOrMnemonic // Only false for 1.0 keyboards.
}
} else if(keystroke instanceof RecordedSyntheticKeystroke) {
let key = this.keyboard.layout(this.device.formFactor).getLayer(keystroke.layer).getKey(keystroke.keyName);
keyEvent = key.constructKeyEvent(processor, this.device);
}
// Fill in the final details of the KeyEvent...
keyEvent.device = this.device;
// And now, execute the keystroke!
// We don't care too much about particularities of per-keystroke behavior yet.
// ... we _could_ if we wanted to, though. The framework is mostly in place;
// it's a matter of actually adding the feature.
let ruleBehavior = processor.processKeystroke(keyEvent, target);
if(this.debugMode) {
console.log(JSON.stringify(target, null, ' '));
console.log(JSON.stringify(ruleBehavior, null, ' '));
}
}
} else {
throw new Error("NodeProctor only supports RecordedKeystrokeSequences for testing at present.");
}
return target.getText();
}
constructor(keyboard: Keyboard, device: DeviceSpec, assert: AssertCallback) {
super(device, assert);
this.keyboard = keyboard;
}
}
// Export the namespace itself, giving access to all contained classes.
module.exports = KMWRecorder;
beforeAll() {
//
}
before() {
//
}
compatibleWithSuite(testSuite: KeyboardTest): boolean {
// Original-version tests did not supply core-compatible KeyEvent data.
return !testSuite.specVersion.equals(KeyboardTest.FALLBACK_VERSION);
}
get debugMode(): boolean {
return this.__debug;
}
set debugMode(value: boolean) {
this.__debug = value;
}
matchesTestSet(testSet: TestSet<any>) {
// KeyboardProcessor is abstract enough to run tests aimed at any platform.
return true;
}
simulateSequence(sequence: TestSequence<any>, target?: OutputTarget): string {
// Start with an empty OutputTarget and a fresh KeyboardProcessor.
if(!target) {
target = new Mock();
}
// Establish a fresh processor, setting its keyboard appropriately for the test.
let processor = new KeyboardProcessor(this.device);
processor.activeKeyboard = this.keyboard;
if(sequence instanceof RecordedKeystrokeSequence) {
for(let keystroke of sequence.inputs) {
let keyEvent: KeyEvent;
if(keystroke instanceof RecordedPhysicalKeystroke) {
// Use the keystroke's stored data to reconstruct the KeyEvent.
keyEvent = {
Lcode: keystroke.keyCode,
Lmodifiers: keystroke.modifiers,
LmodifierChange: keystroke.modifierChanged,
vkCode: keystroke.vkCode,
Lstates: keystroke.states,
kName: '',
device: this.device,
isSynthetic: false,
LisVirtualKey: this.keyboard.definesPositionalOrMnemonic // Only false for 1.0 keyboards.
}
} else if(keystroke instanceof RecordedSyntheticKeystroke) {
let key = this.keyboard.layout(this.device.formFactor).getLayer(keystroke.layer).getKey(keystroke.keyName);
keyEvent = key.constructKeyEvent(processor, this.device);
}
// Fill in the final details of the KeyEvent...
keyEvent.device = this.device;
// And now, execute the keystroke!
// We don't care too much about particularities of per-keystroke behavior yet.
// ... we _could_ if we wanted to, though. The framework is mostly in place;
// it's a matter of actually adding the feature.
let ruleBehavior = processor.processKeystroke(keyEvent, target);
if(this.debugMode) {
console.log(JSON.stringify(target, null, ' '));
console.log(JSON.stringify(ruleBehavior, null, ' '));
}
}
} else {
throw new Error("NodeProctor only supports RecordedKeystrokeSequences for testing at present.");
}
return target.getText();
}
}

View file

@ -1,28 +0,0 @@
{
"extends": "../../../../tsconfig-base.json",
"compilerOptions": {
"allowJs": true,
"module": "none",
"outDir": "../build/nodeProctor/",
"outFile": "../build/nodeProctor/index.js",
"inlineSources": true,
"inlineSourceMap": true,
"target": "es5",
"types": ["node"],
"lib": ["es6"]
},
"files": [
"index.ts",
"proctor.ts",
"nodeProctor.ts"
],
"references": [
{ "path": "../../keyman-version" },
{ "path": "../../utils" },
{ "path": "../../keyboard-processor/src" },
{ "path": "../../lm-message-types" }
]
}

View file

@ -1,50 +1,53 @@
namespace KMWRecorder {
export type AssertCallback = (s1: any, s2: any, msg?: string) => void;
import { type DeviceSpec } from "utils/build/modules/index.js";
import type OutputTarget from "keyboard-processor/build/modules/text/outputTarget.js";
import type { KeyboardTest, TestSet, TestSequence } from "./index.js";
export type AssertCallback = (s1: any, s2: any, msg?: string) => void;
/**
* Facilitates running Recorder-generated tests on various platforms.
*
* Note that DOM-aware KeymanWeb will implement a Browser-based version, while
* keyboard-processor and input-processor will use a Node-based version instead.
*/
export default abstract class Proctor {
device: DeviceSpec;
_assert: AssertCallback;
constructor(device: DeviceSpec, assert: AssertCallback) {
this.device = device;
this._assert = assert;
}
assertEquals(s1: unknown, s2: unknown, msg?: string) {
if(this._assert) {
this._assert(s1, s2, msg);
}
}
// Performs global test prep.
abstract beforeAll();
// Performs per-test setup
abstract before();
/**
* Facilitates running Recorder-generated tests on various platforms.
*
* Note that DOM-aware KeymanWeb will implement a Browser-based version, while
* keyboard-processor and input-processor will use a Node-based version instead.
* Allows the proctor to indicate if is capable of executing a suite of tests or not.
* @param testSuite
*/
export abstract class Proctor {
device: com.keyman.utils.DeviceSpec;
abstract compatibleWithSuite(testSuite: KeyboardTest): boolean;
_assert: AssertCallback;
/**
* Indicates whether or not this Proctor is capable of running the specified set of tests.
*/
abstract matchesTestSet(testSet: TestSet<any>);
constructor(device: com.keyman.utils.DeviceSpec, assert: AssertCallback) {
this.device = device;
this._assert = assert;
}
assertEquals(s1: unknown, s2: unknown, msg?: string) {
if(this._assert) {
this._assert(s1, s2, msg);
}
}
// Performs global test prep.
abstract beforeAll();
// Performs per-test setup
abstract before();
/**
* Allows the proctor to indicate if is capable of executing a suite of tests or not.
* @param testSuite
*/
abstract compatibleWithSuite(testSuite: KeyboardTest): boolean;
/**
* Indicates whether or not this Proctor is capable of running the specified set of tests.
*/
abstract matchesTestSet(testSet: TestSet<any>);
/**
* Simulates the specified test sequence for use in testing.
* @param sequence The recorded sequence, generally provided by a test set.
*/
abstract simulateSequence(sequence: TestSequence<any>, target?: com.keyman.text.OutputTarget);
}
/**
* Simulates the specified test sequence for use in testing.
* @param sequence The recorded sequence, generally provided by a test set.
*/
abstract simulateSequence(sequence: TestSequence<any>, target?: OutputTarget);
}

View file

@ -1,27 +0,0 @@
{
"extends": "../../../../tsconfig-base.json",
"compilerOptions": {
"allowJs": true,
"module": "none",
"outDir": "../build/",
"inlineSources": true,
"inlineSourceMap": true,
"target": "es5",
"types": ["node"],
"lib": ["es6"],
"outFile": "../build/index.js"
},
"files": [
"index.ts",
"proctor.ts"
],
"references": [
{ "path": "../../keyman-version" },
{ "path": "../../utils" },
{ "path": "../../keyboard-processor/src" },
{ "path": "../../lm-message-types" }
]
}

View file

@ -0,0 +1,35 @@
{
"extends": "../../../tsconfig-base.json",
"compilerOptions": {
"allowJs": true,
"module": "es6",
"declaration": true,
"inlineSources": true,
"inlineSourceMap": true,
"target": "es5",
"types": ["node"],
"lib": ["es6"],
"baseUrl": "./",
"outDir": "build/modules/",
"tsBuildInfoFile": "build/modules/tsconfig.tsbuildinfo",
"rootDir": "./src"
},
"include": [
"src/**/*.ts"
],
"references": [
{ "path": "../keyman-version" },
{ "path": "../utils/" },
{ "path": "../keyboard-processor/" },
{ "path": "../lm-message-types" }
],
"paths": {
"keyboard-processor": ["../keyboard-processor/build" ],
"keyman-version": ["../keyman-version/build" ],
"utils": ["../utils/build" ]
}
}