Skip to content

Commit

Permalink
feat(formats): support 2.1.0, 2.2.0, 2.3.0 AsyncAPI versions (#2067)
Browse files Browse the repository at this point in the history
  • Loading branch information
magicmatatjahu authored and P0lip committed Feb 24, 2022
1 parent 7fdf0e1 commit b0b008d
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 21 deletions.
61 changes: 54 additions & 7 deletions packages/formats/src/__tests__/asyncapi.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { asyncApi2 } from '../asyncapi';
import { aas2, aas2_0, aas2_1, aas2_2, aas2_3 } from '../asyncapi';

describe('AsyncApi format', () => {
describe('AsyncApi 2.{minor}.{patch}', () => {
it.each([['2.0.17'], ['2.9.0'], ['2.9.3']])('recognizes %s version correctly', (version: string) => {
expect(asyncApi2({ asyncapi: version }, null)).toBe(true);
});
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);
},
);

const testCases = [
{ asyncapi: '3.0' },
Expand All @@ -15,6 +18,7 @@ describe('AsyncApi format', () => {
{ asyncapi: '2.0.01' },
{ asyncapi: '1.0' },
{ asyncapi: 2 },
{ asyncapi: null },
{ openapi: '4.0' },
{ openapi: '2.0' },
{ openapi: null },
Expand All @@ -25,7 +29,50 @@ describe('AsyncApi format', () => {
];

it.each(testCases)('does not recognize invalid document %o', document => {
expect(asyncApi2(document, null)).toBe(false);
expect(aas2(document, null)).toBe(false);
});
});

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('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);
});
});

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);
});
});

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);
},
);
});
});
40 changes: 26 additions & 14 deletions packages/formats/src/asyncapi.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import type { Format } from '@stoplight/spectral-core';
import { isPlainObject } from '@stoplight/json';

type MaybeAsyncApi2 = Partial<{ asyncapi: unknown }>;
type MaybeAAS2 = { asyncapi: unknown } & Record<string, unknown>;

const bearsAStringPropertyNamed = (document: unknown, propertyName: string): boolean => {
return isPlainObject(document) && propertyName in document && typeof document[propertyName] === 'string';
};
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 version2Regex = /^2\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/;
const isAas2 = (document: unknown): document is { asyncapi: string } & Record<string, unknown> =>
isPlainObject(document) && 'asyncapi' in document && aas2Regex.test(String((document as MaybeAAS2).asyncapi));

export const asyncApi2: Format = document => {
if (!bearsAStringPropertyNamed(document, 'asyncapi')) {
return false;
}
export const aas2: Format = isAas2;
aas2.displayName = 'AsyncAPI 2.x';

const version = String((document as MaybeAsyncApi2).asyncapi);
// for backward compatibility
export const asyncApi2 = aas2;
export const asyncapi2 = aas2;

return version2Regex.test(version);
};
export const aas2_0: Format = (document: unknown): boolean =>
isAas2(document) && aas2_0Regex.test(String((document as MaybeAAS2).asyncapi));
aas2_0.displayName = 'AsyncAPI 2.0.x';

asyncApi2.displayName = 'AsyncAPI 2.x';
export const aas2_1: Format = (document: unknown): boolean =>
isAas2(document) && aas2_1Regex.test(String((document as MaybeAAS2).asyncapi));
aas2_1.displayName = 'AsyncAPI 2.1.x';

export { asyncApi2 as asyncapi2 };
export const aas2_2: Format = (document: unknown): boolean =>
isAas2(document) && aas2_2Regex.test(String((document as MaybeAAS2).asyncapi));
aas2_2.displayName = 'AsyncAPI 2.2.x';

export const aas2_3: Format = (document: unknown): boolean =>
isAas2(document) && aas2_3Regex.test(String((document as MaybeAAS2).asyncapi));
aas2_3.displayName = 'AsyncAPI 2.3.x';

0 comments on commit b0b008d

Please sign in to comment.