From 0fc7416b682c408d14bbbb9499c59daa59eb615d Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 4 Nov 2025 14:30:46 +0100 Subject: [PATCH] =?UTF-8?q?refactor(web):=20rename=20`Mock`=20=E2=86=92=20?= =?UTF-8?q?`SyntheticTextStore`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/docs/internal/context-state-management.md | 16 ++-- web/docs/internal/keystroke-lifecycle.md | 2 +- web/docs/internal/keystroke-processing.md | 6 +- web/src/app/webview/src/contextManager.ts | 22 +++--- .../js-processor/src/jsKeyboardInterface.ts | 4 +- .../js-processor/src/jsKeyboardProcessor.ts | 6 +- web/src/engine/keyboard/src/defaultRules.ts | 2 +- web/src/engine/keyboard/src/index.ts | 2 +- .../src/{mock.ts => syntheticTextStore.ts} | 26 +++---- web/src/engine/keyboard/src/textStore.ts | 10 +-- .../engine/main/src/headless/contextWindow.ts | 8 +- .../main/src/headless/inputProcessor.ts | 12 +-- .../main/src/headless/languageProcessor.ts | 16 ++-- .../element_interfaces.tests.ts | 22 +++--- .../element-wrappers/target_mocks.tests.ts | 14 ++-- .../cases/keyboard/domKeyboardLoader.tests.ts | 4 +- .../prediction/predictionContext.tests.js | 28 +++---- .../js-processor/bundled-module.tests.js | 6 +- .../js-processor/engine/context.tests.js | 6 +- .../engine/notany_context.tests.js | 4 +- .../engine/js-processor/kbdInterface.tests.ts | 4 +- .../non-positional-rules.tests.js | 16 ++-- .../specialized-backspace.tests.js | 16 ++-- .../js-processor/transcriptions.tests.js | 74 +++++++++---------- .../engine/keyboard/keyboard-loading.tests.js | 4 +- .../keyboard/keyboardLoaderBase.tests.ts | 4 +- .../headless/engine/keyboard/mocks.tests.js | 22 +++--- .../main/headless/inputProcessor.tests.js | 12 +-- .../main/headless/languageProcessor.tests.js | 18 ++--- .../tools/testing/recorder-core/src/index.ts | 4 +- .../testing/recorder-core/src/nodeProctor.ts | 4 +- 31 files changed, 198 insertions(+), 196 deletions(-) rename web/src/engine/keyboard/src/{mock.ts => syntheticTextStore.ts} (82%) diff --git a/web/docs/internal/context-state-management.md b/web/docs/internal/context-state-management.md index 4d776defbf..9c25186f7b 100644 --- a/web/docs/internal/context-state-management.md +++ b/web/docs/internal/context-state-management.md @@ -71,29 +71,31 @@ It is possible to determine the `Transform` needed to transition from one `TextStore` to another using `TextStore.buildTransformFrom` (defined on `TextStore`). -### The `Mock` - representing context-state +### The `SyntheticTextStore` - representing context-state The comparison and contrast methods mentioned above for `TextStore` are of particular use for predictive text, which usually operates with a -headless implementation of the type, termed a `Mock`. This class may be +headless implementation of the type, termed a `SyntheticTextStore`. This class may be found in -[web/src/engine/js-processor/src/mock.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/mock.ts). +[web/src/engine/keyboard/src/syntheticTextStore.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/syntheticTextStore.ts). It is a fully-featured implementation of the `TextStore` interface. -It is possible to make a `Mock`-based clone of any +It is possible to make a `SyntheticTextStore`-based clone of any `TextStore`-derived type - a feature leveraged significantly within the inner workings of Keyman Engine for Web. As JS keyboards can have side effects beyond text-manipulation, predictive text generally -operates by first _cloning_ the "true" context source. `Mock`s are +operates by first _cloning_ the "true" context source. `SyntheticTextStore`s are also used when saving context states within the engine for later reference and/or reuse - a feature also utilized significantly for multitap support. -`Mock`s can also easily be constructed from scratch for a simple string. +`SyntheticTextStore`s can also easily be constructed from scratch for a simple string. Optionally, caret position or selection data may be specified at construction time as well. `epic/web-core`: in theory, this should make them easy to utilize for integration with Keyman Core. +- note: previously called `Mock` + ### The `Transcription` - representing context-state transitions The `Transcription` class (defined in @@ -144,7 +146,7 @@ multitap-generated keystrokes. ### JS-keyboard keystroke processing -For JS-keyboard keystroke processing, a `Mock` clone of the context is +For JS-keyboard keystroke processing, a `SyntheticTextStore` clone of the context is generated before any actual keyboard rule checks are applied. This provides a clear "before" state (eventually saved at `Transcription.preInput`) useful for determining the scope of the diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md index 9940ac6d8e..68dfc14d02 100644 --- a/web/docs/internal/keystroke-lifecycle.md +++ b/web/docs/internal/keystroke-lifecycle.md @@ -126,7 +126,7 @@ The bulk of DOM key events trigger keystroke processing on key-down, though modi The `app/webview` version of the engine, which is designed to be used while embedded in a platform-specific host app, does not have direct access to standard hardware keystroke events, as those are handled by the host app's OS and by native code handlers run outside the host app's WebView containing the app/webview Web engine. It is the responsibility of the host app to handle hardware keystroke events and preprocess them on behalf of the Web engine, then forward them to the Web engine via JS call into the WebView. The `PassthroughKeyboard` class within `app/webview` space provides the method `raiseKeyEvent` as an internal API for this purpose, which converts the mobile-app format for hardware keystroke into the internal `KeyEvent` format. `raiseKeyEvent` also handles mnemonic keystroke processing and remapping. -Also note that this variant does not model the user's text context with Web elements - it is entirely managed through the `Mock` type. +Also note that this variant does not model the user's text context with Web elements - it is entirely managed through the `SyntheticTextStore` type. ### On-screen keyboard diff --git a/web/docs/internal/keystroke-processing.md b/web/docs/internal/keystroke-processing.md index 0945615c09..60c2c44f7e 100644 --- a/web/docs/internal/keystroke-processing.md +++ b/web/docs/internal/keystroke-processing.md @@ -6,7 +6,7 @@ In addition to handling keystroke events produced from hardware keyboards, Keyma Defined at [web/src/engine/keyboard/src/keyEvent.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/keyEvent.ts), the `KeyEvent` is used to represent incoming _and_ potential keystrokes. This type is what the JS-keyboard processor references when evaluating keyboard rules during its keystroke processing. For versions of the engine that support AltGr aliasing, such aliasing will be applied during generation of `KeyEvent` objects. -Note that for predictive-text's fat-finger correction functionality, the engine will also generate versions of this type for nearby but _unpressed_ keys into the keystroke processing engine as well in order to facilitate predictions that follow context manipulations that could have resulted from specialized rules or reorders on neighboring keys. `Mock`-cloned copies of the active context-state will be leveraged to prevent unwanted manipulation of the true context source. +Note that for predictive-text's fat-finger correction functionality, the engine will also generate versions of this type for nearby but _unpressed_ keys into the keystroke processing engine as well in order to facilitate predictions that follow context manipulations that could have resulted from specialized rules or reorders on neighboring keys. `SyntheticTextStore`-cloned copies of the active context-state will be leveraged to prevent unwanted manipulation of the true context source. ### `isSynthetic` `isSynthetic` should be set to `true` if generated through interaction with an on-screen-keyboard or for fat-finger simulation. It should only be set to `false` if sending the basic key-event data through to the destination, without rule processing, leads to default handling picking up the slack. Browsers provide default handling of keystrokes not directly defined within keyboards, but this is not available for keystrokes against the engine's OSK without internal support. @@ -31,7 +31,7 @@ See also: [context-state-management.md](context-state-management.md#js-keyboard The "first stop" for incoming keystrokes is the `InputProcessor`, found at [web/src/engine/main/src/headless/inputProcessor.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/main/src/headless/.inputProcessor.ts), through its `processKeyEvent` method. This class manages higher-level functionality triggered by keystroke events while deferring actual interpretation of the incoming keystroke further down the line. Of particular note is that it also handles control-flows that require restoration of previously-occuring contexts. -This class is the connection point for generating prediction requests and receiving corresponding suggestions. In order to facilitate higher-quality predictive-text when enabled, the `InputProcessor` will _also_ generate and trigger processing for nearby keys. This process allows transforms, reorders, and KMN keyboard rules to take effect and be used as alternative context roots for predictions. These are generally run against `Mock`-based clones of the true context source and are additionally prevented from triggering long-term side-effects, such as changes to KMN-keyboard variable stores, by only calling `KeyboardProcessor.finalizeProcessorAction` for the true input keystroke's result object. +This class is the connection point for generating prediction requests and receiving corresponding suggestions. In order to facilitate higher-quality predictive-text when enabled, the `InputProcessor` will _also_ generate and trigger processing for nearby keys. This process allows transforms, reorders, and KMN keyboard rules to take effect and be used as alternative context roots for predictions. These are generally run against `SyntheticTextStore`-based clones of the true context source and are additionally prevented from triggering long-term side-effects, such as changes to KMN-keyboard variable stores, by only calling `KeyboardProcessor.finalizeProcessorAction` for the true input keystroke's result object. Keys generated by OSK multitap need special handling here as well; they should always be applied to the context state as it existed at the time of the initial tap. To facilitate this, the `InputProcessor` will directly rewind the active context-source to match the corresponding context state before requesting that the `KeyEvent` be processed. @@ -64,7 +64,7 @@ The method linked above is the primary entrypoint for rule processing of individ #### JS-keyboard interfacing -Certain Keyman language features can make permanent side-effect changes to state. In order to prevent these from taking place for every keystroke, the method that interfaces with JS keyboards - `JSKeyboardInterface.process` - saves the context state (as a `Mock`) and current variable store values, then prepares a fresh `ProcessorAction` instance, before passing control off to the keyboard's backing script. (Note that `JSKeyboardInterface` itself primarily consists of keyboard-script API called by JS-keyboard script.) +Certain Keyman language features can make permanent side-effect changes to state. In order to prevent these from taking place for every keystroke, the method that interfaces with JS keyboards - `JSKeyboardInterface.process` - saves the context state (as a `SyntheticTextStore`) and current variable store values, then prepares a fresh `ProcessorAction` instance, before passing control off to the keyboard's backing script. (Note that `JSKeyboardInterface` itself primarily consists of keyboard-script API called by JS-keyboard script.) A few of the keyboard-script API methods will mark `ProcessorAction` properties directly when called, but the bulk of its data will be set once the keyboard-script returns control to Keyman Engine for Web. At this time, variable store values will also be reverted to prevent possible cross-contamination effects when predictive text is active - they're reapplied later if `KeyboardProcessor.finalizeProcessorAction` is leveraged on the resulting instance. Components documented in [context-state-management.md](./context-state-management.md) are then leveraged to determine the total change to context caused by the keystroke. diff --git a/web/src/app/webview/src/contextManager.ts b/web/src/app/webview/src/contextManager.ts index 63d28cf850..68111bff6f 100644 --- a/web/src/app/webview/src/contextManager.ts +++ b/web/src/app/webview/src/contextManager.ts @@ -1,4 +1,4 @@ -import { JSKeyboard, Keyboard, TextStore, Transcription, TextTransform, Mock, findCommonSubstringEndIndex } from 'keyman/engine/keyboard'; +import { JSKeyboard, Keyboard, TextStore, Transcription, TextTransform, SyntheticTextStore, findCommonSubstringEndIndex } from 'keyman/engine/keyboard'; import { KeyboardStub } from 'keyman/engine/keyboard-storage'; import { ContextManagerBase } from 'keyman/engine/main'; import { WebviewConfiguration } from './configuration.js'; @@ -7,9 +7,9 @@ import { KMWString, isEmptyTransform } from '@keymanapp/web-utils'; export type OnInsertTextFunc = (deleteLeft: number, text: string, deleteRight: number) => void; -export class ContextHost extends Mock { +export class ContextHost extends SyntheticTextStore { readonly oninserttext?: OnInsertTextFunc; - private savedState: Mock; + private savedState: SyntheticTextStore; constructor(oninserttext: OnInsertTextFunc) { super(); @@ -30,7 +30,7 @@ export class ContextHost extends Mock { if(transcription) { //TODO-web-core: shouldn't need cast in the future? - const preInput = transcription.preInput as Mock; + const preInput = transcription.preInput as SyntheticTextStore; // If our saved state matches the `preInput` from the incoming transcription, just reuse its transform. // Will generally not match during multitap operations, though. // @@ -55,18 +55,18 @@ export class ContextHost extends Mock { } saveState() { - this.savedState = Mock.from(this); + this.savedState = SyntheticTextStore.from(this); } restoreTo(original: TextStore): void { - this.savedState = Mock.from(this); + this.savedState = SyntheticTextStore.from(this); // TODO-web-core super.restoreTo(original as TextStore); } updateContext(text: string, selStart: number, selEnd: number): boolean { let shouldResetContext = false; - const tempMock = new Mock(text, selStart ?? KMWString.length(text), selEnd ?? KMWString.length(text)); + const tempMock = new SyntheticTextStore(text, selStart ?? KMWString.length(text), selEnd ?? KMWString.length(text)); const newLeft = tempMock.getTextBeforeCaret(); const oldLeft = this.getTextBeforeCaret(); @@ -108,12 +108,12 @@ export class ContextHost extends Mock { // and we want a consistent interface for context synchronization between // host app + app/webview KMW. this.setSelection(KMWString.length(this.text)); - this.savedState = Mock.from(this); + this.savedState = SyntheticTextStore.from(this); } } export default class ContextManager extends ContextManagerBase { - // Change of context? Just replace the Mock. Context will be ENTIRELY controlled + // Change of context? Just replace the SyntheticTextStore. Context will be ENTIRELY controlled // by whatever is hosting the WebView. (Some aspects of this context replacement have // yet to be modularized at this time, though.) private _rawContext: ContextHost; @@ -130,7 +130,7 @@ export default class ContextManager extends ContextManagerBase { * @return {string} */ private defaultRuleBehavior(Lkc: KeyEvent, textStore: TextStore, readonly: boolean): ProcessorAction { - const preInput = Mock.from(textStore, readonly); + const preInput = SyntheticTextStore.from(textStore, readonly); const ruleBehavior = new ProcessorAction(); let matched = false; @@ -672,7 +672,7 @@ export class JSKeyboardProcessor extends EventEmitter { first.triggersDefaultCommand = first.triggersDefaultCommand || other.triggersDefaultCommand; - const mergingMock = Mock.from(first.transcription.preInput, false); + const mergingMock = SyntheticTextStore.from(first.transcription.preInput, false); mergingMock.apply(first.transcription.transform); mergingMock.apply(other.transcription.transform); diff --git a/web/src/engine/keyboard/src/defaultRules.ts b/web/src/engine/keyboard/src/defaultRules.ts index d39cdbe34f..06c88507be 100644 --- a/web/src/engine/keyboard/src/defaultRules.ts +++ b/web/src/engine/keyboard/src/defaultRules.ts @@ -112,7 +112,7 @@ export default class DefaultRules { /** * Codes matched here generally have default implementations when in a browser but require emulation - * for 'synthetic' `TextStore`s like `Mock`s, which have no default text handling. + * for 'synthetic' `TextStore`s like `SyntheticTextStore`s, which have no default text handling. */ public forSpecialEmulation(Lkc: KeyEvent): EmulationKeystrokes { let code = this.codeForEvent(Lkc); diff --git a/web/src/engine/keyboard/src/index.ts b/web/src/engine/keyboard/src/index.ts index dad2d5f4c5..7bda82d4fd 100644 --- a/web/src/engine/keyboard/src/index.ts +++ b/web/src/engine/keyboard/src/index.ts @@ -32,7 +32,7 @@ export { default as KeyMapping } from "./keyMapping.js"; export { type SystemStoreMutationHandler, MutableSystemStore, SystemStore, SystemStoreIDs, type SystemStoreDictionary } from "./systemStore.js"; export { type VariableStore, VariableStoreSerializer, VariableStoreDictionary } from "./variableStore.js"; -export { Mock } from "./mock.js"; +export { SyntheticTextStore } from "./syntheticTextStore.js"; export { TextStore } from "./textStore.js"; export { findCommonSubstringEndIndex } from "./stringDivergence.js"; export { Deadkey } from "./deadkeys.js"; diff --git a/web/src/engine/keyboard/src/mock.ts b/web/src/engine/keyboard/src/syntheticTextStore.ts similarity index 82% rename from web/src/engine/keyboard/src/mock.ts rename to web/src/engine/keyboard/src/syntheticTextStore.ts index b426815c51..3fb9ac8cbc 100644 --- a/web/src/engine/keyboard/src/mock.ts +++ b/web/src/engine/keyboard/src/syntheticTextStore.ts @@ -1,7 +1,7 @@ import { TextStore } from './textStore.js'; import { KMWString } from '@keymanapp/web-utils'; -export class Mock extends TextStore { +export class SyntheticTextStore extends TextStore { text: string; selStart: number; @@ -31,17 +31,17 @@ export class Mock extends TextStore { } } - // Clones the state of an existing EditableElement, creating a Mock version of its state. - static from(textStore: TextStore, readonly?: boolean): Mock { - let clone: Mock; + // Clones the state of an existing EditableElement, creating a SyntheticTextStore version of its state. + static from(textStore: TextStore, readonly?: boolean): SyntheticTextStore { + let clone: SyntheticTextStore; this.assertIsOutputTargetBase(textStore); - if (textStore instanceof Mock) { + if (textStore instanceof SyntheticTextStore) { // Avoids the need to run expensive kmwstring.ts `length()` - // calculations when deep-copying Mock instances. - const priorMock = textStore as Mock; - clone = new Mock(priorMock.text, priorMock.selStart, priorMock.selEnd); + // calculations when deep-copying SyntheticTextStore instances. + const priorMock = textStore as SyntheticTextStore; + clone = new SyntheticTextStore(priorMock.text, priorMock.selStart, priorMock.selEnd); } else { const text = textStore.getText(); const textLen = KMWString.length(text); @@ -57,10 +57,10 @@ export class Mock extends TextStore { selectionEnd = textLen - KMWString.length(afterText); } - // readonly group or not, the returned Mock remains the same. + // readonly group or not, the returned SyntheticTextStore remains the same. // New-context events should act as if the caret were at the earlier-in-context // side of the selection, same as standard keyboard rules. - clone = new Mock(text, selectionStart, selectionEnd); + clone = new SyntheticTextStore(text, selectionStart, selectionEnd); } // Also duplicate deadkey state! (Needed for fat-finger ops.) @@ -147,11 +147,11 @@ export class Mock extends TextStore { } /** - * Indicates if this Mock represents an identical context to that of another Mock. + * Indicates if this SyntheticTextStore represents an identical context to that of another SyntheticTextStore. * @param other * @returns */ - isEqual(other: Mock) { + isEqual(other: SyntheticTextStore) { return this.text == other.text && this.selStart == other.selStart && this.selEnd == other.selEnd @@ -159,6 +159,6 @@ export class Mock extends TextStore { } doInputEvent() { - // Mock isn't backed by an element, so it won't have any event listeners. + // SyntheticTextStore isn't backed by an element, so it won't have any event listeners. } } diff --git a/web/src/engine/keyboard/src/textStore.ts b/web/src/engine/keyboard/src/textStore.ts index 1e7889f918..9b405deee3 100644 --- a/web/src/engine/keyboard/src/textStore.ts +++ b/web/src/engine/keyboard/src/textStore.ts @@ -2,7 +2,7 @@ import { KMWString } from "@keymanapp/web-utils"; import { Alternate, TextTransform } from "./keyboards/textTransform.js"; import { Transcription } from "./keyboards/transcription.js"; import { findCommonSubstringEndIndex } from "./stringDivergence.js"; -import { Mock } from "./mock.js"; +import { SyntheticTextStore } from "./syntheticTextStore.js"; // Defines deadkey management in a manner attachable to each element interface. import { type KeyEvent } from 'keyman/engine/keyboard'; @@ -52,7 +52,7 @@ export abstract class TextStore { } /** - * Needed to properly clone deadkeys for use with Mock element interfaces toward predictive text purposes. + * Needed to properly clone deadkeys for use with SyntheticTextStore element interfaces toward predictive text purposes. * @param {object} dks An existing set of deadkeys to deep-copy for use by this element interface. */ protected setDeadkeys(dks: DeadkeyTracker) { @@ -65,7 +65,7 @@ export abstract class TextStore { * * This is designed for use as a "before and after" comparison to determine the effect of a single keyboard rule at a time. * As such, it assumes that the caret is immediately after any inserted text. - * @param from An output target (preferably a Mock) representing the prior state of the input/output system. + * @param from An output target (preferably a SyntheticTextStore) representing the prior state of the input/output system. */ buildTransformFrom(original: TextStore): TextTransform { const toLeft = this.getTextBeforeCaret(); @@ -93,12 +93,12 @@ export abstract class TextStore { // If we ever decide to re-add deadkey tracking, this is the place for it. - return new Transcription(keyEvent, transform, Mock.from(original, readonly), alternates); + return new Transcription(keyEvent, transform, SyntheticTextStore.from(original, readonly), alternates); } /** * Restores the `TextStore` to the indicated state. Designed for use with `Transcription.preInput`. - * @param original An `TextStore` (usually a `Mock`). + * @param original An `TextStore` (usually a `SyntheticTextStore`). */ restoreTo(original: TextStore) { this.clearSelection(); diff --git a/web/src/engine/main/src/headless/contextWindow.ts b/web/src/engine/main/src/headless/contextWindow.ts index 964fea5e20..07051d2332 100644 --- a/web/src/engine/main/src/headless/contextWindow.ts +++ b/web/src/engine/main/src/headless/contextWindow.ts @@ -1,5 +1,5 @@ import { LexicalModelTypes } from '@keymanapp/common-types'; -import { Mock } from "keyman/engine/keyboard"; +import { SyntheticTextStore } from "keyman/engine/keyboard"; import { KMWString } from '@keymanapp/web-utils'; export default class ContextWindow implements LexicalModelTypes.Context { @@ -18,7 +18,7 @@ export default class ContextWindow implements LexicalModelTypes.Context { casingForm?: LexicalModelTypes.CasingForm; - constructor(mock: Mock, config: LexicalModelTypes.Configuration, layerId: string) { + constructor(mock: SyntheticTextStore, config: LexicalModelTypes.Configuration, layerId: string) { this.left = mock.getTextBeforeCaret(); this.startOfBuffer = KMWString.length(this.left) <= config.leftContextCodePoints; if(!this.startOfBuffer) { @@ -38,9 +38,9 @@ export default class ContextWindow implements LexicalModelTypes.Context { null; } - public toMock(): Mock { + public toMock(): SyntheticTextStore { const caretPos = KMWString.length(this.left); - return new Mock(this.left + (this.right || ""), caretPos); + return new SyntheticTextStore(this.left + (this.right || ""), caretPos); } } \ No newline at end of file diff --git a/web/src/engine/main/src/headless/inputProcessor.ts b/web/src/engine/main/src/headless/inputProcessor.ts index 0518d989aa..aee818c42a 100644 --- a/web/src/engine/main/src/headless/inputProcessor.ts +++ b/web/src/engine/main/src/headless/inputProcessor.ts @@ -11,7 +11,7 @@ import { Codes, JSKeyboard, KeyboardMinimalInterface, - Mock, + SyntheticTextStore, TextStore, ProcessorAction, SystemStoreIDs, @@ -120,10 +120,10 @@ export class InputProcessor { // to revert it. If not, we assume it's a layer-change multitap, in which case // no such reset is needed. // TODO-web-core - if(!isEmptyTransform(transcription.transform) || !(transcription.preInput as Mock).isEqual(Mock.from(textStore))) { + if(!isEmptyTransform(transcription.transform) || !(transcription.preInput as SyntheticTextStore).isEqual(SyntheticTextStore.from(textStore))) { // Restores full context, including deadkeys in their exact pre-keystroke state. // TODO-web-core - (textStore as TextStore).restoreTo(transcription.preInput as Mock); + (textStore as TextStore).restoreTo(transcription.preInput as SyntheticTextStore); } /* else: @@ -200,7 +200,7 @@ export class InputProcessor { // Create a "mock" backup of the current textStore in its pre-input state. // Current, long-existing assumption - it's DOM-backed. // TODO-web-core - const preInputMock = Mock.from(textStore as TextStore, true); + const preInputMock = SyntheticTextStore.from(textStore as TextStore, true); const startingLayerId = this.keyboardProcessor.layerId; @@ -292,7 +292,7 @@ export class InputProcessor { return keepRuleBehavior ? ruleBehavior : null; } - private buildAlternates(ruleBehavior: ProcessorAction, keyEvent: KeyEvent, preInputMock: Mock): Alternate[] { + private buildAlternates(ruleBehavior: ProcessorAction, keyEvent: KeyEvent, preInputMock: SyntheticTextStore): Alternate[] { let alternates: Alternate[]; // If we're performing a 'default command', it's not a standard 'typing' event - don't do fat-finger stuff. @@ -360,7 +360,7 @@ export class InputProcessor { break; } - const mock = Mock.from(windowedMock, false); + const mock = SyntheticTextStore.from(windowedMock, false); const altKey = pair.keySpec; if(!altKey) { diff --git a/web/src/engine/main/src/headless/languageProcessor.ts b/web/src/engine/main/src/headless/languageProcessor.ts index b3a749ce93..aa76d7c22b 100644 --- a/web/src/engine/main/src/headless/languageProcessor.ts +++ b/web/src/engine/main/src/headless/languageProcessor.ts @@ -1,6 +1,6 @@ import { EventEmitter } from "eventemitter3"; import { LMLayer, WorkerFactory } from "@keymanapp/lexical-model-layer/web"; -import { Transcription, TextStore, Mock } from 'keyman/engine/keyboard'; +import { Transcription, TextStore, SyntheticTextStore } from 'keyman/engine/keyboard'; import { LanguageProcessorEventMap, ModelSpec, StateChangeEnum, ReadySuggestions } from 'keyman/engine/interfaces'; import ContextWindow from "./contextWindow.js"; import { TranscriptionCache } from "./transcriptionCache.js"; @@ -160,7 +160,7 @@ export class LanguageProcessor extends EventEmitter { } // TODO-web-core - const context = new ContextWindow(Mock.from((target as TextStore), false), this.configuration, layerId); + const context = new ContextWindow(SyntheticTextStore.from((target as TextStore), false), this.configuration, layerId); return this.lmEngine.wordbreak(context); } @@ -216,7 +216,7 @@ export class LanguageProcessor extends EventEmitter { // Apply the Suggestion! // Step 1: determine the final output text - const final = Mock.from(original.preInput, false); + const final = SyntheticTextStore.from(original.preInput, false); final.apply(suggestion.transform); // Step 2: build a final, master Transform that will produce the desired results from the CURRENT state. @@ -233,12 +233,12 @@ export class LanguageProcessor extends EventEmitter { // Build a 'reversion' Transcription that can be used to undo this apply() if needed, // replacing the suggestion transform with the original input text. - const preApply = Mock.from(original.preInput, false); + const preApply = SyntheticTextStore.from(original.preInput, false); preApply.apply(original.transform); // Builds the reversion option according to the loaded lexical model's known // syntactic properties. - const suggestionContext = new ContextWindow(original.preInput as Mock, this.configuration, getLayerId()); + const suggestionContext = new ContextWindow(original.preInput as SyntheticTextStore, this.configuration, getLayerId()); // We must accept the Suggestion from its original context, which was before // `original.transform` was applied. @@ -291,7 +291,7 @@ export class LanguageProcessor extends EventEmitter { // Apply the Reversion! // Step 1: determine the final output text - const final = Mock.from(original.preInput, false); + const final = SyntheticTextStore.from(original.preInput, false); final.apply(reversion.transform); // Should match original.transform, actually. (See applySuggestion) // Step 2: build a final, master Transform that will produce the desired results from the CURRENT state. @@ -303,7 +303,7 @@ export class LanguageProcessor extends EventEmitter { (textStore as TextStore).apply(transform); // The reason we need to preserve the additive-inverse 'transformId' property on Reversions. - const promise = this.currentPromise = this.lmEngine.revertSuggestion(reversion, new ContextWindow(original.preInput as Mock, this.configuration, null)) + const promise = this.currentPromise = this.lmEngine.revertSuggestion(reversion, new ContextWindow(original.preInput as SyntheticTextStore, this.configuration, null)) // If the "current Promise" is as set above, clear it. // If another one has been triggered since... don't. promise.then(() => this.currentPromise = (this.currentPromise == promise) ? null : this.currentPromise); @@ -331,7 +331,7 @@ export class LanguageProcessor extends EventEmitter { return null; } - const context = new ContextWindow(transcription.preInput as Mock, this.configuration, layerId); + const context = new ContextWindow(transcription.preInput as SyntheticTextStore, this.configuration, layerId); this.recordTranscription(transcription); if(resetContext) { diff --git a/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.tests.ts b/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.tests.ts index 99997f14d4..aeaf007833 100644 --- a/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.tests.ts +++ b/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.tests.ts @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { KMWString, Mock } from 'keyman/engine/keyboard'; +import { KMWString, SyntheticTextStore } from 'keyman/engine/keyboard'; import * as wrappers from 'keyman/engine/element-wrappers'; import { DynamicElements } from '../../test_utils.js'; @@ -320,10 +320,10 @@ class DesignIFrameTestHelper implements TestHelper { } //#endregion -//#region Defines helpers related to Mock test setup. +//#region Defines helpers related to SyntheticTextStore test setup. class MockTestHelper implements TestHelper { setupElement(): ElementPair { - return { elem: null, wrapper: new Mock() }; + return { elem: null, wrapper: new SyntheticTextStore() }; } resetWithText(pair: ElementPair, string: string) { @@ -371,7 +371,7 @@ class InterfaceTests { public static DesignIFrame = new DesignIFrameTestHelper(); - public static Mock = new MockTestHelper(); + public static SyntheticTextStore = new MockTestHelper(); //#region Defines common test patterns across element tests public static Tests = class { @@ -1379,8 +1379,8 @@ describe('Element Input/Output Interfacing', function () { }); }); - describe('The "Mock" output target', function () { - // Unique to the Mock type - element interface cloning tests. Is element state properly copied? + describe('The "SyntheticTextStore" output target', function () { + // Unique to the SyntheticTextStore type - element interface cloning tests. Is element state properly copied? // As those require a very different setup, they're in the target_mocks.js test case file instead. // Basic text-retrieval unit tests are now done headlessly in keyman/engine/keyboard. @@ -1388,26 +1388,26 @@ describe('Element Input/Output Interfacing', function () { describe('Text Mutation', function () { describe('deleteCharsBeforeCaret', function () { it("correctly deletes characters from 'context' (no active selection)", function () { - InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.Mock); + InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.SyntheticTextStore); }); it("correctly deletes characters from 'context' (with active selection)", function () { - InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection(InterfaceTests.Mock); + InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection(InterfaceTests.SyntheticTextStore); }); }); describe('insertTextBeforeCaret', function () { it("correctly replaces the element's 'context' (no active selection)", function () { - InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.Mock); + InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.SyntheticTextStore); }); it("correctly replaces the element's 'context' (with active selection)", function () { - InterfaceTests.Tests.insertTextBeforeCaretWithSelection(InterfaceTests.Mock); + InterfaceTests.Tests.insertTextBeforeCaretWithSelection(InterfaceTests.SyntheticTextStore); }); }); it('correctly maintains deadkeys', function () { - InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.Mock); + InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.SyntheticTextStore); }); }); }); diff --git a/web/src/test/auto/dom/cases/element-wrappers/target_mocks.tests.ts b/web/src/test/auto/dom/cases/element-wrappers/target_mocks.tests.ts index a6666898ca..ea4ac07707 100644 --- a/web/src/test/auto/dom/cases/element-wrappers/target_mocks.tests.ts +++ b/web/src/test/auto/dom/cases/element-wrappers/target_mocks.tests.ts @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { KMWString, Mock } from 'keyman/engine/keyboard'; +import { KMWString, SyntheticTextStore } from 'keyman/engine/keyboard'; import { Input } from 'keyman/engine/element-wrappers'; import { DEFAULT_BROWSER_TIMEOUT } from '@keymanapp/common-test-resources/test-timeouts.mjs'; @@ -78,10 +78,10 @@ describe('TextStore Mocking', function() { KMWString.enableSupplementaryPlane(false); }) - describe('The "Mock" output target', function() { + describe('The "SyntheticTextStore" output target', function() { describe('Initialization', function() { it('properly initializes from a raw string', function() { - const mock = new Mock(MockTests.Apple.mixed); + const mock = new SyntheticTextStore(MockTests.Apple.mixed); assert.equal(mock.getText(), MockTests.Apple.mixed); assert.equal(mock.getDeadkeyCaret(), 5); @@ -90,7 +90,7 @@ describe('TextStore Mocking', function() { it('copies an existing TextStore without a text selection', function() { const base = MockTests.setupBase(4); - const mock = Mock.from(base); + const mock = SyntheticTextStore.from(base); assert.equal(mock.getText(), MockTests.Apple.mixed); assert.deepEqual(mock.deadkeys(), base.deadkeys()); }); @@ -98,7 +98,7 @@ describe('TextStore Mocking', function() { it('copies an existing TextStore with a text selection', function() { const base = MockTests.setupBase(4, 5); - const mock = Mock.from(base); + const mock = SyntheticTextStore.from(base); // The selection should appear to be automatically deleted, as any text mutation // by KMW would automatically erase the text anyway. assert.equal(mock.getTextBeforeCaret(), MockTests.Apple.mixed.substr(0, 5)); @@ -114,7 +114,7 @@ describe('TextStore Mocking', function() { it('is not affected by mutation of the source element', function() { // Already-verified code const base = MockTests.setupBase(4); - const mock = Mock.from(base); + const mock = SyntheticTextStore.from(base); const baseInitDks = base.deadkeys().clone(); // Now for the actual test. @@ -133,7 +133,7 @@ describe('TextStore Mocking', function() { it('does not affect the source element when mutated', function() { // Already-verified code const base = MockTests.setupBase(4); - const mock = Mock.from(base); + const mock = SyntheticTextStore.from(base); const baseInitDks = base.deadkeys().clone(); // Now for the actual test. diff --git a/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.tests.ts b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.tests.ts index 8cc5493d4e..326cb5b9aa 100644 --- a/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.tests.ts +++ b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.tests.ts @@ -1,7 +1,7 @@ import { assert } from 'chai'; import { DOMKeyboardLoader } from 'keyman/engine/keyboard/dom-keyboard-loader'; -import { KeyboardHarness, JSKeyboard, MinimalKeymanGlobal, DeviceSpec, KeyboardKeymanGlobal, KeyboardDownloadError, KeyboardScriptError, Keyboard, Mock } from 'keyman/engine/keyboard'; +import { KeyboardHarness, JSKeyboard, MinimalKeymanGlobal, DeviceSpec, KeyboardKeymanGlobal, KeyboardDownloadError, KeyboardScriptError, Keyboard, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface } from 'keyman/engine/js-processor'; import { assertThrowsAsync } from 'keyman/tools/testing/test-utils'; @@ -82,7 +82,7 @@ describe('Keyboard loading in DOM', function() { // TODO: verify actual rule processing. const nullKeyEvent = jsKeyboard.constructNullKeyEvent(device); - const mock = new Mock(); + const mock = new SyntheticTextStore(); const result = jsHarness.processKeystroke(mock, nullKeyEvent); assert.isOk(result); diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js index 96b8d98a26..dd2d75257f 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js @@ -4,7 +4,7 @@ import sinon from 'sinon'; import { LanguageProcessor, TranscriptionCache } from 'keyman/engine/main'; import { PredictionContext } from 'keyman/engine/interfaces'; import { Worker as LMWorker } from "@keymanapp/lexical-model-layer/node"; -import { DeviceSpec, Mock } from 'keyman/engine/keyboard'; +import { DeviceSpec, SyntheticTextStore } from 'keyman/engine/keyboard'; function compileDummyModel(suggestionSets) { return ` @@ -81,8 +81,8 @@ describe("PredictionContext", () => { let updateFake = sinon.fake(); predictiveContext.on('update', updateFake); - let mock = new Mock("appl", 4); // "appl|", with '|' as the caret position. - const initialMock = Mock.from(mock); + let mock = new SyntheticTextStore("appl", 4); // "appl|", with '|' as the caret position. + const initialMock = SyntheticTextStore.from(mock); const promise = predictiveContext.setCurrentTarget(mock); // Initial predictive state: no suggestions. context.initializeState() has not yet been called. @@ -120,8 +120,8 @@ describe("PredictionContext", () => { let updateFake = sinon.fake(); predictiveContext.on('update', updateFake); - let mock = new Mock("appl", 4); // "appl|", with '|' as the caret position. - const initialMock = Mock.from(mock); + let mock = new SyntheticTextStore("appl", 4); // "appl|", with '|' as the caret position. + const initialMock = SyntheticTextStore.from(mock); const promise = predictiveContext.setCurrentTarget(mock); // Initial predictive state: no suggestions. context.initializeState() has not yet been called. @@ -180,7 +180,7 @@ describe("PredictionContext", () => { const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); - let mock = new Mock("appl", 4); // "appl|", with '|' as the caret position. + let mock = new SyntheticTextStore("appl", 4); // "appl|", with '|' as the caret position. const initialSuggestions = await predictiveContext.setCurrentTarget(mock); let updateFake = sinon.fake(); @@ -204,7 +204,7 @@ describe("PredictionContext", () => { const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); - let textState = new Mock("appl", 4); // "appl|", with '|' as the caret position. + let textState = new SyntheticTextStore("appl", 4); // "appl|", with '|' as the caret position. await predictiveContext.setCurrentTarget(textState); @@ -213,7 +213,7 @@ describe("PredictionContext", () => { let suggestions; - let previousTextState = Mock.from(textState); + let previousTextState = SyntheticTextStore.from(textState); textState.insertTextBeforeCaret('e'); // appl| + e = apple let transcription = textState.buildTranscriptionFrom(previousTextState, null, true); await langProcessor.predict(transcription, dummiedGetLayer()); @@ -226,7 +226,7 @@ describe("PredictionContext", () => { assert.equal(suggestions.find((obj) => obj.transform.deleteLeft != 0).displayAs, 'apps'); // Now for the real test. - previousTextState = Mock.from(textState); // snapshot it! + previousTextState = SyntheticTextStore.from(textState); // snapshot it! const suggestionApply = suggestions.find((obj) => obj.displayAs == 'apply'); assert.isOk(suggestionApply); @@ -270,14 +270,14 @@ describe("PredictionContext", () => { const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); - let textState = new Mock("appl", 4); // "appl|", with '|' as the caret position. + let textState = new SyntheticTextStore("appl", 4); // "appl|", with '|' as the caret position. // Test setup - return to the state at the end of the prior-defined unit test ('suggestion application...') await predictiveContext.setCurrentTarget(textState); // This is the point in time that a reversion operation will rewind the context to. - const revertBaseTextState = Mock.from(textState); + const revertBaseTextState = SyntheticTextStore.from(textState); textState.insertTextBeforeCaret('e'); // appl| + e = apple let transcription = textState.buildTranscriptionFrom(revertBaseTextState, null, true); @@ -291,7 +291,7 @@ describe("PredictionContext", () => { const suggestionApply = originalSuggestionSet.find((obj) => obj.displayAs == 'apply'); assert.isOk(suggestionApply); - let previousTextState = Mock.from(textState); + let previousTextState = SyntheticTextStore.from(textState); // For awaiting the suggestions generated upon applying our desired suggestion. // We aren't given a direct Promise for that, but we can construct one this way. @@ -320,7 +320,7 @@ describe("PredictionContext", () => { assert.equal(reversion.displayAs.length, previousTextState.getText().length + 2); // +2: opening + closing quotes. // Fire away! Time to apply the reversion. - previousTextState = Mock.from(textState); + previousTextState = SyntheticTextStore.from(textState); // Since the test uses a separate thread via Worker, make sure to set up any important event handlers // before we request the reversion. @@ -340,7 +340,7 @@ describe("PredictionContext", () => { assert.isNull(returnValue); // as per the method's spec. // Verify that the rewind + application of reversion worked! - let rewoundTextStateWithInput = Mock.from(revertBaseTextState); // appl + let rewoundTextStateWithInput = SyntheticTextStore.from(revertBaseTextState); // appl rewoundTextStateWithInput.apply(reversion.transform); // + e assert.equal(rewoundTextStateWithInput.getText(), 'apple'); // For visual clarity. diff --git a/web/src/test/auto/headless/engine/js-processor/bundled-module.tests.js b/web/src/test/auto/headless/engine/js-processor/bundled-module.tests.js index 0eceada34e..8601a06f45 100644 --- a/web/src/test/auto/headless/engine/js-processor/bundled-module.tests.js +++ b/web/src/test/auto/headless/engine/js-processor/bundled-module.tests.js @@ -39,9 +39,9 @@ describe('Bundled ES Module for keyboard', function () { }); }); - describe('Mock', () => { + describe('SyntheticTextStore', () => { it('basic functionality test', () => { - let target = new KeyboardPackage.Mock("aple", 2); // ap | le + let target = new KeyboardPackage.SyntheticTextStore("aple", 2); // ap | le target.insertTextBeforeCaret('p'); assert.equal(target.getText(), "apple"); }); @@ -49,7 +49,7 @@ describe('Bundled ES Module for keyboard', function () { it('smp test', () => { KMWString.enableSupplementaryPlane(true); // Declared & defined in web-utils. try { - let target = new KeyboardPackage.Mock(u(0x1d5ba) + u(0x1d5c9) + u(0x1d5c5) + u(0x1d5be), 2); // ap | le + let target = new KeyboardPackage.SyntheticTextStore(u(0x1d5ba) + u(0x1d5c9) + u(0x1d5c5) + u(0x1d5be), 2); // ap | le target.insertTextBeforeCaret(u(0x1d5c9)); assert.equal(target.getText(), u(0x1d5ba) + u(0x1d5c9) + u(0x1d5c9) + u(0x1d5c5) + u(0x1d5be)); } finally { diff --git a/web/src/test/auto/headless/engine/js-processor/engine/context.tests.js b/web/src/test/auto/headless/engine/js-processor/engine/context.tests.js index 813f699b1e..54b70f84d6 100644 --- a/web/src/test/auto/headless/engine/js-processor/engine/context.tests.js +++ b/web/src/test/auto/headless/engine/js-processor/engine/context.tests.js @@ -3,7 +3,7 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface, JSKeyboardProcessor } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; @@ -61,7 +61,7 @@ function runEngineRuleSet(ruleSet, defaultNoun) { let proctor = new NodeProctor(keyboardWithHarness, device, assert.equal); // We want to specify the OutputTarget for this test; our actual concern is the resulting context. - var target = new Mock(); + var target = new SyntheticTextStore(); ruleSeq.test(proctor, target); // Now for the real test! @@ -1118,7 +1118,7 @@ describe('Engine - Context Matching', function() { let proctor = new NodeProctor(keyboardWithHarness, device, assert.equal); // We want to specify the OutputTarget for this test; our actual concern is the resulting context. - var target = new Mock(); + var target = new SyntheticTextStore(); ruleSeq.test(proctor, target); // Now for the real test! diff --git a/web/src/test/auto/headless/engine/js-processor/engine/notany_context.tests.js b/web/src/test/auto/headless/engine/js-processor/engine/notany_context.tests.js index 840de72cb0..2237d88f4e 100644 --- a/web/src/test/auto/headless/engine/js-processor/engine/notany_context.tests.js +++ b/web/src/test/auto/headless/engine/js-processor/engine/notany_context.tests.js @@ -3,7 +3,7 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { NodeProctor, RecordedKeystrokeSequence } from '@keymanapp/recorder-core'; @@ -23,7 +23,7 @@ function runEngineRuleSet(ruleSet) { // Prepare the context! const ruleSeq = new RecordedKeystrokeSequence(ruleDef); const proctor = new NodeProctor(keyboardWithHarness, device, assert.equal); - const target = new Mock(); + const target = new SyntheticTextStore(); ruleSeq.test(proctor, target); } } diff --git a/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.ts b/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.ts index d3f75964c5..41485ebf59 100644 --- a/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.ts +++ b/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.ts @@ -3,7 +3,7 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { DeviceSpec, JSKeyboard, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { DeviceSpec, JSKeyboard, MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; @@ -43,7 +43,7 @@ describe('Headless keyboard loading', function () { // -- END: Standard Recorder-based unit test loading boilerplate -- // Runs a blank KeyEvent through the keyboard's rule processing. - harness.processKeystroke(new Mock(), (keyboard as JSKeyboard).constructNullKeyEvent(device)); + harness.processKeystroke(new SyntheticTextStore(), (keyboard as JSKeyboard).constructNullKeyEvent(device)); }); it('does not change the active kehboard', async function () { diff --git a/web/src/test/auto/headless/engine/js-processor/non-positional-rules.tests.js b/web/src/test/auto/headless/engine/js-processor/non-positional-rules.tests.js index a041880bb0..f3b425472e 100644 --- a/web/src/test/auto/headless/engine/js-processor/non-positional-rules.tests.js +++ b/web/src/test/auto/headless/engine/js-processor/non-positional-rules.tests.js @@ -4,7 +4,7 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { Codes, KeyEvent, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { Codes, KeyEvent, MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; @@ -41,7 +41,7 @@ describe('Engine - rule processing', function() { 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 mockMnemonic = new SyntheticTextStore('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 @@ -62,7 +62,7 @@ describe('Engine - rule processing', function() { 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 mockMnemonic = new SyntheticTextStore('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 @@ -81,7 +81,7 @@ describe('Engine - rule processing', function() { }); it('does not match rules with positional-specced KeyEvents', () => { - let mockPositional = new Mock('n'); + let mockPositional = new SyntheticTextStore('n'); let positionalEvent = new KeyEvent({ // If it were positional, we'd use this instead: Lcode: Codes.keyCodes.K_COMMA, // 188 @@ -119,7 +119,7 @@ describe('Engine - rule processing', function() { }); it('matches rules with legacy-specced KeyEvents', () => { - let mockLegacy = new Mock(''); + let mockLegacy = new SyntheticTextStore(''); 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), @@ -139,7 +139,7 @@ describe('Engine - rule processing', function() { }); it('ignores current modifiers and states', () => { - let mockLegacy = new Mock(''); + let mockLegacy = new SyntheticTextStore(''); 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), @@ -159,7 +159,7 @@ describe('Engine - rule processing', function() { }); it('does not match rules with mnemonic-specced KeyEvents', () => { - let mockMnemonic = new Mock(''); + let mockMnemonic = new SyntheticTextStore(''); 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), @@ -178,7 +178,7 @@ describe('Engine - rule processing', function() { }); it('does not match rules with positional-specced KeyEvents', () => { - let mockPositional = new Mock(''); + let mockPositional = new SyntheticTextStore(''); let positionalEvent = new KeyEvent({ // If it were positional, we'd use this instead: Lcode: Codes.keyCodes.K_A, diff --git a/web/src/test/auto/headless/engine/js-processor/specialized-backspace.tests.js b/web/src/test/auto/headless/engine/js-processor/specialized-backspace.tests.js index a1a2d1b229..a9a229bd75 100644 --- a/web/src/test/auto/headless/engine/js-processor/specialized-backspace.tests.js +++ b/web/src/test/auto/headless/engine/js-processor/specialized-backspace.tests.js @@ -5,7 +5,7 @@ import { createRequire } from 'module'; const require = createRequire(import.meta.url); import { KMWString } from '@keymanapp/web-utils'; -import { Codes, KeyEvent, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { Codes, KeyEvent, MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface, JSKeyboardProcessor } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { ModifierKeyConstants } from '@keymanapp/common-types'; @@ -128,7 +128,7 @@ describe('Engine - specialized backspace handling', function() { }); it('empty context, positional keyboard', () => { - let contextSource = new Mock(''); + let contextSource = new SyntheticTextStore(''); let event = new KeyEvent({ Lcode: Codes.keyCodes.K_BKSP, Lmodifiers: 0, @@ -156,7 +156,7 @@ describe('Engine - specialized backspace handling', function() { }); it("empty context, positional keyboard, outputless-key that's not BKSP", () => { - let contextSource = new Mock(''); + let contextSource = new SyntheticTextStore(''); let event = new KeyEvent({ Lcode: Codes.keyCodes.K_A, Lmodifiers: 0, @@ -189,7 +189,7 @@ describe('Engine - specialized backspace handling', function() { }); it('empty context, positional keyboard, but text is selected', () => { - let contextSource = new Mock('selected text', 0); + let contextSource = new SyntheticTextStore('selected text', 0); contextSource.setSelection(0, KMWString.length(contextSource.getText())); let event = new KeyEvent({ @@ -226,7 +226,7 @@ describe('Engine - specialized backspace handling', function() { }); it('empty left-context, positional keyboard', () => { - let contextSource = new Mock('post-caret text', 0); + let contextSource = new SyntheticTextStore('post-caret text', 0); let event = new KeyEvent({ Lcode: Codes.keyCodes.K_BKSP, Lmodifiers: 0, @@ -254,7 +254,7 @@ describe('Engine - specialized backspace handling', function() { }); it('empty context, mnemonic keyboard', () => { - let contextSource = new Mock(''); + let contextSource = new SyntheticTextStore(''); let event = new KeyEvent({ Lcode: Codes.keyCodes.K_BKSP, Lmodifiers: 0, @@ -282,7 +282,7 @@ describe('Engine - specialized backspace handling', function() { }); it('final empty context, positional keyboard, rule-handled BKSP', () => { - let contextSource = new Mock('abc', 2); + let contextSource = new SyntheticTextStore('abc', 2); let event = new KeyEvent({ Lcode: Codes.keyCodes.K_BKSP, Lmodifiers: 0, @@ -317,7 +317,7 @@ describe('Engine - specialized backspace handling', function() { // Special case: BKSP rule-matches with empty left-context. it("empty context, positional keyboard, outputless BKSP rule", () => { - let contextSource = new Mock(''); + let contextSource = new SyntheticTextStore(''); let event = new KeyEvent({ Lcode: Codes.keyCodes.K_BKSP, Lmodifiers: 0, diff --git a/web/src/test/auto/headless/engine/js-processor/transcriptions.tests.js b/web/src/test/auto/headless/engine/js-processor/transcriptions.tests.js index 8f81f0d362..2632431060 100644 --- a/web/src/test/auto/headless/engine/js-processor/transcriptions.tests.js +++ b/web/src/test/auto/headless/engine/js-processor/transcriptions.tests.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { Mock, findCommonSubstringEndIndex } from 'keyman/engine/keyboard'; +import { SyntheticTextStore, findCommonSubstringEndIndex } from 'keyman/engine/keyboard'; import { KMWString } from '@keymanapp/web-utils'; // A unicode-coding like alias for use in constructing non-BMP strings. @@ -157,8 +157,8 @@ describe("Transcriptions and Transforms", function() { it("does not store an alias for related OutputTargets", function() { // We have other texts validating Mocks; by using them as our base 'element', this unit test file // could eventually run in 'headless' mode. - var target = new Mock("apple"); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple"); + var original = SyntheticTextStore.from(target); target.insertTextBeforeCaret("s"); /* It's not exactly black box, but presently we don't NEED the keyEvent object for the method to work. @@ -174,8 +174,8 @@ describe("Transcriptions and Transforms", function() { it("handles context-free single-char output rules", function() { // We have other texts validating Mocks; by using them as our base 'element', this unit test file // could eventually run in 'headless' mode. - var target = new Mock("apple"); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple"); + var original = SyntheticTextStore.from(target); target.insertTextBeforeCaret("s"); /* It's not exactly black box, but presently we don't NEED the keyEvent object for the method to work. @@ -187,8 +187,8 @@ describe("Transcriptions and Transforms", function() { assert.equal(transcription.transform.deleteLeft, 0, "Incorrectly detected left-of-caret deletions"); assert.equal(transcription.transform.deleteRight, 0, "Incorrectly detected right-of-caret deletions"); - target = new Mock("apple", 3); - original = Mock.from(target); + target = new SyntheticTextStore("apple", 3); + original = SyntheticTextStore.from(target); target.insertTextBeforeCaret("s"); // "appsle" var transcription = target.buildTranscriptionFrom(original, null); @@ -199,8 +199,8 @@ describe("Transcriptions and Transforms", function() { }); it("handles operations with moderately long text", function() { - var target = new Mock("The quick brown cat jumped onto the lazy dog.", 19); - var original = Mock.from(target); + var target = new SyntheticTextStore("The quick brown cat jumped onto the lazy dog.", 19); + var original = SyntheticTextStore.from(target); target.setSelection(30); // 19 + 11: moves it to after "onto". target.deleteCharsBeforeCaret(14); // delete: "cat jumped onto" target.insertTextBeforeCaret("fox jumped over"); @@ -228,8 +228,8 @@ he did. Unfortunately, he taught his apprentice everything he knew, then his apprentice killed him in his sleep. It's ironic he could save others from death, but not himself.`; // Sheev Palpatine, in the Star Wars prequels. - var target = new Mock(text, text.length); - var original = Mock.from(target); + var target = new SyntheticTextStore(text, text.length); + var original = SyntheticTextStore.from(target); target.deleteCharsBeforeCaret(1); target.insertTextBeforeCaret("!"); @@ -244,8 +244,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. }); it("handles deletions around the caret without text insertion", function() { - var target = new Mock("apple", 2); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple", 2); + var original = SyntheticTextStore.from(target); target.setSelection(3); target.deleteCharsBeforeCaret(2); // "ale" @@ -262,8 +262,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. it("handles deletions around the caret without text insertion (non-BMP text)", function() { try { KMWString.enableSupplementaryPlane(true); - var target = new Mock(smpApple, 2); - var original = Mock.from(target); + var target = new SyntheticTextStore(smpApple, 2); + var original = SyntheticTextStore.from(target); target.setSelection(3); target.deleteCharsBeforeCaret(2); // "ale" @@ -283,8 +283,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. it("handles deletions around the caret with text insertion", function() { // We have other texts validating Mocks; by using them as our base 'element', this unit test file // could eventually run in 'headless' mode. - var target = new Mock("apple", 2); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple", 2); + var original = SyntheticTextStore.from(target); target.setSelection(3); target.deleteCharsBeforeCaret(2); target.insertTextBeforeCaret("PP"); // "aPPle" @@ -300,8 +300,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // CASE 2 - var target = new Mock("apple", 2); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple", 2); + var original = SyntheticTextStore.from(target); target.setSelection(4); target.deleteCharsBeforeCaret(3); target.insertTextBeforeCaret("P"); // "aPe" @@ -317,8 +317,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // CASE 3 - var target = new Mock("apple", 2); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple", 2); + var original = SyntheticTextStore.from(target); target.setSelection(4); target.deleteCharsBeforeCaret(3); target.insertTextBeforeCaret("aaaaaaaaaaaaaa"); // "aaaaaaaaaaaaaaae" @@ -334,8 +334,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // CASE 4 - var target = new Mock("apple", 2); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple", 2); + var original = SyntheticTextStore.from(target); target.setSelection(5); target.deleteCharsBeforeCaret(4); target.insertTextBeforeCaret("les"); // "ales" - since we've appended a letter at the very end, the whole right-hand is indeed an insertion. @@ -357,9 +357,9 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // We have other texts validating Mocks; by using them as our base 'element', this unit test file // could eventually run in 'headless' mode. - var target = new Mock(smpApple, 2); + var target = new SyntheticTextStore(smpApple, 2); let smpLE = u(0x1d5c5)+u(0x1d5be); - var original = Mock.from(target); + var original = SyntheticTextStore.from(target); target.setSelection(3); target.deleteCharsBeforeCaret(2); target.insertTextBeforeCaret(smpLE); // "alele" @@ -377,9 +377,9 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // CASE 2 - var target = new Mock(smpApple, 2); + var target = new SyntheticTextStore(smpApple, 2); let smpB = u(0x1d5bb); - var original = Mock.from(target); + var original = SyntheticTextStore.from(target); target.setSelection(4); target.deleteCharsBeforeCaret(3); target.insertTextBeforeCaret(smpB); // "aPe" @@ -395,8 +395,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // CASE 3 - var target = new Mock(smpApple, 2); - var original = Mock.from(target); + var target = new SyntheticTextStore(smpApple, 2); + var original = SyntheticTextStore.from(target); target.setSelection(4); target.deleteCharsBeforeCaret(3); target.insertTextBeforeCaret("aaaaaaaaaaaaaa"); // "aaaaaaaaaaaaaaae" @@ -412,9 +412,9 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // CASE 4 - var target = new Mock(smpApple, 2); + var target = new SyntheticTextStore(smpApple, 2); let smpLES = u(0x1d5c5)+u(0x1d5be)+u(0x1d5cb); - var original = Mock.from(target); + var original = SyntheticTextStore.from(target); target.setSelection(5); target.deleteCharsBeforeCaret(4); target.insertTextBeforeCaret(smpLES); // "ales" - since we've appended a letter at the very end, the whole right-hand is indeed an insertion. @@ -435,9 +435,9 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. it('from targets with existing selection', () => { // | | - const target = new Mock("testing testing one two three"); + const target = new SyntheticTextStore("testing testing one two three"); target.setSelection(8, 20) - const original = Mock.from(target); + const original = SyntheticTextStore.from(target); target.clearSelection(); const transform = target.buildTransformFrom(original); @@ -451,7 +451,7 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. it('to targets with existing selection', () => { // | | - const target = new Mock("testing testing one two three"); + const target = new SyntheticTextStore("testing testing one two three"); target.setSelection(8, 20) const transform = { insert: '', @@ -471,8 +471,8 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. // We have other texts validating Mocks; by using them as our base 'element', this unit test file // could eventually run in 'headless' mode. - var target = new Mock("apple"); - var original = Mock.from(target); + var target = new SyntheticTextStore("apple"); + var original = SyntheticTextStore.from(target); target.setSelection(4); target.insertDeadkeyBeforeCaret(0); @@ -481,7 +481,7 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels. target.setSelection(2); target.insertDeadkeyBeforeCaret(2); // 'a' dk(1) 'p' dk(2) | 'p' 'l' dk(0) 'e' - var original = Mock.from(target); + var original = SyntheticTextStore.from(target); target.hasDeadkeyMatch(0, 2); target.deadkeys().deleteMatched(); diff --git a/web/src/test/auto/headless/engine/keyboard/keyboard-loading.tests.js b/web/src/test/auto/headless/engine/keyboard/keyboard-loading.tests.js index e789f6bf51..d9dd5e7414 100644 --- a/web/src/test/auto/headless/engine/keyboard/keyboard-loading.tests.js +++ b/web/src/test/auto/headless/engine/keyboard/keyboard-loading.tests.js @@ -3,7 +3,7 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardHarness, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { KeyboardHarness, MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; @@ -61,7 +61,7 @@ describe('Headless keyboard loading', function() { let ruleHarness = new JSKeyboardInterface({}, MinimalKeymanGlobal); ruleHarness.activeKeyboard = keyboard; try { - ruleHarness.processKeystroke(new Mock(), keyboard.constructNullKeyEvent(device)); + ruleHarness.processKeystroke(new SyntheticTextStore(), keyboard.constructNullKeyEvent(device)); assert.fail(); } catch (err) { // Drives home an important detail: the 'global' object is effectively diff --git a/web/src/test/auto/headless/engine/keyboard/keyboardLoaderBase.tests.ts b/web/src/test/auto/headless/engine/keyboard/keyboardLoaderBase.tests.ts index 232293fbc2..e7f7ecd6d3 100644 --- a/web/src/test/auto/headless/engine/keyboard/keyboardLoaderBase.tests.ts +++ b/web/src/test/auto/headless/engine/keyboard/keyboardLoaderBase.tests.ts @@ -3,7 +3,7 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardHarness, MinimalKeymanGlobal, KeyboardDownloadError, DeviceSpec, InvalidKeyboardError, JSKeyboard, Mock } from 'keyman/engine/keyboard'; +import { KeyboardHarness, MinimalKeymanGlobal, KeyboardDownloadError, DeviceSpec, InvalidKeyboardError, JSKeyboard, SyntheticTextStore } from 'keyman/engine/keyboard'; import { JSKeyboardInterface } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { assertThrowsAsync, assertThrows } from 'keyman/tools/testing/test-utils'; @@ -84,7 +84,7 @@ describe('Headless keyboard loading', function() { // 'sandboxed' keyboard loading in the DOM!) const ruleHarness = new JSKeyboardInterface({}, MinimalKeymanGlobal); ruleHarness.activeKeyboard = keyboard as JSKeyboard; - assertThrows(() => ruleHarness.processKeystroke(new Mock(), (keyboard as JSKeyboard).constructNullKeyEvent(device)), 'k.KKM is not a function'); + assertThrows(() => ruleHarness.processKeystroke(new SyntheticTextStore(), (keyboard as JSKeyboard).constructNullKeyEvent(device)), 'k.KKM is not a function'); }); }); }); diff --git a/web/src/test/auto/headless/engine/keyboard/mocks.tests.js b/web/src/test/auto/headless/engine/keyboard/mocks.tests.js index b02f259886..eaf0f37a3b 100644 --- a/web/src/test/auto/headless/engine/keyboard/mocks.tests.js +++ b/web/src/test/auto/headless/engine/keyboard/mocks.tests.js @@ -1,13 +1,13 @@ import { assert } from 'chai'; -import { Mock } from 'keyman/engine/keyboard'; +import { SyntheticTextStore } from 'keyman/engine/keyboard'; describe('Mocks', function() { describe('app|les', () => { - const testMock = new Mock('apples', 3); + const testMock = new SyntheticTextStore('apples', 3); it('Cloning with .from()', () => { - assert.deepEqual(Mock.from(testMock), testMock); - assert.notStrictEqual(Mock.from(testMock), testMock); + assert.deepEqual(SyntheticTextStore.from(testMock), testMock); + assert.notStrictEqual(SyntheticTextStore.from(testMock), testMock); }); it('getText', () => { @@ -31,7 +31,7 @@ describe('Mocks', function() { }); it('clearSelection', () => { - let editMock = Mock.from(testMock); + let editMock = SyntheticTextStore.from(testMock); editMock.clearSelection(); assert.equal(editMock.getText(), testMock.getTextBeforeCaret() + testMock.getTextAfterCaret()); @@ -39,7 +39,7 @@ describe('Mocks', function() { assert.equal(editMock.getTextAfterCaret(), testMock.getTextAfterCaret()); assert.isTrue(editMock.isSelectionEmpty()); - let postClear = Mock.from(editMock); + let postClear = SyntheticTextStore.from(editMock); editMock.clearSelection(); // on same object; make sure its internal selection stuff updates correctly! assert.notStrictEqual(postClear, editMock); assert.deepEqual(postClear, editMock); @@ -47,11 +47,11 @@ describe('Mocks', function() { }); describe('app|les and ba|nanas', () => { // selection = 'les and ba' - const testMock = new Mock('apples and bananas', 3, 13); + const testMock = new SyntheticTextStore('apples and bananas', 3, 13); it('Cloning with from()', () => { - assert.deepEqual(Mock.from(testMock), testMock); - assert.notStrictEqual(Mock.from(testMock), testMock); + assert.deepEqual(SyntheticTextStore.from(testMock), testMock); + assert.notStrictEqual(SyntheticTextStore.from(testMock), testMock); }); it('getText', () => { @@ -75,7 +75,7 @@ describe('Mocks', function() { }); it('clearSelection', () => { - let editMock = Mock.from(testMock); + let editMock = SyntheticTextStore.from(testMock); editMock.clearSelection(); assert.equal(editMock.getText(), testMock.getTextBeforeCaret() + testMock.getTextAfterCaret()); @@ -83,7 +83,7 @@ describe('Mocks', function() { assert.equal(editMock.getTextAfterCaret(), testMock.getTextAfterCaret()); assert.isTrue(editMock.isSelectionEmpty()); - let postClear = Mock.from(editMock); + let postClear = SyntheticTextStore.from(editMock); editMock.clearSelection(); // on same object; make sure its internal selection stuff updates correctly! assert.notStrictEqual(postClear, editMock); assert.deepEqual(postClear, editMock); diff --git a/web/src/test/auto/headless/engine/main/headless/inputProcessor.tests.js b/web/src/test/auto/headless/engine/main/headless/inputProcessor.tests.js index d5b8eb1d86..01cfce2780 100644 --- a/web/src/test/auto/headless/engine/main/headless/inputProcessor.tests.js +++ b/web/src/test/auto/headless/engine/main/headless/inputProcessor.tests.js @@ -6,7 +6,7 @@ const require = createRequire(import.meta.url); import { InputProcessor } from 'keyman/engine/main'; import { JSKeyboardInterface } from 'keyman/engine/js-processor'; -import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardTest } from '@keymanapp/recorder-core'; @@ -104,7 +104,7 @@ describe('InputProcessor', function() { it('with minimal context (no fat-fingers)', function() { this.timeout(32); // ms let core = new InputProcessor(device); - let context = new Mock("", 0); + let context = new SyntheticTextStore("", 0); core.keyboardProcessor.keyboardInterface = keyboardWithHarness; let keyboard = keyboardWithHarness.activeKeyboard; @@ -118,7 +118,7 @@ describe('InputProcessor', function() { it('with extremely long context (' + KMWString.length(coreSourceCode) + ' chars, no fat-fingers)', function() { // Assumes no SMP chars in the source, which is fine. - let context = new Mock(coreSourceCode, KMWString.length(coreSourceCode)); + let context = new SyntheticTextStore(coreSourceCode, KMWString.length(coreSourceCode)); this.timeout(500); // 500 ms, excluding text import. // These often run on VMs, so we'll be a bit generous. @@ -141,7 +141,7 @@ describe('InputProcessor', function() { it('with minimal context (with fat-fingers)', function() { this.timeout(32); // ms let core = new InputProcessor(device); - let context = new Mock("", 0); + let context = new SyntheticTextStore("", 0); core.keyboardProcessor.keyboardInterface = keyboardWithHarness; let keyboard = keyboardWithHarness.activeKeyboard; @@ -156,7 +156,7 @@ describe('InputProcessor', function() { it('with extremely long context (' + KMWString.length(coreSourceCode) + ' chars, with fat-fingers)', function() { // Assumes no SMP chars in the source, which is fine. - let context = new Mock(coreSourceCode, KMWString.length(coreSourceCode)); + let context = new SyntheticTextStore(coreSourceCode, KMWString.length(coreSourceCode)); this.timeout(500); // 500 ms, excluding text import. // These often run on VMs, so we'll be a bit generous. @@ -202,7 +202,7 @@ describe('InputProcessor', function() { it(testSet.msg ?? 'test', function() { this.timeout(32); // ms let core = new InputProcessor(device); - let context = new Mock("", 0); + let context = new SyntheticTextStore("", 0); core.keyboardProcessor.keyboardInterface = keyboardWithHarness; let keyboard = keyboardWithHarness.activeKeyboard; diff --git a/web/src/test/auto/headless/engine/main/headless/languageProcessor.tests.js b/web/src/test/auto/headless/engine/main/headless/languageProcessor.tests.js index 4fc2b0d9bd..a8b524f6b2 100644 --- a/web/src/test/auto/headless/engine/main/headless/languageProcessor.tests.js +++ b/web/src/test/auto/headless/engine/main/headless/languageProcessor.tests.js @@ -2,7 +2,7 @@ import { assert } from 'chai'; import { LanguageProcessor, TranscriptionCache } from 'keyman/engine/main'; import { SourcemappedWorker as LMWorker } from "@keymanapp/lexical-model-layer/node"; -import { Mock } from 'keyman/engine/keyboard'; +import { SyntheticTextStore } from 'keyman/engine/keyboard'; /* * Unit tests for the Dummy prediction model. @@ -110,7 +110,7 @@ describe('LanguageProcessor', function() { }); it("generates the expected prediction set", function(done) { - let contextSource = new Mock("li", 2); + let contextSource = new SyntheticTextStore("li", 2); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { @@ -147,7 +147,7 @@ describe('LanguageProcessor', function() { describe("does not alter casing when input is lowercased", function() { it("when input is fully lowercased", function(done) { - let contextSource = new Mock("li", 2); + let contextSource = new SyntheticTextStore("li", 2); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { @@ -164,7 +164,7 @@ describe('LanguageProcessor', function() { }); it("when input has non-initial uppercased letters", function(done) { - let contextSource = new Mock("lI", 2); + let contextSource = new SyntheticTextStore("lI", 2); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { @@ -182,7 +182,7 @@ describe('LanguageProcessor', function() { }); it("unless the suggestion has uppercased letters", function(done) { - let contextSource = new Mock("i", 1); + let contextSource = new SyntheticTextStore("i", 1); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { @@ -201,7 +201,7 @@ describe('LanguageProcessor', function() { describe("uppercases suggestions when input is fully capitalized ", function() { it("for suggestions with default casing (== 'lower')", function(done) { - let contextSource = new Mock("LI", 2); + let contextSource = new SyntheticTextStore("LI", 2); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { @@ -219,7 +219,7 @@ describe('LanguageProcessor', function() { }); it("for precapitalized suggestions", function(done) { - let contextSource = new Mock("I", 1); + let contextSource = new SyntheticTextStore("I", 1); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { @@ -239,7 +239,7 @@ describe('LanguageProcessor', function() { describe("initial-cases suggestions when input uses initial casing ", function() { describe("when input is a single capitalized letter", function() { it("for suggestions with default casing (== 'lower')", function(done) { - let contextSource = new Mock("L", 1); + let contextSource = new SyntheticTextStore("L", 1); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { @@ -259,7 +259,7 @@ describe('LanguageProcessor', function() { describe("input length > 1", function() { it("for suggestions with default casing (== 'lower')", function(done) { - let contextSource = new Mock("Li", 2); + let contextSource = new SyntheticTextStore("Li", 2); let transcription = contextSource.buildTranscriptionFrom(contextSource, null, null); languageProcessor.loadModel(modelSpec).then(function() { diff --git a/web/src/tools/testing/recorder-core/src/index.ts b/web/src/tools/testing/recorder-core/src/index.ts index b1073d09cc..f74639f207 100644 --- a/web/src/tools/testing/recorder-core/src/index.ts +++ b/web/src/tools/testing/recorder-core/src/index.ts @@ -1,4 +1,4 @@ -import { KeyDistribution, KeyEvent, type TextStore, Mock } from "keyman/engine/keyboard"; +import { KeyDistribution, KeyEvent, type TextStore, SyntheticTextStore } from "keyman/engine/keyboard"; import Proctor from "./proctor.js"; @@ -219,7 +219,7 @@ export abstract class TestSequence { // Start with an empty TextStore and a fresh KeyboardProcessor. if(!target) { - target = new Mock(); + target = new SyntheticTextStore(); } proctor.before(); diff --git a/web/src/tools/testing/recorder-core/src/nodeProctor.ts b/web/src/tools/testing/recorder-core/src/nodeProctor.ts index 2bf5cc427a..9297e45e84 100644 --- a/web/src/tools/testing/recorder-core/src/nodeProctor.ts +++ b/web/src/tools/testing/recorder-core/src/nodeProctor.ts @@ -8,7 +8,7 @@ import { RecordedSyntheticKeystroke } from "./index.js"; -import { KeyEvent, KeyEventSpec, KeyboardHarness, Mock, TextStore } from "keyman/engine/keyboard"; +import { KeyEvent, KeyEventSpec, KeyboardHarness, SyntheticTextStore, TextStore } from "keyman/engine/keyboard"; import { DeviceSpec } from "@keymanapp/web-utils"; import { JSKeyboardInterface, JSKeyboardProcessor } from 'keyman/engine/js-processor'; @@ -51,7 +51,7 @@ export default class NodeProctor extends Proctor { async simulateSequence(sequence: TestSequence, target?: TextStore): Promise { // Start with an empty TextStore and a fresh KeyboardProcessor. if(!target) { - target = new Mock(); + target = new SyntheticTextStore(); } // Establish a fresh processor, setting its keyboard appropriately for the test.