From a7ba312ed0449bce6e1ef10e211701e32b73894f Mon Sep 17 00:00:00 2001 From: Anshukumar123975 Date: Wed, 2 Jul 2025 18:15:28 +0530 Subject: [PATCH 1/7] Updated readme and added the CLI for customising the import source path for the parser, modelmanager and modelfile Signed-off-by: Anshukumar123975 --- README.md | 33 +++++++++- cli.js | 65 +++++++++++++++++++ package.json | 7 +- .../Semantic.Support.CSharp.AssemblyInfo.cs | 2 +- ...ic.Support.CSharp.AssemblyInfoInputs.cache | 2 +- semantic/features/support/Javascript/steps.ts | 7 +- semantic/features/support/Javascript/world.ts | 5 +- .../templates/Javascript/steps.template.ts | 54 +++++++++++++++ .../templates/Javascript/world.template.ts | 15 +++++ tsconfig.json | 4 +- 10 files changed, 180 insertions(+), 14 deletions(-) create mode 100644 cli.js create mode 100644 semantic/features/support/templates/Javascript/steps.template.ts create mode 100644 semantic/features/support/templates/Javascript/world.template.ts diff --git a/README.md b/README.md index a9f2d0d..7859fc1 100644 --- a/README.md +++ b/README.md @@ -1 +1,32 @@ -# concerto-conformance +# Concerto Conformance Test Suite +## Desription +The Concerto Conformance Test Suite provides a standardized, automated testing suite to validate models and semantic behavior across Accord Project Concerto implementations. +## Overview +This repository includes: +1. A curated set of semantic validation rules +2. Comprehensive valid and invalid model examples +3. Tests written using Cucumber, offering behavior-driven, human-readable test definitions +4. Support for both JavaScript and C# environments +The suite specifically tests core components of the Concerto ecosystem: +1. The Parser from `@accordproject/concerto-cto` +2. The ModelFile and ModelManager from `@accordproject/concerto-core` +## Getting started +1. Install dependencies: + `npm install` +2. Run the Javascript test suite: + `npm test` +3. Run tests for C#: + `npm run test:csharp` +## Interactive CLI: +You can also use the built-in CLI for a guided setup: + `npm start` +The CLI allows you to: +1. Provide custom ModelManager, Parser, or ModelFile sources for testing +2. Choose between JavaScript or C# environments +3. Automatically generate test files with proper imports +4. Run the relevant conformance tests seamlessly +## Future Roadmap +Enabling straightforward integration with CI/CD pipelines, so projects like Concerto itself can: +1. Automatically run conformance tests on every push +2. Detect semantic rule violations or model-breaking changes early +3. Maintain consistent validation standards across development workflows \ No newline at end of file diff --git a/cli.js b/cli.js new file mode 100644 index 0000000..4b42909 --- /dev/null +++ b/cli.js @@ -0,0 +1,65 @@ +import inquirer from 'inquirer'; +import fs from 'fs'; +import { execSync } from 'child_process'; + +const defaults = { + ModelManager: '@accordproject/concerto-core', + Parser: '@accordproject/concerto-cto', + ModelFile: '@accordproject/concerto-core' +}; + +async function run() { + const { language } = await inquirer.prompt({ + type: 'list', + name: 'language', + message: 'Choose language:', + choices: ['Javascript', 'C#'] + }); + + const imports = {}; + + for (const comp of Object.keys(defaults)) { + const { include } = await inquirer.prompt({ + type: 'confirm', + name: 'include', + message: `Do you want to test your own ${comp}?` + }); + + if (include) { + const { path: userPath } = await inquirer.prompt({ + type: 'input', + name: 'path', + message: `Enter import path for ${comp} (default: ${defaults[comp]}):` + }); + + const finalPath = userPath.trim() || defaults[comp]; + imports[comp] = `import { ${comp} } from '${finalPath}';`; + + } else { + imports[comp] = `import { ${comp} } from '${defaults[comp]}';`; + } + } + + const templatePath = `semantic/features/support/templates/${language}`; + const outputPath = `semantic/features/support/${language}`; + + const worldTemplate = fs.readFileSync(`${templatePath}/world.template.ts`, 'utf-8'); + const worldOutput = worldTemplate.replace('{{MODELMANAGER_IMPORT}}', imports.ModelManager); + fs.writeFileSync(`${outputPath}/world.ts`, worldOutput); + + const stepsTemplate = fs.readFileSync(`${templatePath}/steps.template.ts`, 'utf-8'); + const stepsOutput = stepsTemplate + .replace('{{PARSER_IMPORT}}', imports.Parser) + .replace('{{MODELFILE_IMPORT}}', imports.ModelFile); + fs.writeFileSync(`${outputPath}/steps.ts`, stepsOutput); + + console.log("Setup ready. Running tests..."); + + if (language === 'Javascript') { + execSync('npm test', { stdio: 'inherit' }); + } else { + execSync('npm run test:csharp', { stdio: 'inherit' }); + } +} + +run(); diff --git a/package.json b/package.json index 4f27cc4..7fc17e3 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,9 @@ "main": "index.js", "type": "module", "scripts": { - "test": "cucumber-js \"semantic/features/**/*.feature\" --loader ts-node/esm --import \"semantic/features/support/**/*.ts\" --tags \"not @skip\"", - "test:csharp": "dotnet test semantic/features/support/C#/Semantic.Support.CSharp/Semantic.Support.CSharp.csproj" + "test": "cucumber-js \"semantic/features/**/*.feature\" --loader ts-node/esm --import \"semantic/features/support/Javascript/*.ts\" --tags \"not @skip\"", + "test:csharp": "dotnet test semantic/features/support/C#/Semantic.Support.CSharp/Semantic.Support.CSharp.csproj", + "start": "node cli.js" }, "keywords": [], "author": "", @@ -14,7 +15,9 @@ "dependencies": { "@accordproject/concerto-core": "^3.21.0", "@accordproject/concerto-cto": "^3.22.0", + "child_process": "^1.0.2", "fs": "^0.0.1-security", + "inquirer": "^12.6.3", "path": "^0.12.7", "vitest": "^3.2.1" }, diff --git a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs index 30718d3..3b15194 100644 --- a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs +++ b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("Semantic.Support.CSharp")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+63a012d9040a0114719eb56b8d735e07fff7bb4a")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a8397d03d19e11da53c8cf4b0c20d533bd38674e")] [assembly: System.Reflection.AssemblyProductAttribute("Semantic.Support.CSharp")] [assembly: System.Reflection.AssemblyTitleAttribute("Semantic.Support.CSharp")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache index 988e6da..7ef3799 100644 --- a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache +++ b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache @@ -1 +1 @@ -ac751e616cdb4178e8e1b0c3c1233dc4b2b6a691fe113800adc728d7d8146b29 +a60373f232043311d004e6b4f6c4a7eaa249c4bc5e82ad1c8092b7f04a30ceb2 diff --git a/semantic/features/support/Javascript/steps.ts b/semantic/features/support/Javascript/steps.ts index ddb2efc..87add78 100644 --- a/semantic/features/support/Javascript/steps.ts +++ b/semantic/features/support/Javascript/steps.ts @@ -8,7 +8,6 @@ Given('I load the following models:', function (dataTable) { for (const row of dataTable.hashes()) { const modelContent = loadCTO(row.model_file); try { - // this.modelManager.addCTOModel(modelContent, row.model_file, true); const ast = Parser.parse(modelContent, row.model_file); const modelFile = new ModelFile(this.modelManager, ast, modelContent, row.model_file); this.modelManager.addModelFile(modelFile, null, modelFile.getName(), true); @@ -19,7 +18,6 @@ Given('I load the following models:', function (dataTable) { } }); - When('I validate the models', function () { try { this.modelManager.validateModelFiles(); @@ -31,7 +29,7 @@ When('I validate the models', function () { Then('an error should be thrown with message {string}', function (expected: string) { assert(this.error, 'Expected an error to be thrown, but none was'); - + let isMatch: boolean; const match = expected.match(/^\/(.+)\/([gimsuy]*)?$/); @@ -51,7 +49,6 @@ Then('an error should be thrown with message {string}', function (expected: stri } }); - Then('no error should be thrown', function () { assert.strictEqual(this.error, null, `Expected no error, but got: ${this.error?.message}`); -}); \ No newline at end of file +}); diff --git a/semantic/features/support/Javascript/world.ts b/semantic/features/support/Javascript/world.ts index 9ed89ca..c15b388 100644 --- a/semantic/features/support/Javascript/world.ts +++ b/semantic/features/support/Javascript/world.ts @@ -1,6 +1,7 @@ -import { setWorldConstructor, IWorldOptions } from '@cucumber/cucumber'; import { ModelManager } from '@accordproject/concerto-core'; +import { setWorldConstructor, IWorldOptions } from '@cucumber/cucumber'; + export class CustomWorld { public modelManager: ModelManager; public error: Error | null; @@ -11,4 +12,4 @@ export class CustomWorld { } } -setWorldConstructor(CustomWorld); \ No newline at end of file +setWorldConstructor(CustomWorld); diff --git a/semantic/features/support/templates/Javascript/steps.template.ts b/semantic/features/support/templates/Javascript/steps.template.ts new file mode 100644 index 0000000..eb29952 --- /dev/null +++ b/semantic/features/support/templates/Javascript/steps.template.ts @@ -0,0 +1,54 @@ +import { Given, When, Then } from '@cucumber/cucumber'; +import { loadCTO } from './utils/loadCTO.ts'; +{{PARSER_IMPORT}} +{{MODELFILE_IMPORT}} +import assert from 'assert'; + +Given('I load the following models using the follwoing model files:', function (dataTable) { + for (const row of dataTable.hashes()) { + const modelContent = loadCTO(row.model_file); + try { + const ast = Parser.parse(modelContent, row.model_file); + const modelFile = new ModelFile(this.modelManager, ast, modelContent, row.model_file); + this.modelManager.addModelFile(modelFile, null, modelFile.getName(), true); + } catch (err) { + this.error = err as Error; + break; + } + } +}); + +When('I validate the models', function () { + try { + this.modelManager.validateModelFiles(); + this.error = null; + } catch (err) { + this.error = err as Error; + } +}); + +Then('an error should be thrown with message {string}', function (expected: string) { + assert(this.error, 'Expected an error to be thrown, but none was'); + + let isMatch: boolean; + const match = expected.match(/^\/(.+)\/([gimsuy]*)?$/); + + if (match) { + const pattern = new RegExp(match[1], match[2]); + isMatch = pattern.test(this.error.message); + assert( + isMatch, + `Expected error to match regex ${pattern}, but got: "${this.error.message}"` + ); + } else { + isMatch = this.error.message.includes(expected); + assert( + isMatch, + `Expected error to include "${expected}", but got: "${this.error.message}"` + ); + } +}); + +Then('no error should be thrown', function () { + assert.strictEqual(this.error, null, `Expected no error, but got: ${this.error?.message}`); +}); diff --git a/semantic/features/support/templates/Javascript/world.template.ts b/semantic/features/support/templates/Javascript/world.template.ts new file mode 100644 index 0000000..fb531b0 --- /dev/null +++ b/semantic/features/support/templates/Javascript/world.template.ts @@ -0,0 +1,15 @@ +{{MODELMANAGER_IMPORT}} + +import { setWorldConstructor, IWorldOptions } from '@cucumber/cucumber'; + +export class CustomWorld { + public modelManager: ModelManager; + public error: Error | null; + + constructor(options: IWorldOptions) { + this.modelManager = new ModelManager({ enableMapType: true }); + this.error = null; + } +} + +setWorldConstructor(CustomWorld); diff --git a/tsconfig.json b/tsconfig.json index 54b3afa..9b63d42 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,6 @@ "resolveJsonModule": true, "isolatedModules": true }, - "include": ["semantic/features/**/*.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules","semantic/features/support/Javascript/**/*.template.ts"], + "include": ["semantic/features/support/Javascript/*.ts", "semantic/features/support/templates/Javascript/world.template.ts", "semantic/features/support/templates/Javascript/steps.template.ts"] } From 2f0aa72d37cfb891a85492386d7f7cadc86aa60b Mon Sep 17 00:00:00 2001 From: Anshukumar123975 Date: Wed, 2 Jul 2025 18:28:58 +0530 Subject: [PATCH 2/7] Some minor bug fixes Signed-off-by: Anshukumar123975 --- .../features/support/templates/Javascript/steps.template.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantic/features/support/templates/Javascript/steps.template.ts b/semantic/features/support/templates/Javascript/steps.template.ts index eb29952..2d3ea77 100644 --- a/semantic/features/support/templates/Javascript/steps.template.ts +++ b/semantic/features/support/templates/Javascript/steps.template.ts @@ -4,7 +4,7 @@ import { loadCTO } from './utils/loadCTO.ts'; {{MODELFILE_IMPORT}} import assert from 'assert'; -Given('I load the following models using the follwoing model files:', function (dataTable) { +Given('I load the following models:', function (dataTable) { for (const row of dataTable.hashes()) { const modelContent = loadCTO(row.model_file); try { From 6a38acbbf559ba4141855815a65238fa9f37d933 Mon Sep 17 00:00:00 2001 From: Anshu Kumar <146181349+Anshukumar123975@users.noreply.github.com> Date: Thu, 3 Jul 2025 13:53:42 +0530 Subject: [PATCH 3/7] Update README.md Co-authored-by: Ertugrul Karademir Signed-off-by: Anshukumar123975 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7859fc1..c96051a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Concerto Conformance Test Suite ## Desription -The Concerto Conformance Test Suite provides a standardized, automated testing suite to validate models and semantic behavior across Accord Project Concerto implementations. +The Concerto Conformance Test Suite provides a standardized, automated testing suite to validate models and semantic behavior across Accord Project's Concerto implementation. ## Overview This repository includes: 1. A curated set of semantic validation rules From 3fed28884e848cf362f5f0e8a3c427fafbffe544 Mon Sep 17 00:00:00 2001 From: Anshu Kumar <146181349+Anshukumar123975@users.noreply.github.com> Date: Thu, 3 Jul 2025 13:53:56 +0530 Subject: [PATCH 4/7] Update README.md Co-authored-by: Ertugrul Karademir Signed-off-by: Anshukumar123975 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c96051a..4525ff2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This repository includes: 1. A curated set of semantic validation rules 2. Comprehensive valid and invalid model examples 3. Tests written using Cucumber, offering behavior-driven, human-readable test definitions -4. Support for both JavaScript and C# environments +4. Support for both JavaScript and C# runtimes The suite specifically tests core components of the Concerto ecosystem: 1. The Parser from `@accordproject/concerto-cto` 2. The ModelFile and ModelManager from `@accordproject/concerto-core` From c3f588421538ab2ae2e1e6372ddba4fbb38dca27 Mon Sep 17 00:00:00 2001 From: Anshu Kumar <146181349+Anshukumar123975@users.noreply.github.com> Date: Thu, 3 Jul 2025 13:54:04 +0530 Subject: [PATCH 5/7] Update README.md Co-authored-by: Ertugrul Karademir Signed-off-by: Anshukumar123975 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4525ff2..a52c9e3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This repository includes: 4. Support for both JavaScript and C# runtimes The suite specifically tests core components of the Concerto ecosystem: 1. The Parser from `@accordproject/concerto-cto` -2. The ModelFile and ModelManager from `@accordproject/concerto-core` +2. The `ModelFile` and `ModelManager` classes from `@accordproject/concerto-core` ## Getting started 1. Install dependencies: `npm install` From b59ef6f3ac61c50be591c3942e50bc2cd97da9dc Mon Sep 17 00:00:00 2001 From: Anshu Kumar <146181349+Anshukumar123975@users.noreply.github.com> Date: Thu, 3 Jul 2025 13:54:30 +0530 Subject: [PATCH 6/7] Update README.md Co-authored-by: Ertugrul Karademir Signed-off-by: Anshukumar123975 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a52c9e3..054ec66 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Concerto Conformance Test Suite ## Desription The Concerto Conformance Test Suite provides a standardized, automated testing suite to validate models and semantic behavior across Accord Project's Concerto implementation. + ## Overview This repository includes: 1. A curated set of semantic validation rules From 686e835f79b9e2e2c4b8ec207a074561a7ff3d4b Mon Sep 17 00:00:00 2001 From: Anshukumar123975 Date: Thu, 3 Jul 2025 13:58:49 +0530 Subject: [PATCH 7/7] Updated readme.md Signed-off-by: Anshukumar123975 --- README.md | 16 +++++++--------- .../Semantic.Support.CSharp.AssemblyInfo.cs | 2 +- ...antic.Support.CSharp.AssemblyInfoInputs.cache | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 054ec66..33b0d1b 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ # Concerto Conformance Test Suite + ## Desription The Concerto Conformance Test Suite provides a standardized, automated testing suite to validate models and semantic behavior across Accord Project's Concerto implementation. ## Overview This repository includes: -1. A curated set of semantic validation rules +1. A set of semantic validation rules 2. Comprehensive valid and invalid model examples 3. Tests written using Cucumber, offering behavior-driven, human-readable test definitions 4. Support for both JavaScript and C# runtimes -The suite specifically tests core components of the Concerto ecosystem: -1. The Parser from `@accordproject/concerto-cto` -2. The `ModelFile` and `ModelManager` classes from `@accordproject/concerto-core` +The suite specifically tests core components of the Concerto ecosystem: the `ModelFile` and `ModelManager` classes from `@accordproject/concerto-core` + ## Getting started 1. Install dependencies: `npm install` @@ -18,14 +18,12 @@ The suite specifically tests core components of the Concerto ecosystem: `npm test` 3. Run tests for C#: `npm run test:csharp` + ## Interactive CLI: You can also use the built-in CLI for a guided setup: `npm start` -The CLI allows you to: -1. Provide custom ModelManager, Parser, or ModelFile sources for testing -2. Choose between JavaScript or C# environments -3. Automatically generate test files with proper imports -4. Run the relevant conformance tests seamlessly +The CLI allows you to provide custom ModelManager, Parser, or ModelFile sources for testing. + ## Future Roadmap Enabling straightforward integration with CI/CD pipelines, so projects like Concerto itself can: 1. Automatically run conformance tests on every push diff --git a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs index 3b15194..1c7a0f1 100644 --- a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs +++ b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("Semantic.Support.CSharp")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a8397d03d19e11da53c8cf4b0c20d533bd38674e")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+069d3994476d298ecb67f9eee824952d7af16260")] [assembly: System.Reflection.AssemblyProductAttribute("Semantic.Support.CSharp")] [assembly: System.Reflection.AssemblyTitleAttribute("Semantic.Support.CSharp")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache index 7ef3799..bdc26ea 100644 --- a/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache +++ b/semantic/features/support/C#/Semantic.Support.CSharp/obj/Debug/net6.0/Semantic.Support.CSharp.AssemblyInfoInputs.cache @@ -1 +1 @@ -a60373f232043311d004e6b4f6c4a7eaa249c4bc5e82ad1c8092b7f04a30ceb2 +728d0b1b0d333a3b88a57dc69ea86f43dc0b627052d6c700db51c82470e30ee7