Merge pull request #15220 from keymanapp/refactor/web/corekbdproctests

refactor(web): make core adapter and processor tests headless

Also improve Core Adapter to detect if we're running in a browser or on node.js and load the appropriate km-core module.

Follow-up-of: #13993
This commit is contained in:
Eberhard Beilharz 2025-11-27 13:09:41 +01:00 committed by GitHub
commit 43ec5c28fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 33 additions and 37 deletions

View file

@ -103,9 +103,6 @@ build_tests_action() {
builder_echo "Copying some files"
mkdir -p "${KEYMAN_ROOT}/web/build/test/dom/cases/core-adapter/import/core/"
cp "${KEYMAN_ROOT}/web/src/engine/src/core-adapter/import/core/keymancore.d.ts" "${KEYMAN_ROOT}/web/build/test/dom/cases/core-adapter/import/core/"
for dir in \
"${KEYMAN_ROOT}/web/build/test/dom/cases"/*/ \
"${KEYMAN_ROOT}/web/build/test/integrated/" \

View file

@ -44,6 +44,7 @@ copy_deps() {
mkdir -p "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"
cp "${KEYMAN_ROOT}/core/build/wasm/${BUILDER_CONFIGURATION}/src/keymancore.d.ts" "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"
cp "${KEYMAN_ROOT}/core/build/wasm/${BUILDER_CONFIGURATION}/src/"km-core{.js,.wasm} "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"
cp "${KEYMAN_ROOT}/core/build/wasm/${BUILDER_CONFIGURATION}/src/"km-core-node{.mjs,.wasm} "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"
cp "${KEYMAN_ROOT}/common/resources/fonts/keymanweb-osk.ttf" "${KEYMAN_ROOT}/web/src/resources/osk/"
}

View file

@ -49,8 +49,14 @@ export class KM_Core {
return this.km_core;
}
private static isNode() {
// from https://stackoverflow.com/a/31456668
return (typeof process !== "undefined" && process?.versions?.node);
}
public static async createCoreProcessor(baseurl: string): Promise<KMXCoreModule> {
const module = await import(baseurl + '/km-core.js');
const coreModuleName = this.isNode() ? 'km-core-node.mjs' : 'km-core.js';
const module = await import(`${baseurl}/${coreModuleName}`);
const createCoreProcessor = module.default;
const km_core = createCoreProcessor({
locateFile: function (path: string, scriptDirectory: string) {

View file

@ -1,4 +1,3 @@
// import { BrowserConfiguration, ContextManager } from 'keyman/app/browser';
import { ContextManager } from 'keyman/app/browser';
import { textStoreForElement } from 'keyman/engine/attachment';
import { TextAreaElementTextStore } from 'keyman/engine/element-text-stores';

View file

@ -82,15 +82,3 @@ export class DynamicElements {
return editable.id;
}
}
export const coreurl = '/build/engine/obj/core-adapter/import/core';
export async function loadKeyboardBlob(uri: string) {
const response = await fetch(uri);
if (!response.ok) {
throw new Error(`HTTP ${response.status} ${response.statusText}`);
}
const buffer = await response.arrayBuffer();
return new Uint8Array(buffer);
}

View file

@ -58,16 +58,6 @@ export default {
// Relative, from the containing package.json
files: ['web/build/test/dom/cases/browser/**/*.tests.mjs']
},
{
name: 'engine/core-adapter',
// Relative, from the containing package.json
files: ['web/src/test/auto/dom/cases/core-adapter/*.tests.ts']
},
{
name: 'engine/core-processor',
// Relative, from the containing package.json
files: ['web/src/test/auto/dom/cases/core-processor/*.tests.ts']
},
{
name: 'engine/dom-utils',
// Relative, from the containing package.json

View file

@ -1,6 +1,10 @@
/*
* Keyman is copyright (C) SIL Global. MIT License.
*/
import { assert } from 'chai';
import { KM_Core, KM_CORE_STATUS } from 'keyman/engine/core-adapter';
import { coreurl, loadKeyboardBlob } from '../../test_utils.js';
import { coreurl, loadKeyboardBlob } from '../loadKeyboardHelper.js';
// Test the KM_Core interface.
describe('KM_Core', function () {

View file

@ -5,23 +5,21 @@
import { assert } from 'chai';
import sinon from 'sinon';
import { KM_Core, km_core_context, km_core_keyboard, km_core_state, KM_CORE_CT, KM_CORE_STATUS, km_core_context_items } from 'keyman/engine/core-adapter';
import { coreurl, loadKeyboardBlob } from '../../test_utils.js';
import { coreurl, loadKeyboardBlob } from '../loadKeyboardHelper.js';
import { Deadkey, SyntheticTextStore } from 'keyman/engine/keyboard';
import { CoreKeyboardProcessor } from 'keyman/engine/core-processor';
// TODO-web-core: These tests would run headless if we'd additionally build WASM for node
describe('CoreKeyboardProcessor', function () {
const loadKeyboard = async function (name: string): Promise<km_core_keyboard> {
const blob = await loadKeyboardBlob(name)
const loadKeyboard = function (name: string): km_core_keyboard {
const blob = loadKeyboardBlob(name);
const result = KM_Core.instance.keyboard_load_from_blob(name, blob);
assert.equal(result.status, 0);
assert.isOk(result.object);
return result.object;
};
const createState = async function (keyboardName: string): Promise<km_core_state> {
const keyboard = await loadKeyboard(keyboardName);
const createState = function (keyboardName: string): km_core_state {
const keyboard = loadKeyboard(keyboardName);
const state = KM_Core.instance.state_create(keyboard, []);
assert.equal(state.status, 0);
assert.isOk(state.object);
@ -52,7 +50,7 @@ describe('CoreKeyboardProcessor', function () {
beforeEach(async function () {
coreProcessor = new CoreKeyboardProcessor();
await coreProcessor.init(coreurl);
state = await createState('/common/test/resources/keyboards/test_8568_deadkeys.kmx');
state = createState('/common/test/resources/keyboards/test_8568_deadkeys.kmx');
context = KM_Core.instance.state_context(state);
sandbox = sinon.createSandbox();
Deadkey.ordinalSeed = 0;
@ -133,7 +131,7 @@ describe('CoreKeyboardProcessor', function () {
beforeEach(async function () {
coreProcessor = new CoreKeyboardProcessor();
await coreProcessor.init(coreurl);
state = await createState('/common/test/resources/keyboards/test_8568_deadkeys.kmx');
state = createState('/common/test/resources/keyboards/test_8568_deadkeys.kmx');
context = KM_Core.instance.state_context(state);
});

View file

@ -0,0 +1,13 @@
/*
* Keyman is copyright (C) SIL Global. MIT License.
*/
import fs from 'node:fs';
const KEYMAN_ROOT = process.env['KEYMAN_ROOT'];
export const coreurl = `${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core`;
export function loadKeyboardBlob(filename: string) {
const data = fs.readFileSync(`${KEYMAN_ROOT}${filename}`, null);
return new Uint8Array(data);
}