Repository: asyncapi/parser-js
Pull request #824 (2023-08-01 10:27:29)

chore: merge `master` into `next-major-spec` + adapt tests for v3
> **Warning**
> This PR should be merged manually by using Merge with commit strategy. More info on https://github.com/asyncapi/community/issues/641


Patch:
diff --git a/CODEOWNERS b/CODEOWNERS
index 90134c9..22daaea 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -5,4 +5,4 @@
 # For more details, read the following article on GitHub: https://help.github.com/articles/about-codeowners/.
 
 # The default owners are automatically added as reviewers when you open a pull request unless different owners are specified in the file.
-* @fmvilas @magicmatatjahu @jonaslagoni @derberg @smoya @asyncapi-bot-eve
+* @fmvilas @magicmatatjahu @jonaslagoni @smoya @asyncapi-bot-eve
diff --git a/src/ruleset/formats.ts b/src/ruleset/formats.ts
index 7abda41..a0d0693 100644
--- a/src/ruleset/formats.ts
+++ b/src/ruleset/formats.ts
@@ -1,51 +1,57 @@
-/* eslint-disable security/detect-unsafe-regex */
-
-import { isObject } from '../utils';
+import { getSemver, isObject } from '../utils';
+import { schemas } from '@asyncapi/specs';
 
 import type { Format } from '@stoplight/spectral-core';
 import type { MaybeAsyncAPI } from '../types';
 
-const aas2Regex = /^2\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/;
-const aas2_0Regex = /^2\.0(?:\.[0-9]*)?$/;
-const aas2_1Regex = /^2\.1(?:\.[0-9]*)?$/;
-const aas2_2Regex = /^2\.2(?:\.[0-9]*)?$/;
-const aas2_3Regex = /^2\.3(?:\.[0-9]*)?$/;
-const aas2_4Regex = /^2\.4(?:\.[0-9]*)?$/;
-const aas2_5Regex = /^2\.5(?:\.[0-9]*)?$/;
-const aas2_6Regex = /^2\.6(?:\.[0-9]*)?$/;
-
-const isAas2 = (document: unknown): document is { asyncapi: string } & Record<string, unknown> =>
-  isObject(document) && 'asyncapi' in document && aas2Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-
-export const aas2: Format = isAas2;
-aas2.displayName = 'AsyncAPI 2.x';
-
-export const aas2_0: Format = (document: unknown): boolean =>
-  isAas2(document) && aas2_0Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-aas2_0.displayName = 'AsyncAPI 2.0.x';
-
-export const aas2_1: Format = (document: unknown): boolean =>
-  isAas2(document) && aas2_1Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-aas2_1.displayName = 'AsyncAPI 2.1.x';
-
-export const aas2_2: Format = (document: unknown): boolean =>
-  isAas2(document) && aas2_2Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-aas2_2.displayName = 'AsyncAPI 2.2.x';
-
-export const aas2_3: Format = (document: unknown): boolean =>
-  isAas2(document) && aas2_3Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-aas2_3.displayName = 'AsyncAPI 2.3.x';
-
-export const aas2_4: Format = (document: unknown): boolean =>
-  isAas2(document) && aas2_4Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-aas2_4.displayName = 'AsyncAPI 2.4.x';
-
-export const aas2_5: Format = (document: unknown): boolean =>
-  isAas2(document) && aas2_5Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-aas2_5.displayName = 'AsyncAPI 2.5.x';
-
-export const aas2_6: Format = (document: unknown): boolean =>
-  isAas2(document) && aas2_6Regex.test(String((document as MaybeAsyncAPI).asyncapi));
-aas2_6.displayName = 'AsyncAPI 2.6.x';
+export class Formats extends Map<string, Format> {
+  filterByMajorVersions(majorsToInclude: string[]): Formats {
+    return new Formats([...this.entries()].filter(element => {return majorsToInclude.includes(element[0].split('.')[0]);}));
+  }
+
+  excludeByVersions(versionsToExclude: string[]): Formats {
+    return new Formats([...this.entries()].filter(element => {return !versionsToExclude.includes(element[0]);}));
+  }
+
+  find(version: string): Format | undefined {
+    return this.get(formatVersion(version));
+  }
+
+  formats(): Format[] {
+    return [...this.values()];
+  } 
+}
+
+export const AsyncAPIFormats = new Formats(Object.entries(schemas).reverse().map(([version]) => [version, createFormat(version)])); // reverse is used for giving newer versions a higher priority when matching
+
+function isAsyncAPIVersion(versionToMatch: string, document: unknown): document is { asyncapi: string } & Record<string, unknown> {
+  const asyncAPIDoc = document as MaybeAsyncAPI;
+  if (!asyncAPIDoc) return false;
+
+  const documentVersion = String(asyncAPIDoc.asyncapi);
+  return isObject(document) && 'asyncapi' in document 
+    && assertValidAsyncAPIVersion(documentVersion)
+    && versionToMatch === formatVersion(documentVersion);
+}
+  
+function assertValidAsyncAPIVersion(documentVersion: string): boolean {
+  const semver = getSemver(documentVersion);
+  const regexp = new RegExp(`^(${semver.major})\\.(${semver.minor})\\.(0|[1-9][0-9]*)$`); // eslint-disable-line security/detect-non-literal-regexp
+  return regexp.test(documentVersion);
+}
+
+function createFormat(version: string): Format {
+  const format: Format = (document: unknown): boolean =>
+    isAsyncAPIVersion(version, document);
+  
+  const semver = getSemver(version);
+  format.displayName = `AsyncAPI ${semver.major}.${semver.minor}.x`;
+
+  return format; 
+}
+
+const formatVersion = function (version: string): string {
+  const versionSemver = getSemver(version);
+  return `${versionSemver.major}.${versionSemver.minor}.0`;
+};
 
