From a7092d7a725c47eb2215549ab1a23ea17960a7ff Mon Sep 17 00:00:00 2001 From: "jonas-lt@live.dk" Date: Mon, 24 Jul 2023 20:05:34 +0200 Subject: [PATCH] fix tests and implementation --- src/commands/bundle.ts | 8 +++--- src/commands/diff.ts | 2 +- src/commands/generate/fromTemplate.ts | 30 +++++++++++++++++++++ src/commands/generate/models.ts | 2 +- src/commands/optimize.ts | 19 ++++++++++--- test/commands/bundle/bundle.test.ts | 15 +++++++++++ test/commands/diff.test.ts | 12 +++++++++ test/commands/generate/fromTemplate.test.ts | 15 +++++++++++ test/commands/generate/models.test.ts | 14 +++++++++- test/commands/optimize.test.ts | 5 ++-- 10 files changed, 110 insertions(+), 12 deletions(-) diff --git a/src/commands/bundle.ts b/src/commands/bundle.ts index 22baef09db2..6e865a33f64 100644 --- a/src/commands/bundle.ts +++ b/src/commands/bundle.ts @@ -32,12 +32,14 @@ export default class Bundle extends Command { let baseFile; const outputFormat = path.extname(argv[0]); const AsyncAPIFiles = await this.loadFiles(argv); - const containsAsyncAPI3 = AsyncAPIFiles.map((file) => { + + const containsAsyncAPI3 = AsyncAPIFiles.filter((file) => { return file.isAsyncAPI3(); }); - if (containsAsyncAPI3) { - return this.error('One of the files you tried to bundle is AsyncAPI v3 format, the bundle command does not support it yet, please checkout https://github.com/asyncapi/bundler/issues/133'); + if (containsAsyncAPI3.length > 0) { + this.error('One of the files you tried to bundle is AsyncAPI v3 format, the bundle command does not support it yet, please checkout https://github.com/asyncapi/bundler/issues/133'); } + if (flags.base) {baseFile = (await load(flags.base)).text();} const fileContents = AsyncAPIFiles.map((file) => file.text()); diff --git a/src/commands/diff.ts b/src/commands/diff.ts index 187d7ef5852..60b9a1205fc 100644 --- a/src/commands/diff.ts +++ b/src/commands/diff.ts @@ -88,7 +88,7 @@ export default class Diff extends Command { firstDocument = await load(firstDocumentPath); if (firstDocument.isAsyncAPI3()) { - return this.error('Diff command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/diff/issues/154'); + this.error('Diff command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/diff/issues/154'); } enableWatch(watchMode, { diff --git a/src/commands/generate/fromTemplate.ts b/src/commands/generate/fromTemplate.ts index 8cd1a63e373..7cf040ff7c7 100644 --- a/src/commands/generate/fromTemplate.ts +++ b/src/commands/generate/fromTemplate.ts @@ -30,6 +30,29 @@ interface ParsedFlags { mapBaseUrlToFolder: IMapBaseUrlToFlag } +const templatesNotSupportingV3: Record = { + '@asyncapi/minimaltemplate': 'some link', // For testing purpose + '@asyncapi/html-template': 'https://github.com/asyncapi/html-template/issues/430', + '@asyncapi/dotnet-nats-template': 'https://github.com/asyncapi/dotnet-nats-template/issues/384', + '@asyncapi/ts-nats-template': 'https://github.com/asyncapi/ts-nats-template/issues/545', + '@asyncapi/python-paho-template': 'https://github.com/asyncapi/python-paho-template/issues/189', + '@asyncapi/nodejs-ws-template': 'https://github.com/asyncapi/nodejs-ws-template/issues/294', + '@asyncapi/java-spring-cloud-stream-template': 'https://github.com/asyncapi/java-spring-cloud-stream-template/issues/336', + '@asyncapi/go-watermill-template': 'https://github.com/asyncapi/go-watermill-template/issues/243', + '@asyncapi/java-spring-template': 'https://github.com/asyncapi/java-spring-template/issues/308', + '@asyncapi/markdown-template': 'https://github.com/asyncapi/markdown-template/issues/341' +}; + +/** + * Verify that a given template support v3, if not, return the link to the issue that needs to be solved. + */ +function verifyTemplateSupportForV3(template: string) { + if (templatesNotSupportingV3[`${template}`] !== undefined) { + return templatesNotSupportingV3[`${template}`]; + } + return undefined; +} + export default class Template extends Command { static description = 'Generates whatever you want using templates compatible with AsyncAPI Generator.'; @@ -99,6 +122,7 @@ export default class Template extends Command { mapBaseUrlToFolder: parsedFlags.mapBaseUrlToFolder, disabledHooks: parsedFlags.disableHooks, }; + const asyncapiInput = (await load(asyncapi)) || (await load()); const watchTemplate = flags['watch']; const genOption: any = {}; @@ -106,6 +130,12 @@ export default class Template extends Command { genOption.resolve = {resolve: this.getMapBaseUrlToFolderResolver(parsedFlags.mapBaseUrlToFolder)}; } + if (asyncapiInput.isAsyncAPI3()) { + const v3IssueLink = verifyTemplateSupportForV3(template); + if (v3IssueLink !== undefined) { + this.error(`${template} template does not support AsyncAPI v3 documents, please checkout ${v3IssueLink}`); + } + } await this.generate(asyncapi, template, output, options, genOption); if (watchTemplate) { const watcherHandler = this.watcherHandler(asyncapi, template, output, options, genOption); diff --git a/src/commands/generate/models.ts b/src/commands/generate/models.ts index 88e244841b6..daf976e4d5e 100644 --- a/src/commands/generate/models.ts +++ b/src/commands/generate/models.ts @@ -153,7 +153,7 @@ export default class Models extends Command { const { language, file } = args; const inputFile = (await load(file)) || (await load()); if (inputFile.isAsyncAPI3()) { - return this.error('Generate Models command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/modelina/issues/1376'); + this.error('Generate Models command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/modelina/issues/1376'); } const { document, diagnostics ,status } = await parse(this, inputFile, flags); if (!document || status === 'invalid') { diff --git a/src/commands/optimize.ts b/src/commands/optimize.ts index b00b9ed7778..8c12c2dd57a 100644 --- a/src/commands/optimize.ts +++ b/src/commands/optimize.ts @@ -51,7 +51,7 @@ export default class Optimize extends Command { try { specFile = await load(filePath); } catch (err) { - return this.error( + this.error( new ValidationError({ type: 'invalid-file', filepath: filePath, @@ -60,11 +60,22 @@ export default class Optimize extends Command { } if (specFile.isAsyncAPI3()) { - return this.error('Optimize command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/optimizer/issues/168'); + this.error('Optimize command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/optimizer/issues/168'); } - const optimizer: Optimizer = new Optimizer(specFile.text()); - const report: Report = await optimizer.getReport(); + let optimizer: Optimizer; + let report: Report; + try { + optimizer = new Optimizer(specFile.text()); + report = await optimizer.getReport(); + } catch (err) { + this.error( + new ValidationError({ + type: 'invalid-file', + filepath: filePath, + }) + ); + } this.isInteractive = !flags['no-tty']; this.optimizations = flags.optimization as Optimizations[]; this.outputMethod = flags.output as Outputs; diff --git a/test/commands/bundle/bundle.test.ts b/test/commands/bundle/bundle.test.ts index 870a1d590cb..b5792e330c0 100644 --- a/test/commands/bundle/bundle.test.ts +++ b/test/commands/bundle/bundle.test.ts @@ -4,6 +4,7 @@ import path from 'path'; import { fileCleanup } from '../../testHelper'; const spec = fs.readFileSync('./test/commands/bundle/final-asyncapi.yaml', {encoding: 'utf-8'}); +const asyncapiv3 = './test/specification-v3.yml'; function validateGeneratedSpec(filePath, spec) { const generatedSPec = fs.readFileSync(path.resolve(filePath), { encoding: 'utf-8' }); @@ -11,6 +12,20 @@ function validateGeneratedSpec(filePath, spec) { } describe('bundle', () => { + describe('should handle AsyncAPI v3 document correctly', () => { + test + .stderr() + .stdout() + .command([ + 'bundle', + asyncapiv3, + '--output=./test/commands/bundle/final.yaml']) + .it('give error', (ctx, done) => { + expect(ctx.stderr).toEqual('Error: One of the files you tried to bundle is AsyncAPI v3 format, the bundle command does not support it yet, please checkout https://github.com/asyncapi/bundler/issues/133\n'); + expect(ctx.stdout).toEqual(''); + done(); + }); + }); test .stdout() .command([ diff --git a/test/commands/diff.test.ts b/test/commands/diff.test.ts index e82b08f63de..67e0b12d22f 100644 --- a/test/commands/diff.test.ts +++ b/test/commands/diff.test.ts @@ -1,6 +1,7 @@ /* eslint-disable sonarjs/no-duplicate-string */ import { test } from '@oclif/test'; +const asyncapiv3 = './test/specification-v3.yml'; const noChangesJson = '"{\\n \\"changes\\": []\\n}\\n"'; const breakingChangesJson = '"[\\n {\\n \\"action\\": \\"edit\\",\\n \\"path\\": \\"/servers/mosquitto/protocol\\",\\n \\"before\\": \\"mqtt\\",\\n \\"after\\": \\"http\\",\\n \\"type\\": \\"breaking\\"\\n },\\n {\\n \\"action\\": \\"edit\\",\\n \\"path\\": \\"/servers/mosquitto/url\\",\\n \\"before\\": \\"mqtt://test.mosquitto.org\\",\\n \\"after\\": \\"http://test.mosquitto.org\\",\\n \\"type\\": \\"breaking\\"\\n }\\n]\\n"'; const nonBreakingChangesJson = '"[\\n {\\n \\"action\\": \\"add\\",\\n \\"path\\": \\"/channels/user~1signedup\\",\\n \\"after\\": {\\n \\"subscribe\\": {\\n \\"message\\": {\\n \\"payload\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"displayName\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Name of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"email\\": {\\n \\"type\\": \\"string\\",\\n \\"format\\": \\"email\\",\\n \\"description\\": \\"Email of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n }\\n },\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"x-parser-message-name\\": \\"UserSignedUp\\",\\n \\"x-parser-original-schema-format\\": \\"application/vnd.aai.asyncapi;version=2.1.0\\",\\n \\"schemaFormat\\": \\"application/vnd.aai.asyncapi;version=2.1.0\\",\\n \\"x-parser-original-payload\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"displayName\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Name of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"email\\": {\\n \\"type\\": \\"string\\",\\n \\"format\\": \\"email\\",\\n \\"description\\": \\"Email of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n }\\n },\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"x-parser-message-parsed\\": true\\n }\\n }\\n },\\n \\"type\\": \\"non-breaking\\"\\n },\\n {\\n \\"action\\": \\"edit\\",\\n \\"path\\": \\"/info/title\\",\\n \\"before\\": \\"Streetlights API\\",\\n \\"after\\": \\"Streetlights API V2\\",\\n \\"type\\": \\"non-breaking\\"\\n },\\n {\\n \\"action\\": \\"add\\",\\n \\"path\\": \\"/components\\",\\n \\"after\\": {\\n \\"messages\\": {\\n \\"UserSignedUp\\": {\\n \\"payload\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"displayName\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Name of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"email\\": {\\n \\"type\\": \\"string\\",\\n \\"format\\": \\"email\\",\\n \\"description\\": \\"Email of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n }\\n },\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"x-parser-message-name\\": \\"UserSignedUp\\",\\n \\"x-parser-original-schema-format\\": \\"application/vnd.aai.asyncapi;version=2.1.0\\",\\n \\"schemaFormat\\": \\"application/vnd.aai.asyncapi;version=2.1.0\\",\\n \\"x-parser-original-payload\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"displayName\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Name of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"email\\": {\\n \\"type\\": \\"string\\",\\n \\"format\\": \\"email\\",\\n \\"description\\": \\"Email of the user\\",\\n \\"x-parser-schema-id\\": \\"\\"\\n }\\n },\\n \\"x-parser-schema-id\\": \\"\\"\\n },\\n \\"x-parser-message-parsed\\": true\\n }\\n }\\n },\\n \\"type\\": \\"non-breaking\\"\\n }\\n]\\n"'; @@ -16,6 +17,17 @@ const markdownJsonOutput = "\"## Unclassified\\n\\n\\n - **Path**: `/channels/li const markdownYamlOutput = '"## Unclassified\\n\\n\\n - **Path**: `/channels/light~1measured/publish/message/x-parser-original-payload/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/x-parser-original-payload/properties/sentAt/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/x-parser-original-payload/properties/lumens/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/x-parser-original-payload/properties/id/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/x-parser-original-payload/properties/id/minimum`\\n - **Action**: edit\\n - **Before**: 0\\n - **After**: 1\\n \\n - **Path**: `/channels/light~1measured/publish/message/payload/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/payload/properties/sentAt/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/payload/properties/lumens/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/payload/properties/id/x-parser-schema-id`\\n - **Action**: edit\\n - **Before**: \\n - **After**: \\n \\n - **Path**: `/channels/light~1measured/publish/message/payload/properties/id/minimum`\\n - **Action**: edit\\n - **Before**: 0\\n - **After**: 1\\n \\n\\n## Non-breaking\\n\\n\\n - **Path**: `/channels/user~1signedup`\\n - **Action**: add\\n -
\\n After \\n \\n ```yaml\\n subscribe:\\n message:\\n payload:\\n type: object\\n properties:\\n displayName:\\n type: string\\n description: Name of the user\\n x-parser-schema-id: \\n email:\\n type: string\\n format: email\\n description: Email of the user\\n x-parser-schema-id: \\n x-parser-schema-id: \\n x-parser-message-name: UserSignedUp\\n x-parser-original-schema-format: application/vnd.aai.asyncapi;version=2.1.0\\n schemaFormat: application/vnd.aai.asyncapi;version=2.1.0\\n x-parser-original-payload:\\n type: object\\n properties:\\n displayName:\\n type: string\\n description: Name of the user\\n x-parser-schema-id: \\n email:\\n type: string\\n format: email\\n description: Email of the user\\n x-parser-schema-id: \\n x-parser-schema-id: \\n x-parser-message-parsed: true\\n \\n ``` \\n
\\n \\n \\n - **Path**: `/info/title`\\n - **Action**: edit\\n - **Before**: Streetlights API\\n - **After**: Streetlights API V2\\n \\n - **Path**: `/components`\\n - **Action**: add\\n -
\\n After \\n \\n ```yaml\\n messages:\\n UserSignedUp:\\n payload:\\n type: object\\n properties:\\n displayName:\\n type: string\\n description: Name of the user\\n x-parser-schema-id: \\n email:\\n type: string\\n format: email\\n description: Email of the user\\n x-parser-schema-id: \\n x-parser-schema-id: \\n x-parser-message-name: UserSignedUp\\n x-parser-original-schema-format: application/vnd.aai.asyncapi;version=2.1.0\\n schemaFormat: application/vnd.aai.asyncapi;version=2.1.0\\n x-parser-original-payload:\\n type: object\\n properties:\\n displayName:\\n type: string\\n description: Name of the user\\n x-parser-schema-id: \\n email:\\n type: string\\n format: email\\n description: Email of the user\\n x-parser-schema-id: \\n x-parser-schema-id: \\n x-parser-message-parsed: true\\n \\n ``` \\n
\\n \\n \\n\\n## Breaking\\n\\n\\n - **Path**: `/servers/mosquitto/protocol`\\n - **Action**: edit\\n - **Before**: mqtt\\n - **After**: http\\n \\n - **Path**: `/servers/mosquitto/url`\\n - **Action**: edit\\n - **Before**: mqtt://test.mosquitto.org\\n - **After**: http://test.mosquitto.org\\n \\n\\n"'; describe('diff', () => { + describe('should handle AsyncAPI v3 document correctly', () => { + test + .stderr() + .stdout() + .command(['diff', asyncapiv3, asyncapiv3]) + .it('give error', (ctx, done) => { + expect(ctx.stderr).toEqual('Error: Diff command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/diff/issues/154\n'); + expect(ctx.stdout).toEqual(''); + done(); + }); + }); describe('with file paths, and there are no difference between the files', () => { test .stderr() diff --git a/test/commands/generate/fromTemplate.test.ts b/test/commands/generate/fromTemplate.test.ts index 0faa2f55041..7a315b8bd13 100644 --- a/test/commands/generate/fromTemplate.test.ts +++ b/test/commands/generate/fromTemplate.test.ts @@ -8,6 +8,7 @@ const generalOptions = [ './test/specification.yml', '@asyncapi/minimaltemplate', ]; +const asyncapiv3 = './test/specification-v3.yml'; function cleanup(filepath: string) { rimraf.sync(filepath); @@ -28,6 +29,20 @@ describe('template', () => { done(); }); + describe('should handle AsyncAPI v3 document correctly', () => { + test + .stderr() + .stdout() + .command([ + 'generate:fromTemplate', + asyncapiv3, + '@asyncapi/minimaltemplate']) + .it('give error', (ctx, done) => { + expect(ctx.stderr).toEqual('Error: @asyncapi/minimaltemplate template does not support AsyncAPI v3 documents, please checkout some link\n'); + expect(ctx.stdout).toEqual(''); + done(); + }); + }); describe('git clash', () => { const pathToOutput = './test/docs/2'; beforeAll(() => { diff --git a/test/commands/generate/models.test.ts b/test/commands/generate/models.test.ts index fe92b6478f9..c7a47c33933 100644 --- a/test/commands/generate/models.test.ts +++ b/test/commands/generate/models.test.ts @@ -5,7 +5,7 @@ import { test } from '@oclif/test'; import { createMockServer, stopMockServer } from '../../testHelper'; const generalOptions = ['generate:models']; const outputDir = './test/commands/generate/models'; - +const asyncapiv3 = './test/specification-v3.yml'; describe('models', () => { beforeAll(() => { createMockServer(); @@ -13,6 +13,18 @@ describe('models', () => { afterAll(() => { stopMockServer(); }); + describe('should handle AsyncAPI v3 document correctly', () => { + test + .stderr() + .stdout() + .command([ + ...generalOptions, 'typescript', asyncapiv3]) + .it('give error', (ctx, done) => { + expect(ctx.stderr).toEqual('Error: Generate Models command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/modelina/issues/1376\n'); + expect(ctx.stdout).toEqual(''); + done(); + }); + }); test .stderr() .stdout() diff --git a/test/commands/optimize.test.ts b/test/commands/optimize.test.ts index dbc7a57fa61..c48b83529aa 100644 --- a/test/commands/optimize.test.ts +++ b/test/commands/optimize.test.ts @@ -17,11 +17,12 @@ describe('optimize', () => { .stdout() .command(['optimize', asyncapiv3]) .it('give error', (ctx, done) => { - expect(ctx.stderr).toEqual('Error: Optimize command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/optimizer/issues/168'); - expect(ctx.stdout).toEqual(' '); + expect(ctx.stderr).toEqual('Error: Optimize command does not support AsyncAPI v3 yet, please checkout https://github.com/asyncapi/optimizer/issues/168\n'); + expect(ctx.stdout).toEqual(''); done(); }); }); + describe('no optimization needed', () => { beforeEach(() => { testHelper.createDummyContextFile();