maint(developer): make TestCompilerCallbacks usage more consistent and simplify

Simplify usage of `TestCompilerCallbacks` by making it responsible for
the `beforeEach` and `afterEach` incantations itself. There are a couple
of more complex usages of `TestCompilerCallbacks` which have been
excluded from this change on purpose.

Renamed `testCallbacks` to `callbacks` in the one place where it was
different.

Hoist @types/node and @types/mocha because inconsistent versions of
@types/mocha were causing compiler errors with this change.

Also added a cast to `fs.readFileSync` to `Uint8Array` to eliminate
compiler warnings/errors in test files.

Fixes: #15654
Test-bot: skip
This commit is contained in:
Marc Durdin 2026-03-03 16:44:06 +01:00
parent 0e0b858269
commit 529a49431e
39 changed files with 156 additions and 238 deletions

View file

@ -36,8 +36,6 @@
"restructure": "3.0.1"
},
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"ajv": "^8.12.0",
"ajv-cli": "^5.0.0",
"ajv-formats": "^2.1.1",

View file

@ -5,6 +5,7 @@ import { CompilerEvent, CompilerCallbacks, CompilerPathCallbacks, CompilerFileSy
CompilerFileSystemAsyncCallbacks,
CompilerErrorSeverity} from '@keymanapp/developer-utils';
import { fileURLToPath } from 'url';
import { Suite } from 'mocha';
const { TEST_SAVE_FIXTURES } = process.env;
@ -12,16 +13,27 @@ const { TEST_SAVE_FIXTURES } = process.env;
* A CompilerCallbacks implementation for testing
*/
export class TestCompilerCallbacks implements CompilerCallbacks {
/* TestCompilerCallbacks */
private readonly suite: Suite;
messages: CompilerEvent[] = [];
readonly _net: TestCompilerNetAsyncCallbacks;
readonly _fsAsync: DefaultCompilerFileSystemAsyncCallbacks = new DefaultCompilerFileSystemAsyncCallbacks(this);
constructor(basePath?: string) {
constructor(suite?: Suite, basePath?: string) {
if(basePath) {
this._net = new TestCompilerNetAsyncCallbacks(basePath);
}
this.suite = suite;
if(this.suite) {
const _this = this;
this.suite.beforeEach(function() {
_this.clear();
});
this.suite.afterEach(function() {
if(this.currentTest?.isFailed()) {
_this.printMessages();
}
})
}
}
clear() {
@ -55,7 +67,7 @@ export class TestCompilerCallbacks implements CompilerCallbacks {
loadFile(filename: string): Uint8Array {
try {
return fs.readFileSync(filename);
return fs.readFileSync(filename) as Uint8Array;
} catch(e) {
if (e.code === 'ENOENT') {
return null;
@ -162,7 +174,7 @@ class TestCompilerNetAsyncCallbacks implements CompilerNetAsyncCallbacks {
// missing file, this is okay
return null;
}
const data: Uint8Array = fs.readFileSync(p);
const data = fs.readFileSync(p) as Uint8Array;
return data;
}

View file

@ -6,13 +6,15 @@ import { KPJFileReader } from "../../src/types/kpj/kpj-file-reader.js";
import { KeymanDeveloperProjectFile10, KeymanDeveloperProjectType } from '../../src/types/kpj/keyman-developer-project.js';
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
const callbacks = new TestCompilerCallbacks();
describe('kpj-file-reader', function () {
const callbacks = new TestCompilerCallbacks(this);
it('kpj-file-reader should read a valid file', async function() {
const kpjPath = 'khmer_angkor.kpj';
const path = makePathToFixture('kpj', kpjPath);
const input = fs.readFileSync(path);
const input = fs.readFileSync(path) as Uint8Array;
const reader = new KPJFileReader(callbacks);
const kpj = reader.read(input);
reader.validate(kpj);
@ -124,7 +126,7 @@ describe('kpj-file-reader', function () {
it('should load a v1.0 keyboard project with missing <File>', async function() {
const path = makePathToFixture('kpj', 'project-missing-file', 'project_missing_file.kpj');
const input = fs.readFileSync(path);
const input = fs.readFileSync(path) as Uint8Array;
const reader = new KPJFileReader(callbacks);
const kpj = reader.read(input);
reader.validate(kpj);
@ -140,7 +142,7 @@ describe('kpj-file-reader', function () {
it('should load a v1.0 keyboard project with missing <Files>', async function() {
const path = makePathToFixture('kpj', 'project-missing-file', 'project_missing_files.kpj');
const input = fs.readFileSync(path);
const input = fs.readFileSync(path) as Uint8Array;
const reader = new KPJFileReader(callbacks);
const kpj = reader.read(input);
reader.validate(kpj);

View file

@ -29,8 +29,6 @@
},
"devDependencies": {
"@keymanapp/resources-gosh": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"

View file

@ -14,17 +14,7 @@ import { KeymanProjectCopier } from '../src/KeymanProjectCopier.js';
import { makePathToFixture } from './helpers/index.js';
describe('CopierMessages', function () {
const callbacks = new TestCompilerCallbacks(makePathToFixture('online'));
this.beforeEach(function() {
callbacks.clear();
});
this.afterEach(function() {
if(this.currentTest?.isFailed()) {
callbacks.printMessages();
}
});
const callbacks = new TestCompilerCallbacks(this, makePathToFixture('online'));
it('should have a valid CopierMessages object', function() {
return verifyCompilerMessagesObject(CopierMessages, CompilerErrorNamespace.Copier);

View file

@ -23,7 +23,7 @@ function normalizeNewLine(s: string): string {
}
describe('KeymanProjectCopier', function() {
const callbacks = new TestCompilerCallbacks(makePathToFixture('online'));
const callbacks = new TestCompilerCallbacks(this, makePathToFixture('online'));
this.beforeAll(function() {
if(TEST_SAVE_ARTIFACTS) {
@ -32,16 +32,6 @@ describe('KeymanProjectCopier', function() {
}
});
this.beforeEach(function() {
callbacks.clear();
});
this.afterEach(function() {
if(this.currentTest?.isFailed()) {
callbacks.printMessages();
}
});
const tests = [
//

View file

@ -35,6 +35,8 @@ function getFilenames(p: string, base?: string): string[] {
describe('LexicalModelGenerator', function () {
let clock: sinon.SinonFakeTimers;
const callbacks = new TestCompilerCallbacks(this);
before(function() {
// We will always be 12 April 2024 to match test fixtures
clock = sinon.useFakeTimers(new Date(2024, 3, 12));
@ -46,7 +48,6 @@ describe('LexicalModelGenerator', function () {
it('should generate a lexical model from provided options', async function() {
const generator = new LexicalModelGenerator();
const callbacks = new TestCompilerCallbacks();
const opts: GeneratorOptions = {...options};
opts.id = 'sample.en.sample';
opts.targets = [KeymanTargets.KeymanTarget.any];

View file

@ -29,8 +29,6 @@
"@keymanapp/langtags": "*"
},
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"

View file

@ -8,8 +8,6 @@ import { makePathToFixture } from './helpers/index.js';
import { KeyboardInfoCompiler } from '../src/keyboard-info-compiler.js';
import { KeyboardInfoFile } from '../src/keyboard-info-file.js';
const callbacks = new TestCompilerCallbacks();
const KHMER_ANGKOR_JS = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.js');
const KHMER_ANGKOR_KPS = makePathToFixture('khmer_angkor', 'source', 'khmer_angkor.kps');
const KHMER_ANGKOR_KMP = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.kmp');
@ -24,15 +22,7 @@ const KHMER_ANGKOR_SOURCES = {
describe('KeyboardInfoCompilerMessages', function () {
this.beforeEach(function() {
callbacks.clear();
});
this.afterEach(function() {
if(this.currentTest?.isFailed()) {
callbacks.printMessages();
}
})
const callbacks = new TestCompilerCallbacks(this);
it('should have a valid KeyboardInfoCompilerMessages object', function() {
return verifyCompilerMessagesObject(KeyboardInfoCompilerMessages, CompilerErrorNamespace.KeyboardInfoCompiler);

View file

@ -10,18 +10,6 @@ import { KMX, KeymanFileTypes, KeymanTargets, KmpJsonFile } from '@keymanapp/com
import { CompilerCallbacks } from '@keymanapp/developer-utils';
import { KeyboardInfoFile, KeyboardInfoFileLanguage, KeyboardInfoFilePlatform } from './keyboard-info-file.js';
const callbacks = new TestCompilerCallbacks();
beforeEach(function() {
callbacks.clear();
});
afterEach(function() {
if(this.currentTest?.isFailed()) {
callbacks.printMessages();
}
});
const KHMER_ANGKOR_KPJ = makePathToFixture('khmer_angkor', 'khmer_angkor.kpj');
const KHMER_ANGKOR_JS = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.js');
const KHMER_ANGKOR_KPS = makePathToFixture('khmer_angkor', 'source', 'khmer_angkor.kps');
@ -87,6 +75,9 @@ const JAVA_DISPLAY_FONT_INFO = { family: "Java", source: [ JAVA_DISPLAY_FONT ] }
const JAVA_OSK_FONT_INFO = { family: "Java Kbd", source: [ JAVA_OSK_FONT ] };
describe('keyboard-info-compiler', function () {
const callbacks = new TestCompilerCallbacks(this);
it('compile a .keyboard_info file correctly', async function() {
const kpjFilename = KHMER_ANGKOR_KPJ;
const buildKeyboardInfoFilename = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.keyboard_info');
@ -844,6 +835,9 @@ describe('keyboard-info-compiler', function () {
});
describe('fillLanguageMetadata', function() {
const callbacks = new TestCompilerCallbacks(this);
const tests: { bcp47: string, lang: KeyboardInfoFileLanguage, commonScript: string }[] = [
// 'und' language subtag

View file

@ -32,8 +32,6 @@
},
"devDependencies": {
"@keymanapp/developer-test-helpers": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"@types/semver": "^7.3.12",
"@types/sinon": "^10.0.13",
"@types/sinon-chai": "^3.2.9",

View file

@ -11,6 +11,8 @@ const keyboardsDir = __dirname + '/../../../../../common/test/keyboards/';
const baselineDir = keyboardsDir + 'baseline/';
describe('Compiler class', function() {
const callbacks = new TestCompilerCallbacks(this);
it('should throw on failure', async function() {
const compiler = new KmnCompiler();
const callbacks : any = null; // ERROR
@ -25,14 +27,12 @@ describe('Compiler class', function() {
it('should start', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, null));
assert(compiler.verifyInitialized());
});
it('should compile a basic keyboard', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, {saveDebug: true, shouldAddCompilerVersion: false}));
assert(compiler.verifyInitialized());
@ -60,7 +60,6 @@ describe('Compiler class', function() {
it('should build all baseline fixtures', async function() {
this.timeout(10000); // there are quite a few fixtures, sometimes CI agents are slow
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, {saveDebug: true, shouldAddCompilerVersion: false}));
assert(compiler.verifyInitialized());
@ -90,7 +89,6 @@ describe('Compiler class', function() {
it('should compile a keyboard with visual keyboard', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert.isTrue(await compiler.init(callbacks, {
saveDebug: true,
shouldAddCompilerVersion: false,

View file

@ -7,19 +7,14 @@ import { KMX, KmxFileReader } from '@keymanapp/common-types';
describe('Keyboard compiler features', function() {
let compiler: KmnCompiler = null;
let callbacks: TestCompilerCallbacks = null;
const callbacks = new TestCompilerCallbacks(this);
this.beforeAll(async function() {
compiler = new KmnCompiler();
callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, {saveDebug: true}));
assert(compiler.verifyInitialized());
});
beforeEach(function() {
callbacks.clear();
});
// Test each Keyman file version target
const versions = [

View file

@ -7,7 +7,7 @@ import { KmnCompilerMessageRanges, KmnCompilerMessages } from '../src/compiler/k
import { makePathToFixture } from './helpers/index.js';
describe('KmnCompilerMessages', function () {
const callbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
it('should have a valid KmnCompilerMessages object', function() {
return verifyCompilerMessagesObject(KmnCompilerMessages, CompilerErrorNamespace.KmnCompiler);

View file

@ -25,7 +25,7 @@ const generateTestFilenames = (id: string) => ({
});
describe('KeymanWeb Compiler', function() {
const callbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
const kmnCompiler: KmnCompiler = new KmnCompiler();
this.beforeAll(async function() {
@ -35,13 +35,6 @@ describe('KeymanWeb Compiler', function() {
}));
});
this.afterEach(function() {
if(this.currentTest?.isFailed() || debug) {
callbacks.printMessages();
}
callbacks.clear();
});
it('should compile a complex keyboard', async function() {
await run_test_keyboard(kmnCompiler, 'khmer_angkor');
});

View file

@ -7,7 +7,7 @@ import { KmnCompiler } from '../../src/main.js';
import { CompilerErrorNamespace } from '@keymanapp/developer-utils';
describe('KmwCompilerMessages', function () {
const callbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
it('should have a valid KmwCompilerMessages object', function() {
return verifyCompilerMessagesObject(KmwCompilerMessages, CompilerErrorNamespace.KmwCompiler);

View file

@ -6,6 +6,8 @@ import { KmnCompilerMessages } from '../src/compiler/kmn-compiler-messages.js';
import { compilerErrorFormatCode } from '@keymanapp/developer-utils';
describe('Compiler UnicodeSet function', function() {
const callbacks = new TestCompilerCallbacks(this);
it('should fixup "short" \\u{} escapes', function () {
assert.equal(KmnCompiler.fixNewPattern(`\\u{A}`), `\\u000A`); // "
assert.equal(KmnCompiler.fixNewPattern(`\\u{22}`), `\\u0022`); // "
@ -24,14 +26,12 @@ describe('Compiler UnicodeSet function', function() {
it('should start', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, null));
assert(compiler.verifyInitialized());
});
it('should compile a basic uset', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, null));
assert(compiler.verifyInitialized());
@ -49,7 +49,6 @@ describe('Compiler UnicodeSet function', function() {
});
it('should compile a more complex uset', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, null));
assert(compiler.verifyInitialized());
@ -69,7 +68,6 @@ describe('Compiler UnicodeSet function', function() {
});
it('should compile an even more complex uset', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, null));
assert(compiler.verifyInitialized());
@ -96,7 +94,6 @@ describe('Compiler UnicodeSet function', function() {
});
it('should fail in various ways', async function() {
const compiler = new KmnCompiler();
const callbacks = new TestCompilerCallbacks();
assert(await compiler.init(callbacks, null));
assert(compiler.verifyInitialized());
// map from string to failing error

View file

@ -35,8 +35,6 @@
"@keymanapp/developer-test-helpers": "*",
"@keymanapp/resources-gosh": "*",
"@types/common-tags": "^1.8.4",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"@types/semver": "^7.3.12",
"abnf": "^4.3.1",
"c8": "^7.12.0",

View file

@ -34,8 +34,6 @@
"@keymanapp/developer-utils": "*"
},
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"

View file

@ -6,13 +6,9 @@ import { makePathToFixture } from './helpers/index.js';
import { ModelInfoCompiler } from '../src/model-info-compiler.js';
import { KmpCompiler } from '@keymanapp/kmc-package';
const callbacks = new TestCompilerCallbacks();
beforeEach(function() {
callbacks.clear();
});
describe('model-info-compiler', function () {
const callbacks = new TestCompilerCallbacks(this);
it('compile a .model_info file correctly', async function() {
const kpjFilename = makePathToFixture('sil.cmo.bw', 'sil.cmo.bw.model.kpj');
const kpsFilename = makePathToFixture('sil.cmo.bw', 'source', 'sil.cmo.bw.model.kps');

View file

@ -37,8 +37,6 @@
"devDependencies": {
"@keymanapp/developer-test-helpers": "*",
"@keymanapp/models-templates": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"esbuild": "^0.25.0"

View file

@ -7,7 +7,7 @@ import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
import { LexicalModelTypes } from '@keymanapp/common-types';
describe('LexicalModelCompiler - pseudoclosure compilation + use', function () {
const callbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
const MODEL_ID = 'example.qaa.trivial';
const PATH = makePathToFixture(MODEL_ID);

View file

@ -7,7 +7,7 @@ import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
import { KeymanFileTypes } from '@keymanapp/common-types';
describe('LexicalModelCompiler', function () {
const callbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
this.timeout(5000);

View file

@ -11,10 +11,7 @@ import { TrieModel } from '@keymanapp/models-templates';
import { LexicalModelTypes } from '@keymanapp/common-types';
describe('LexicalModelCompiler', function () {
const callbacks = new TestCompilerCallbacks();
this.beforeEach(function() {
callbacks.clear();
});
const callbacks = new TestCompilerCallbacks(this);
describe('#generateLexicalModelCode', function () {
it('should compile a trivial word list', async function () {

View file

@ -8,17 +8,7 @@ import { makePathToFixture } from './helpers/index.js';
describe('ModelCompilerMessages', function () {
const callbacks = new TestCompilerCallbacks();
this.beforeEach(function() {
callbacks.clear();
});
this.afterEach(function() {
if(this.currentTest?.isFailed()) {
callbacks.printMessages();
}
});
const callbacks = new TestCompilerCallbacks(this);
it('should have a valid ModelCompilerMessages object', function() {
return verifyCompilerMessagesObject(ModelCompilerMessages, CompilerErrorNamespace.ModelCompiler);

View file

@ -22,11 +22,10 @@ const SENCOTEN_WORDLIST = {
describe('parsing a word list', function () {
const testCallbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
beforeEach(function () {
testCallbacks.clear();
setCompilerCallbacks(testCallbacks);
setCompilerCallbacks(callbacks);
});
afterEach(function () {
@ -43,12 +42,12 @@ describe('parsing a word list', function () {
const withoutBOM: WordList = {};
parseWordListFromContents(withoutBOM, file);
assert.deepEqual(withoutBOM, expected, "expected regular file to parse properly");
assert.isEmpty(testCallbacks.messages);
assert.isEmpty(callbacks.messages);
const withBOM: WordList = {};
parseWordListFromContents(withBOM, `${BOM}${file}`)
assert.deepEqual(withBOM, expected, "expected BOM to be ignored");
assert.isEmpty(testCallbacks.messages);
assert.isEmpty(callbacks.messages);
});
it('should read word lists in UTF-8', function () {
@ -58,7 +57,7 @@ describe('parsing a word list', function () {
parseWordListFromFilename(wordlist, filename);
assert.deepEqual(wordlist, SENCOTEN_WORDLIST);
assert.isEmpty(testCallbacks.messages);
assert.isEmpty(callbacks.messages);
});
it('should read word lists in UTF-16 little-endian (with BOM)', function () {
@ -69,7 +68,7 @@ describe('parsing a word list', function () {
parseWordListFromFilename(wordlist, filename);
assert.deepEqual(wordlist, SENCOTEN_WORDLIST);
assert.isEmpty(testCallbacks.messages);
assert.isEmpty(callbacks.messages);
});
it('should NOT read word lists in UTF-16 big-endian (with BOM)', function () {
@ -106,22 +105,22 @@ describe('parsing a word list', function () {
assert.deepEqual(repeatedWords, expected);
assert.lengthOf(testCallbacks.messages, 4);
assert.lengthOf(callbacks.messages, 4);
// hello has been seen multiple times:
assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
assert.isTrue(callbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
// helló and hello + U+0301 have both been seen:
assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
assert.isTrue(callbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
// Let's parse another file:
testCallbacks.clear();
callbacks.clear();
// Now, parse a DIFFERENT file, but with an NFD entry.
parseWordListFromContents(repeatedWords, "hello\u0301\t5\n");
assert.lengthOf(testCallbacks.messages, 1);
assert.lengthOf(callbacks.messages, 1);
// hello + U+0301 (NFD) has been seen, but...
assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
assert.isTrue(callbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
// BUT! We have not seen a duplicate **within the same file**
assert.isFalse(testCallbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
assert.isFalse(callbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
assert.deepEqual(repeatedWords, {
hello: expected['hello'],

View file

@ -6,12 +6,13 @@ import { makePathToFixture, compileModelSourceCode } from './helpers/index.js';
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
describe('LexicalModelCompiler', function () {
const callbacks = new TestCompilerCallbacks(this);
describe('specifying punctuation', function () {
const MODEL_ID = 'example.qaa.trivial';
const PATH = makePathToFixture(MODEL_ID);
it('should compile punctuation into the generated code', async function () {
const callbacks = new TestCompilerCallbacks();
const compiler = new LexicalModelCompiler();
assert.isTrue(await compiler.init(callbacks, null));

View file

@ -36,8 +36,6 @@
},
"devDependencies": {
"@keymanapp/developer-test-helpers": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"

View file

@ -10,15 +10,10 @@ import { makePathToFixture } from './helpers/index.js';
import { KmpCompiler } from '../src/compiler/kmp-compiler.js';
import { CompilerErrorNamespace, CompilerOptions } from '@keymanapp/developer-utils';
const callbacks = new TestCompilerCallbacks();
describe('PackageCompilerMessages', function () {
this.afterEach(function() {
if(this.currentTest.isFailed()) {
callbacks.printMessages();
}
});
const callbacks = new TestCompilerCallbacks(this);
it('should have a valid PackageCompilerMessages object', function() {
return verifyCompilerMessagesObject(PackageCompilerMessages, CompilerErrorNamespace.PackageCompiler);

View file

@ -21,22 +21,14 @@ describe('KmpCompiler', function () {
'example.qaa.sencoten',
'withfolders.qaa.sencoten',
];
const callbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
let kmpCompiler: KmpCompiler = null;
this.beforeAll(async function() {
callbacks.clear();
kmpCompiler = new KmpCompiler();
assert.isTrue(await kmpCompiler.init(callbacks, null));
});
this.afterEach(function() {
if(this.currentTest?.isFailed()) {
callbacks.printMessages();
}
callbacks.clear();
});
for (const modelID of MODELS) {
const kpsPath = modelID.includes('withfolders') ?
makePathToFixture(modelID, 'source', `${modelID}.model.kps`) : makePathToFixture(modelID, `${modelID}.model.kps`);

View file

@ -11,6 +11,7 @@ import { makePathToFixture } from './helpers/index.js';
// test results documented below.
describe('package versioning', function () {
const callbacks = new TestCompilerCallbacks(this);
const cases: [string,string][] = [
['test-single-version-1-package', 'test1.kps'],
@ -33,7 +34,6 @@ describe('package versioning', function () {
for(const [ caseTitle, filename ] of cases) {
it(caseTitle, async function () {
const callbacks = new TestCompilerCallbacks();
const kmpCompiler = new KmpCompiler();
assert.isTrue(await kmpCompiler.init(callbacks, null));

View file

@ -9,6 +9,8 @@ import { makePathToFixture } from './helpers/index.js';
import { WindowsPackageInstallerCompiler, WindowsPackageInstallerSources } from '../src/compiler/windows-package-installer-compiler.js';
describe('WindowsPackageInstallerCompiler', function () {
const callbacks = new TestCompilerCallbacks(this);
it(`should build an SFX archive`, async function () {
this.timeout(10000); // this test can take a little while to run
@ -22,7 +24,6 @@ describe('WindowsPackageInstallerCompiler', function () {
appName: 'Testing',
};
const callbacks = new TestCompilerCallbacks();
const compiler = new WindowsPackageInstallerCompiler();
assert.isTrue(await compiler.init(callbacks, {sources}));
@ -44,7 +45,7 @@ describe('WindowsPackageInstallerCompiler', function () {
const zipBuffer = sfxBuffer.slice(setupExeSize);
// Verify setup.exe sfx loader
const setupExeFixture = fs.readFileSync(sources.setupExeFilename);
const setupExeFixture = fs.readFileSync(sources.setupExeFilename) as Uint8Array;
assert.deepEqual(setupExe, setupExeFixture);
// Load the zip from the buffer
@ -68,7 +69,7 @@ khmer_angkor.kmp
assert.equal(setupInf.trim(), setupInfFixture.trim());
const verifyFile = async (filename: string) => {
const fixture = fs.readFileSync(filename);
const fixture = fs.readFileSync(filename) as Uint8Array;
const file = await zipFile.file(path.basename(filename)).async('uint8array');
assert.deepEqual(file, fixture, `File in zip '${filename}' did not match fixture`);
};

View file

@ -53,8 +53,6 @@
],
"devDependencies": {
"@sentry/cli": "^2.31.0",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"esbuild": "^0.25.0",
"typescript": "^5.4.5"

View file

@ -29,9 +29,7 @@
"@keymanapp/keyman-version": "*",
"@keymanapp/resources-gosh": "*",
"@types/express": "^4.17.13",
"@types/mocha": "^9.1.0",
"@types/multer": "^1.4.12",
"@types/node": "^20.4.1",
"@types/ws": "^8.2.2",
"copyfiles": "^2.4.1",
"node-gyp": "^10.2.0",

161
package-lock.json generated
View file

@ -47,6 +47,7 @@
"@microsoft/api-documenter": "^7.28.0",
"@microsoft/api-extractor": "^7.47.3",
"@types/chai": "^4.3.14",
"@types/mocha": "^10.0.10",
"@types/node": "^20.4.1",
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@web/dev-server-esbuild": "^1.0.2",
@ -149,8 +150,6 @@
"restructure": "3.0.1"
},
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"ajv": "^8.12.0",
"ajv-cli": "^5.0.0",
"ajv-formats": "^2.1.1",
@ -160,11 +159,6 @@
"typescript": "^5.4.5"
}
},
"common/web/types/node_modules/@types/mocha": {
"version": "5.2.7",
"dev": true,
"license": "MIT"
},
"common/web/types/node_modules/ansi-styles": {
"version": "3.2.1",
"dev": true,
@ -285,8 +279,6 @@
},
"devDependencies": {
"@sentry/cli": "^2.31.0",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"esbuild": "^0.25.0",
"typescript": "^5.4.5"
@ -302,19 +294,11 @@
},
"devDependencies": {
"@keymanapp/resources-gosh": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"
}
},
"developer/src/kmc-analyze/node_modules/@types/mocha": {
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
"dev": true
},
"developer/src/kmc-analyze/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@ -581,19 +565,11 @@
"@keymanapp/langtags": "*"
},
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"
}
},
"developer/src/kmc-keyboard-info/node_modules/@types/mocha": {
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
"dev": true
},
"developer/src/kmc-keyboard-info/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@ -666,8 +642,6 @@
},
"devDependencies": {
"@keymanapp/developer-test-helpers": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"@types/semver": "^7.3.12",
"@types/sinon": "^10.0.13",
"@types/sinon-chai": "^3.2.9",
@ -677,12 +651,6 @@
"typescript": "^5.4.5"
}
},
"developer/src/kmc-kmn/node_modules/@types/mocha": {
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
"dev": true
},
"developer/src/kmc-kmn/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@ -759,8 +727,6 @@
"@keymanapp/developer-test-helpers": "*",
"@keymanapp/resources-gosh": "*",
"@types/common-tags": "^1.8.4",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"@types/semver": "^7.3.12",
"abnf": "^4.3.1",
"c8": "^7.12.0",
@ -770,12 +736,6 @@
"typescript": "^5.4.5"
}
},
"developer/src/kmc-ldml/node_modules/@types/mocha": {
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
"dev": true
},
"developer/src/kmc-ldml/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@ -849,8 +809,6 @@
"devDependencies": {
"@keymanapp/developer-test-helpers": "*",
"@keymanapp/models-templates": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"esbuild": "^0.25.0"
@ -864,18 +822,11 @@
"@keymanapp/developer-utils": "*"
},
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"
}
},
"developer/src/kmc-model-info/node_modules/@types/mocha": {
"version": "5.2.7",
"dev": true,
"license": "MIT"
},
"developer/src/kmc-model-info/node_modules/ansi-styles": {
"version": "3.2.1",
"dev": true,
@ -932,11 +883,6 @@
"node": ">=4"
}
},
"developer/src/kmc-model/node_modules/@types/mocha": {
"version": "5.2.7",
"dev": true,
"license": "MIT"
},
"developer/src/kmc-model/node_modules/ansi-styles": {
"version": "3.2.1",
"dev": true,
@ -1004,18 +950,11 @@
},
"devDependencies": {
"@keymanapp/developer-test-helpers": "*",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"typescript": "^5.4.5"
}
},
"developer/src/kmc-package/node_modules/@types/mocha": {
"version": "5.2.7",
"dev": true,
"license": "MIT"
},
"developer/src/kmc-package/node_modules/ansi-styles": {
"version": "3.2.1",
"dev": true,
@ -1072,11 +1011,6 @@
"node": ">=4"
}
},
"developer/src/kmc/node_modules/@types/mocha": {
"version": "5.2.7",
"dev": true,
"license": "MIT"
},
"developer/src/kmc/node_modules/ansi-styles": {
"version": "3.2.1",
"license": "MIT",
@ -1162,9 +1096,7 @@
"@keymanapp/keyman-version": "*",
"@keymanapp/resources-gosh": "*",
"@types/express": "^4.17.13",
"@types/mocha": "^9.1.0",
"@types/multer": "^1.4.12",
"@types/node": "^20.4.1",
"@types/ws": "^8.2.2",
"copyfiles": "^2.4.1",
"node-gyp": "^10.2.0",
@ -1175,11 +1107,6 @@
"node-hide-console-window": "^2.2.0"
}
},
"developer/src/server/node_modules/@types/mocha": {
"version": "9.1.1",
"dev": true,
"license": "MIT"
},
"developer/src/server/node_modules/@types/multer": {
"version": "1.4.12",
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz",
@ -3480,7 +3407,9 @@
"license": "MIT"
},
"node_modules/@types/mocha": {
"version": "7.0.2",
"version": "10.0.10",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz",
"integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==",
"dev": true,
"license": "MIT"
},
@ -4679,6 +4608,15 @@
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
"license": "MIT"
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/argparse": {
"version": "2.0.1",
"dev": true,
@ -5842,6 +5780,15 @@
"version": "1.0.3",
"license": "MIT"
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -9846,6 +9793,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true,
"license": "ISC",
"optional": true,
"peer": true
},
"node_modules/make-fetch-happen": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz",
@ -12939,6 +12895,47 @@
"typescript": ">=4.2.0"
}
},
"node_modules/ts-node": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
"integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"source-map-support": "^0.5.17",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"typescript": ">=2.7"
}
},
"node_modules/ts-node/node_modules/diff": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"dev": true,
"license": "BSD-3-Clause",
"optional": true,
"peer": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/tsc-watch": {
"version": "4.6.2",
"dev": true,
@ -13779,6 +13776,18 @@
"node": ">= 4.0.0"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"engines": {
"node": ">=6"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"dev": true,
@ -14097,7 +14106,6 @@
"devDependencies": {
"@keymanapp/common-types": "*",
"@keymanapp/web-utils": "*",
"@types/mocha": "^7.0.2",
"c8": "^7.12.0",
"typescript": "^5.4.5"
}
@ -14115,7 +14123,6 @@
"devDependencies": {
"@keymanapp/common-types": "*",
"@keymanapp/resources-gosh": "*",
"@types/mocha": "^7.0.2",
"c8": "^7.12.0",
"typescript": "^5.4.5"
}

View file

@ -5,6 +5,7 @@
"@microsoft/api-documenter": "^7.28.0",
"@microsoft/api-extractor": "^7.47.3",
"@types/chai": "^4.3.14",
"@types/mocha": "^10.0.10",
"@types/node": "^20.4.1",
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@web/dev-server-esbuild": "^1.0.2",

View file

@ -53,7 +53,6 @@
"devDependencies": {
"@keymanapp/common-types": "*",
"@keymanapp/web-utils": "*",
"@types/mocha": "^7.0.2",
"c8": "^7.12.0",
"typescript": "^5.4.5"
},

View file

@ -56,7 +56,6 @@
"devDependencies": {
"@keymanapp/common-types": "*",
"@keymanapp/resources-gosh": "*",
"@types/mocha": "^7.0.2",
"c8": "^7.12.0",
"typescript": "^5.4.5"
},

View file

@ -22,11 +22,10 @@ global.keyman = {}; // So that keyboard-based checks against the global `keyman`
// Test the KeyboardProcessor interface.
describe('LanguageProcessor', function() {
let languageProcessor;
const callbacks = new TestCompilerCallbacks();
const callbacks = new TestCompilerCallbacks(this);
beforeEach(function() {
languageProcessor = new LanguageProcessor(LMWorker, new TranscriptionCache());
callbacks.clear();
});
afterEach(function() {