-export const aas2All = [aas2_0, aas2_1, aas2_2, aas2_3, aas2_4, aas2_5, aas2_6];
diff --git a/src/ruleset/functions/documentStructure.ts b/src/ruleset/functions/documentStructure.ts
index e6f6c08..a00268d 100644
--- a/src/ruleset/functions/documentStructure.ts
+++ b/src/ruleset/functions/documentStructure.ts
@@ -1,10 +1,10 @@
 import specs from '@asyncapi/specs';
 import { createRulesetFunction } from '@stoplight/spectral-core';
 import { schema as schemaFn } from '@stoplight/spectral-functions';
-import { aas2_0, aas2_1, aas2_2, aas2_3, aas2_4, aas2_5, aas2_6 } from '../formats';
 
 import type { ErrorObject } from 'ajv';
 import type { IFunctionResult, Format } from '@stoplight/spectral-core';
+import { AsyncAPIFormats } from '../formats';
 
 type AsyncAPIVersions = keyof typeof specs.schemas;
 
@@ -80,24 +80,11 @@ function filterRefErrors(errors: IFunctionResult[], resolved: boolean) {
     });
 }
 
-function getSchema(formats: Set<Format>): Record<string, any> | void {
-  switch (true) {
-  case formats.has(aas2_6):
-    return getSerializedSchema('2.6.0');
-  case formats.has(aas2_5):
-    return getSerializedSchema('2.5.0');
-  case formats.has(aas2_4):
-    return getSerializedSchema('2.4.0');
-  case formats.has(aas2_3):
-    return getSerializedSchema('2.3.0');
-  case formats.has(aas2_2):
-    return getSerializedSchema('2.2.0');
-  case formats.has(aas2_1):
-    return getSerializedSchema('2.1.0');
-  case formats.has(aas2_0):
-    return getSerializedSchema('2.0.0');
-  default:
-    return;
+export function getSchema(docFormats: Set<Format>): Record<string, any> | void {
+  for (const [version, format] of AsyncAPIFormats) {
+    if (docFormats.has(format)) {
+      return getSerializedSchema(version as AsyncAPIVersions);
+    }
   }
 }
 
diff --git a/src/ruleset/functions/unusedComponent.ts b/src/ruleset/functions/unusedComponent.ts
index 0be382d..0040204 100644
--- a/src/ruleset/functions/unusedComponent.ts
+++ b/src/ruleset/functions/unusedComponent.ts
@@ -1,6 +1,5 @@
 import { unreferencedReusableObject } from '@stoplight/spectral-functions';
 import { createRulesetFunction } from '@stoplight/spectral-core';
-import { aas2 } from '../formats';
 import { isObject } from '../../utils';
 
 import type { IFunctionResult } from '@stoplight/spectral-core';
@@ -23,9 +22,9 @@ export const unusedComponent = createRulesetFunction<{ components: Record<string
 
     const results: IFunctionResult[] = [];
     Object.keys(components).forEach(componentType => {
-      // if component type is `securitySchemes` and we operate on AsyncAPI 2.x.x skip validation
-      // security schemes in 2.x.x are referenced by keys, not by object ref - for this case we have a separate `asyncapi2-unused-securityScheme` rule
-      if (componentType === 'securitySchemes' && aas2(targetVal, null)) {
+      // if component type is `securitySchemes` we skip the validation
+      // security schemes in >=2.x.x are referenced by keys, not by object ref - for this case we have a separate `asyncapi2-unused-securityScheme` rule
+      if (componentType === 'securitySchemes') {
         return;
       }
 
diff --git a/src/ruleset/ruleset.ts b/src/ruleset/ruleset.ts
index 0f87c3d..c24ebfd 100644
--- a/src/ruleset/ruleset.ts
+++ b/src/ruleset/ruleset.ts
@@ -1,4 +1,4 @@
-import { aas2All as aas2AllFormats } from './formats';
+
 import { lastVersion } from '../constants';
 import { truthy, schema } from '@stoplight/spectral-functions';
 
@@ -6,10 +6,11 @@ import { documentStructure } from './functions/documentStructure';
 import { internal } from './functions/internal';
 import { isAsyncAPIDocument } from './functions/isAsyncAPIDocument';
 import { unusedComponent } from './functions/unusedComponent';
+import { AsyncAPIFormats } from './formats';
 
 export const coreRuleset = {
   description: 'Core AsyncAPI x.x.x ruleset.',
-  formats: [...aas2AllFormats],
+  formats: AsyncAPIFormats.filterByMajorVersions(['2']).formats(), // Validation for AsyncAPI v3 is still WIP.
   rules: {
     /**
      * Root Object rules
@@ -80,7 +81,7 @@ export const coreRuleset = {
 
 export const recommendedRuleset = {
   description: 'Recommended AsyncAPI x.x.x ruleset.',
-  formats: [...aas2AllFormats],
+  formats: AsyncAPIFormats.filterByMajorVersions(['2']).formats(), // Validation for AsyncAPI v3 is still WIP.
   rules: {
     /**
      * Root Object rules
@@ -188,6 +189,7 @@ export const recommendedRuleset = {
      */
     'asyncapi-unused-component': {
       description: 'Potentially unused component has been detected in AsyncAPI document.',
+      formats: AsyncAPIFormats.filterByMajorVersions(['2']).formats(), // Validation for AsyncAPI v3 is still WIP.
       recommended: true,
       resolved: false,
       severity: 'info',
diff --git a/src/ruleset/v2/ruleset.ts b/src/ruleset/v2/ruleset.ts
index 419a6a0..a9c6096 100644
--- a/src/ruleset/v2/ruleset.ts
+++ b/src/ruleset/v2/ruleset.ts
@@ -1,6 +1,6 @@
 /* eslint-disable sonarjs/no-duplicate-string */
 
-import { aas2All as aas2AllFormats } from '../formats';
+import { AsyncAPIFormats } from '../formats';
 import { truthy, pattern } from '@stoplight/spectral-functions';
 
 import { channelParameters } from './functions/channelParameters';
@@ -20,7 +20,7 @@ import type { Parser } from '../../parser';
 
 export const v2CoreRuleset = {
   description: 'Core AsyncAPI 2.x.x ruleset.',
-  formats: [...aas2AllFormats],
+  formats: AsyncAPIFormats.filterByMajorVersions(['2']).formats(),
   rules: {
     /**
      * Server Object rules
@@ -191,7 +191,6 @@ export const v2CoreRuleset = {
 export const v2SchemasRuleset = (parser: Parser) => {
   return {
     description: 'Schemas AsyncAPI 2.x.x ruleset.',
-    formats: [...aas2AllFormats],
     rules: {
       'asyncapi2-schemas': asyncApi2SchemaParserRule(parser),
       'asyncapi2-schema-default': {
@@ -244,7 +243,7 @@ export const v2SchemasRuleset = (parser: Parser) => {
 
 export const v2RecommendedRuleset = {
   description: 'Recommended AsyncAPI 2.x.x ruleset.',
-  formats: [...aas2AllFormats],
+  formats: AsyncAPIFormats.filterByMajorVersions(['2']).formats(),
   rules: {
     /**
      * Root Object rules
@@ -334,7 +333,7 @@ export const v2RecommendedRuleset = {
     'asyncapi2-message-messageId': {
       description: 'Message should have a "messageId" field defined.',
       recommended: true,
-      formats: aas2AllFormats.slice(4), // from 2.4.0
+      formats: AsyncAPIFormats.filterByMajorVersions(['2']).excludeByVersions(['2.0.0', '2.1.0', '2.2.0', '2.3.0']).formats(), // message.messageId is available starting from v2.4.      
       given: [
         '$.channels.*.[publish,subscribe][?(@property === "message" && @.oneOf == void 0)]',
         '$.channels.*.[publish,subscribe].message.oneOf.*',


Test patch:
diff --git a/test/parse.spec.ts b/test/parse.spec.ts
index cdca94a..aec7002 100644
--- a/test/parse.spec.ts
+++ b/test/parse.spec.ts
@@ -1,13 +1,13 @@
 import { Document } from '@stoplight/spectral-core';
 
-import { AsyncAPIDocumentV2 } from '../src/models';
+import { AsyncAPIDocumentV2, AsyncAPIDocumentV3 } from '../src/models';
 import { Parser } from '../src/parser';
 import { xParserApiVersion } from '../src/constants';
 
 describe('parse()', function() {
   const parser = new Parser();
 
-  it('should parse valid document', async function() {
+  it('should parse valid document', async function() { 
     const documentRaw = {
       asyncapi: '2.0.0',
       info: {
@@ -22,6 +22,20 @@ describe('parse()', function() {
     expect(diagnostics.length > 0).toEqual(true);
   });
 
+  it('should not parse valid v3 document', async function() { 
+    const documentRaw = {
+      asyncapi: '3.0.0',
+      info: {
+        title: 'Valid AsyncApi document',
+        version: '1.0',
+      },
+      channels: {}
+    };
+    const { document, diagnostics } = await parser.parse(documentRaw);
+    expect(document).toBeInstanceOf(AsyncAPIDocumentV3);
+    expect(diagnostics.length === 0).toEqual(true);
+  });
+
   it('should parse invalid document', async function() {
     const documentRaw = {
       asyncapi: '2.0.0',
@@ -36,6 +50,20 @@ describe('parse()', function() {
     expect(diagnostics.length > 0).toEqual(true);
   });
 
+  it('should parse invalid v3 document', async function() {
+    const documentRaw = {
+      asyncapi: '3.0.0',
+      not_a_valid_info_object: {
+        title: 'Invalid AsyncApi document',
+        version: '1.0',
+      },
+    };
+    const { document, diagnostics } = await parser.parse(documentRaw);
+    
+    expect(document).toBeInstanceOf(AsyncAPIDocumentV3);
+    expect(diagnostics.length === 0).toEqual(true); // Validation in v3 is still not enabled. This test will intentionally fail once that changes.
+  });
+
   it('should return extras', async function() {
     const documentRaw = {
       asyncapi: '2.0.0',
diff --git a/test/ruleset/formats.spec.ts b/test/ruleset/formats.spec.ts
index 5de1168..41474d6 100644
--- a/test/ruleset/formats.spec.ts
+++ b/test/ruleset/formats.spec.ts
@@ -1,117 +1,82 @@
-import { aas2, aas2_0, aas2_1, aas2_2, aas2_3, aas2_4, aas2_5, aas2_6 } from '../../src/ruleset/formats';
+import { schemas } from '@asyncapi/specs';
+import { AsyncAPIFormats, Formats } from '../../src/ruleset/formats';
+import { getSemver } from '../../src/utils';
 
-describe('AsyncAPI format', () => {
-  describe('AsyncAPI 2.x', () => {
-    it.each(['2.0.0', '2.1.0', '2.2.0', '2.3.0', '2.0.17', '2.1.37', '2.9.0', '2.9.3'])(
-      'recognizes %s version correctly',
-      version => {
-        expect(aas2({ asyncapi: version }, null)).toBe(true);
-      },
-    );
+import type { Format } from '@stoplight/spectral-core';
 
+describe('AsyncAPI format', () => {
+  describe('Recognizes versions', () => {
     const testCases = [
-      { asyncapi: '3.0' },
-      { asyncapi: '3.0.0' },
-      { asyncapi: '2' },
-      { asyncapi: '2.0' },
-      { asyncapi: '2.0.' },
-      { asyncapi: '2.0.01' },
-      { asyncapi: '1.0' },
-      { asyncapi: 2 },
-      { asyncapi: null },
-      { openapi: '4.0' },
-      { openapi: '2.0' },
-      { openapi: null },
-      { swagger: null },
-      { swagger: '3.0' },
-      {},
-      null,
+      { formatVersion: '2.0.0', document: {asyncapi: '2.0.0'}, existsFormat: true, result: true },
+      { formatVersion: '2.0.0', document: {asyncapi: '2.1.8'}, existsFormat: true, result: false },
+      { formatVersion: '2.1.8', document: {asyncapi: '2.0.0'}, existsFormat: true, result: false },
+      { formatVersion: '2.1.3', document: {asyncapi: '2.1.3'}, existsFormat: true, result: true },
+      { formatVersion: '2.1.3', document: {asyncapi: '2.0.0'}, existsFormat: true, result: false },
+      { formatVersion: '2.0.0', document: {asyncapi: '2.1.3'}, existsFormat: true, result: false },
+      { formatVersion: '2.2.9', document: {asyncapi: '2.2.9'}, existsFormat: true, result: true },
+      { formatVersion: '2.2.9', document: {asyncapi: '2.0.0'}, existsFormat: true, result: false },
+      { formatVersion: '2.0.0', document: {asyncapi: '2.2.9'}, existsFormat: true, result: false },
+      { formatVersion: '2.6.5', document: {asyncapi: '2.6.5'}, existsFormat: true, result: true },
+      { formatVersion: '2.6.5', document: {asyncapi: '2.0.0'}, existsFormat: true, result: false },
+      { formatVersion: '2.0.0', document: {asyncapi: '2.6.5'}, existsFormat: true, result: false },
+      { formatVersion: '3.0.10', document: {asyncapi: '3.0.10'}, existsFormat: true, result: true },
+      { formatVersion: '3.0.0', document: {openapi: '3.0.0'}, existsFormat: true, result: false },
+      { formatVersion: '3.0.0', document: null, existsFormat: true, result: false },
+      { formatVersion: '999.999.0', document: {}, existsFormat: false, result: false },
+      { formatVersion: '19923.1.0', document: {}, existsFormat: false, result: false },
+      { formatVersion: '2.99.0', document: {}, existsFormat: false, result: false },
     ];
-
-    it.each(testCases)('does not recognize invalid document %o', document => {
-      expect(aas2(document, null)).toBe(false);
+      
+    it.each(testCases)('format formatVersion recognizes version %p correctly', testCase => {
+      const format = AsyncAPIFormats.find(testCase.formatVersion);
+      expect(format !== undefined).toEqual(testCase.existsFormat);
+      if (format !== undefined) {
+        expect(format(testCase.document, null)).toEqual(testCase.result);
+      }
     });
   });
+});
 
-  describe('AsyncAPI 2.0', () => {
-    it.each(['2.0.0', '2.0.3'])('recognizes %s version correctly', version => {
-      expect(aas2_0({ asyncapi: version }, null)).toBe(true);
-    });
-
-    it.each(['2', '2.0', '2.1.0', '2.1.3'])('does not recognize %s version', version => {
-      expect(aas2_0({ asyncapi: version }, null)).toBe(false);
-    });
+describe('AsyncAPIFormats collection', () => {
+  it('Is a Formats collection', () => {
+    expect(AsyncAPIFormats).toBeInstanceOf(Formats);
   });
 
-  describe('AsyncAPI 2.1', () => {
-    it.each(['2.1.0', '2.1.37'])('recognizes %s version correctly', version => {
-      expect(aas2_1({ asyncapi: version }, null)).toBe(true);
-    });
-
-    it.each(['2', '2.1', '2.0.0', '2.2.0', '2.2.3'])('does not recognize %s version', version => {
-      expect(aas2_1({ asyncapi: version }, null)).toBe(false);
-    });
+  it('Returns all formats as array', () => {
+    const formats = AsyncAPIFormats.formats();
+    expect(formats).toHaveLength(Object.keys(schemas).length);    
   });
 
-  describe('AsyncAPI 2.2', () => {
-    it.each(['2.2.0', '2.2.3'])('recognizes %s version correctly', version => {
-      expect(aas2_2({ asyncapi: version }, null)).toBe(true);
-    });
-
-    it.each(['2', '2.2', '2.0.0', '2.1.0', '2.1.37', '2.3.0', '2.3.3'])('does not recognize %s version', version => {
-      expect(aas2_2({ asyncapi: version }, null)).toBe(false);
-    });
+  it('Finds existing version', () => {
+    expect(AsyncAPIFormats.find('2.0.0') !== undefined).toBeTruthy();
   });
 
-  describe('AsyncAPI 2.3', () => {
-    it.each(['2.3.0', '2.3.3'])('recognizes %s version correctly', version => {
-      expect(aas2_3({ asyncapi: version }, null)).toBe(true);
-    });
-
-    it.each(['2', '2.3', '2.0.0', '2.1.0', '2.1.37', '2.2.0', '2.4.0', '2.4.3'])(
-      'does not recognize %s version',
-      version => {
-        expect(aas2_3({ asyncapi: version }, null)).toBe(false);
-      },
-    );
+  it('Finds non-existing version', () => {
+    expect(AsyncAPIFormats.find('9999.9999.99999-rc') === undefined).toBeTruthy();
   });
 
-  describe('AsyncAPI 2.4', () => {
-    it.each(['2.4.0', '2.4.3'])('recognizes %s version correctly', version => {
-      expect(aas2_4({ asyncapi: version }, null)).toBe(true);
-    });
+  it('Filters by major version', () => {
+    const formats = AsyncAPIFormats;
+    formats.set('999.0.0', (_: unknown): boolean => true);
 
-    it.each(['2', '2.3', '2.0.0', '2.1.0', '2.1.37', '2.2.0', '2.3.0', '2.5.0', '2.5.3'])(
-      'does not recognize %s version',
-      version => {
-        expect(aas2_4({ asyncapi: version }, null)).toBe(false);
-      },
-    );
-  });
+    const filteredMajorVersion = '2';
+    const previousLenght = AsyncAPIFormats.formats().length;
+    const filteredFormats = AsyncAPIFormats.filterByMajorVersions([filteredMajorVersion]);
 
-  describe('AsyncAPI 2.5', () => {
-    it.each(['2.5.0', '2.5.2'])('recognizes %s version correctly', version => {
-      expect(aas2_5({ asyncapi: version }, null)).toBe(true);
+    expect(filteredFormats.size).toBeLessThan(previousLenght);
+    filteredFormats.forEach((_, version) => {
+      expect(String(getSemver(version).major)).toEqual(filteredMajorVersion);
     });
-
-    it.each(['2', '2.3', '2.0.0', '2.1.0', '2.1.37', '2.2.0', '2.3.0', '2.4.0', '2.4.3', '2.6.0', '2.6.4'])(
-      'does not recognize %s version',
-      version => {
-        expect(aas2_5({ asyncapi: version }, null)).toBe(false);
-      },
-    );
   });
 
-  describe('AsyncAPI 2.6', () => {
-    it.each(['2.6.0', '2.6.2'])('recognizes %s version correctly', version => {
-      expect(aas2_6({ asyncapi: version }, null)).toBe(true);
-    });
+  it('Excludes by version', () => {
+    const excludedVersions = ['2.0.0', '2.1.0', '2.6.0'];
+    const previousLenght = AsyncAPIFormats.formats().length;
+    const filteredFormats = AsyncAPIFormats.excludeByVersions(excludedVersions);
 
-    it.each(['2', '2.3', '2.0.0', '2.1.0', '2.1.37', '2.2.0', '2.3.0', '2.4.0', '2.4.3', '2.5.0', '2.5.3', '2.7.0', '2.7.4'])(
-      'does not recognize %s version',
-      version => {
-        expect(aas2_6({ asyncapi: version }, null)).toBe(false);
-      },
-    );
+    expect(filteredFormats.size).toEqual(previousLenght - excludedVersions.length);
+    excludedVersions.forEach((version) => {
+      expect(filteredFormats.find(version)).toBeFalsy();
+    });
   });
 });