diff --git a/developer/src/kmc/src/commands/analyze.ts b/developer/src/kmc/src/commands/analyze.ts index 0ee8149d0b..fd6314ec86 100644 --- a/developer/src/kmc/src/commands/analyze.ts +++ b/developer/src/kmc/src/commands/analyze.ts @@ -121,3 +121,10 @@ async function analyzeOskRewritePua(callbacks: CompilerCallbacks, filenames: str return true; }); } + +/** + * these are exported only for unit tests, do not use + */ +export const analyzeUnitTestEndpoints = { + analyzeOskCharUse +}; \ No newline at end of file diff --git a/developer/src/kmc/test/fixtures/analyze/error_unknown_file_format.xxx b/developer/src/kmc/test/fixtures/analyze/error_unknown_file_format.xxx new file mode 100644 index 0000000000..5ae49a58cb --- /dev/null +++ b/developer/src/kmc/test/fixtures/analyze/error_unknown_file_format.xxx @@ -0,0 +1 @@ +This is a file used to test the unknown file format error (see test-infrastructureMessages.ts) \ No newline at end of file diff --git a/developer/src/kmc/test/fixtures/invalid-keyboards/error_file_type_not_recognized.xxx b/developer/src/kmc/test/fixtures/invalid-keyboards/error_file_type_not_recognized.xxx new file mode 100644 index 0000000000..162d8d5f2e --- /dev/null +++ b/developer/src/kmc/test/fixtures/invalid-keyboards/error_file_type_not_recognized.xxx @@ -0,0 +1 @@ +This is a file used to test the unrecognised file type error (see test-infrastructureMessages.ts) \ No newline at end of file diff --git a/developer/src/kmc/test/fixtures/invalid-projects/build b/developer/src/kmc/test/fixtures/invalid-projects/build new file mode 100644 index 0000000000..ce5a9fe3c0 --- /dev/null +++ b/developer/src/kmc/test/fixtures/invalid-projects/build @@ -0,0 +1 @@ +This is a file used to test the cannot create folder error (see test-infrastructureMessages.ts) \ No newline at end of file diff --git a/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__keyboard.kpj b/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__keyboard.kpj new file mode 100644 index 0000000000..c810dc7c33 --- /dev/null +++ b/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__keyboard.kpj @@ -0,0 +1,24 @@ + + + + $PROJECTPATH + False + False + False + keyboard + + + + error_file_type_not_found_kbd_1 + error_file_type_not_found__keyboard.kmn + error_file_type_not_found__keyboard.kmn + 1.0 + .kmn +
+ error_file_type_not_found__keyboard + Copyright (C) Keyman Team +
+
+ +
+
diff --git a/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__model_kps.kpj b/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__model_kps.kpj new file mode 100644 index 0000000000..aa1e55d9ae --- /dev/null +++ b/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__model_kps.kpj @@ -0,0 +1,24 @@ + + + + $PROJECTPATH + False + False + False + lexicalmodel + + + + error_file_type_not_found_mdl_kps_1 + error_file_type_not_found__model_kps.model.ts + error_file_type_not_found__model_kps.model.ts + + .model.ts +
+ error_file_type_not_found__model_kps + Copyright (C) Keyman Team +
+
+ +
+
diff --git a/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__model_ts.kpj b/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__model_ts.kpj new file mode 100644 index 0000000000..3d69834913 --- /dev/null +++ b/developer/src/kmc/test/fixtures/invalid-projects/error_file_type_not_found__model_ts.kpj @@ -0,0 +1,24 @@ + + + + $PROJECTPATH + False + False + False + lexicalmodel + + + + + error_file_type_not_found_mdl_mdl_2 + error_file_type_not_found__model_ts.kps + error_file_type_not_found__model_ts.kps + + .kps +
+ error_file_type_not_found__model_ts + Copyright (C) Keyman Team +
+
+
+
diff --git a/developer/src/kmc/test/fixtures/invalid-projects/error_invalid_project_file.kpj b/developer/src/kmc/test/fixtures/invalid-projects/error_invalid_project_file.kpj new file mode 100644 index 0000000000..e01a746e66 --- /dev/null +++ b/developer/src/kmc/test/fixtures/invalid-projects/error_invalid_project_file.kpj @@ -0,0 +1 @@ +This is a file used to test the invalid project file error (see test-infrastructureMessages.ts) \ No newline at end of file diff --git a/developer/src/kmc/test/fixtures/invalid-projects/error_not_a_project_file.xxx b/developer/src/kmc/test/fixtures/invalid-projects/error_not_a_project_file.xxx new file mode 100644 index 0000000000..f7fff35790 --- /dev/null +++ b/developer/src/kmc/test/fixtures/invalid-projects/error_not_a_project_file.xxx @@ -0,0 +1 @@ +This is a file used to test the not a project file error (see test-infrastructureMessages.ts) \ No newline at end of file diff --git a/developer/src/kmc/test/fixtures/no-source-folder/.gitkeep b/developer/src/kmc/test/fixtures/no-source-folder/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/developer/src/kmc/test/test-infrastructureMessages.ts b/developer/src/kmc/test/test-infrastructureMessages.ts index 2b481fe6c9..6d8da21b31 100644 --- a/developer/src/kmc/test/test-infrastructureMessages.ts +++ b/developer/src/kmc/test/test-infrastructureMessages.ts @@ -4,11 +4,15 @@ import { InfrastructureMessages } from '../src/messages/infrastructureMessages.j import { verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers'; import { makePathToFixture } from './helpers/index.js'; import { NodeCompilerCallbacks } from '../src/util/NodeCompilerCallbacks.js'; -import { CompilerErrorNamespace, CompilerEvent } from '@keymanapp/common-types'; +import { CompilerErrorNamespace, CompilerEvent, KeymanFileTypes } from '@keymanapp/common-types'; import { unitTestEndpoints } from '../src/commands/build.js'; import { KmnCompilerMessages } from '@keymanapp/kmc-kmn'; import { clearOptions } from '@keymanapp/developer-utils'; import { loadProject } from '../src/util/projectLoader.js'; +import { defaultCompilerOptions, CompilerOptions} from '@keymanapp/common-types'; +import { analyzeUnitTestEndpoints } from '../src/commands/analyze.js'; +import { BuildKeyboardInfo } from '../src/commands/buildClasses/BuildKeyboardInfo.js'; +import { BuildModelInfo } from '../src/commands/buildClasses/BuildModelInfo.js'; describe('InfrastructureMessages', function () { @@ -36,34 +40,47 @@ describe('InfrastructureMessages', function () { assert.instanceOf(ncb.messages[0].exceptionVar, Error); }); -/* // ERROR_FileDoesNotExist it('should generate ERROR_FileDoesNotExist if a file does not exist', async function() { - await testForMessage(this, ['invalid-keyboards', 'error_file_does_not_exist.kmn'], CompilerMessages.ERROR_FileDoesNotExist); + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + await unitTestEndpoints.build(makePathToFixture('invalid-keyboards', 'Error_File_Does_Not_Exist.kmn'), '', ncb, {}); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_FileDoesNotExist), + 'ERROR_FileDoesNotExist not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); }); // ERROR_FileTypeNotRecognized it('should generate ERROR_FileTypeNotRecognized if a file is not a recognized type', async function() { - await testForMessage(this, ['invalid-keyboards', 'error_file_type_not_recognized.xxx'], CompilerMessages.ERROR_FileTypeNotRecognized); + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + await unitTestEndpoints.build(makePathToFixture('invalid-keyboards', 'error_file_type_not_recognized.xxx'), '', ncb, {}); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_FileTypeNotRecognized), + 'ERROR_FileTypeNotRecognized not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); }); // ERROR_OutFileNotValidForProjects it('should generate ERROR_OutFileNotValidForProjects if an output file is specified for a project build', async function() { - await testForMessage(this, ['invalid-keyboards', 'error_out_file_not_valid_for_projects.kpj'], CompilerMessages.ERROR_OutFileNotValidForProjects); + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + const projectPath = makePathToFixture('kpj-2.0/khmer_angkor', 'khmer_angkor.kpj'); + const outFilePath = makePathToFixture('kpj-2.0/khmer_angkor', 'khmer_angkor.kmx'); + const options: CompilerOptions = {...defaultCompilerOptions}; + await unitTestEndpoints.build(projectPath, outFilePath, ncb, options); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_OutFileNotValidForProjects), + 'ERROR_OutFileNotValidForProjects not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); }); // ERROR_InvalidProjectFile it('should generate ERROR_InvalidProjectFile if a project file is invalid', async function() { - await testForMessage(this, ['invalid-keyboards', 'error_invalid_project_file.kpj'], CompilerMessages.ERROR_InvalidProjectFile); + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + await unitTestEndpoints.build(makePathToFixture('invalid-projects', 'error_invalid_project_file.kpj'), '', ncb, {}); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_InvalidProjectFile), + 'ERROR_InvalidProjectFile not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); }); - */ // ERROR_InvalidProjectFolder (invalid source folder) - + it('should generate ERROR_InvalidProjectFolder if there are no valid file types in the source folder when generating a default project file', async function() { const projectPath = makePathToFixture('invalid-source-folder', 'error_invalid_project_folder.kpj') const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); @@ -72,6 +89,93 @@ describe('InfrastructureMessages', function () { `ERROR_FileTypeNotFound not generated, instead got: `+JSON.stringify(ncb.messages,null,2)); }); + // ERROR_NotAProjectFile + + it('should generate ERROR_NotAProjectFile if a project file is not the correct type', async function() { + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + const projectPath = makePathToFixture('invalid-projects', 'error_not_a_project_file.xxx') + loadProject(projectPath, ncb); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_NotAProjectFile), + 'ERROR_NotAProjectFile not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + }); + + // ERROR_UnknownFileFormat + + it('should generate ERROR_UnknownFileFormat if an analyze osk-char-use mapping file is not the correct type', async function() { + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + const options = {mappingFile: makePathToFixture('analyze', 'error_unknown_file_format.xxx')}; + await analyzeUnitTestEndpoints.analyzeOskCharUse(ncb, [], options); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_UnknownFileFormat), + 'ERROR_UnknownFileFormat not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + }); + + // ERROR_FileTypeNotFound (BuildKeyboardInfo) + + it('should generate ERROR_FileTypeNotFound if a project file does not contain a .kps file entry (BuildKeyboardInfo)', async function() { + const buildKeyboardInfo = new BuildKeyboardInfo(); + const projectPath = makePathToFixture('invalid-projects', 'error_file_type_not_found__keyboard.kpj') + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + await buildKeyboardInfo.build(projectPath, '', ncb, {}); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_FileTypeNotFound), + 'ERROR_FileTypeNotFound not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + }); + + // ERROR_FileTypeNotFound (BuildModelInfo; .model.ts) + + it('should generate ERROR_FileTypeNotFound if a project file does not contain a .model.ts file entry (BuildModelInfo)', async function() { + const buildModelInfo = new BuildModelInfo(); + const projectPath = makePathToFixture('invalid-projects', 'error_file_type_not_found__model_ts.kpj') + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + await buildModelInfo.build(projectPath, '', ncb, {}); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_FileTypeNotFound), + 'ERROR_FileTypeNotFound not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + assert.isTrue(nodeCompilerMessage(ncb, InfrastructureMessages.ERROR_FileTypeNotFound).includes(KeymanFileTypes.Source.Model), + KeymanFileTypes.Source.Model+' not found in the message'); + }); + + // ERROR_FileTypeNotFound (BuildModelInfo; .kps) + + it('should generate ERROR_FileTypeNotFound if a project file does not contain a .kps file entry (BuildModelInfo)', async function() { + const buildModelInfo = new BuildModelInfo(); + const projectPath = makePathToFixture('invalid-projects', 'error_file_type_not_found__model_kps.kpj') + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + await buildModelInfo.build(projectPath, '', ncb, {}); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_FileTypeNotFound), + 'ERROR_FileTypeNotFound not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + assert.isTrue(nodeCompilerMessage(ncb, InfrastructureMessages.ERROR_FileTypeNotFound).includes(KeymanFileTypes.Source.Package), + KeymanFileTypes.Source.Package+' not found in the message'); + }); + + // ERROR_InvalidProjectFolder (no source folder) + it('should generate ERROR_InvalidProjectFolder if there is no source folder when generating a default project file', async function() { + const projectPath = makePathToFixture('no-source-folder', 'error_invalid_project_folder.kpj') + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + loadProject(projectPath, ncb); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_InvalidProjectFolder), + 'ERROR_InvalidProjectFolder not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + }); + + // ERROR_InvalidProjectFolder (invalid source folder) + + it('should generate ERROR_InvalidProjectFolder if there are no valid file types in the source folder when generating a default project file', async function() { + const projectPath = makePathToFixture('invalid-source-folder', 'error_invalid_project_folder.kpj') + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + loadProject(projectPath, ncb); + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_InvalidProjectFolder), + 'ERROR_InvalidProjectFolder not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + }); + + // ERROR_CannotCreateFolder + + it('should generate ERROR_CannotCreateFolder if the output folder cannot be created', async function() { + const buildKeyboardInfo = new BuildKeyboardInfo(); + const targetFilename = makePathToFixture('invalid-projects', 'build', 'error_cannot_create_folder.xxx') + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + buildKeyboardInfo['createOutputFolder'](targetFilename, ncb); // call private method + assert.isTrue(ncb.hasMessage(InfrastructureMessages.ERROR_CannotCreateFolder), + 'ERROR_CannotCreateFolder not generated, instead got: '+JSON.stringify(ncb.messages,null,2)); + }); + // HINT_FilenameHasDifferingCase it('should generate HINT_FilenameHasDifferingCase if a referenced file has differing case', async function() { @@ -117,4 +221,8 @@ function assertMessagesEqual(actualMessages: CompilerEvent[], expectedMessages: assert.deepEqual(actualMessages.map(m => m.code), expectedMessages, `actual callbacks.messages:\n${JSON.stringify(actualMessages,null,2)}\n\n`+ `did not match expected:\n${JSON.stringify(expectedMessages,null,2)}\n\n`); +} + +function nodeCompilerMessage(ncb: NodeCompilerCallbacks, code: number): string { + return ncb.messages.find((item) => item.code == code).message ?? ''; } \ No newline at end of file