diff --git a/src/constants.ts b/src/constants.ts index 27c1faf72..ac5f77c51 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -8,3 +8,5 @@ export const xParserOriginalSchemaFormat = 'x-parser-original-schema-format'; export const xParserOriginalTraits = 'x-parser-original-traits'; export const xParserCircular = 'x-parser-circular'; + +export const EXTENSION_REGEX = /^x-[\w\d\.\-\_]+$/; diff --git a/src/models/asyncapi.ts b/src/models/asyncapi.ts index b370204c0..e5f95f030 100644 --- a/src/models/asyncapi.ts +++ b/src/models/asyncapi.ts @@ -1,26 +1,29 @@ import { InfoInterface } from "./info"; import { BaseModel } from "./base"; + import { AsyncAPIDocumentV2 } from "./v2"; import { AsyncAPIDocumentV3 } from "./v3"; -export interface AsyncAPIDocumentInterface extends BaseModel { - version(): string; - info(): InfoInterface +import { ExternalDocsMixinInterface, SpecificationExtensionsMixinInterface, TagsMixinInterface } from "./mixins"; + +export interface AsyncAPIDocumentInterface extends BaseModel, ExternalDocsMixinInterface, SpecificationExtensionsMixinInterface, TagsMixinInterface { + version(): string; + info(): InfoInterface; } export function newAsyncAPIDocument(json: Record): AsyncAPIDocumentInterface { - const version = json['asyncapi']; // Maybe this should be an arg. - if (version == undefined || version == null || version == '') { - throw new Error('Missing AsyncAPI version in document'); - } + const version = json['asyncapi']; // Maybe this should be an arg. + if (version == undefined || version == null || version == '') { + throw new Error('Missing AsyncAPI version in document'); + } - const major = version.split(".")[0]; - switch (major) { - case '2': - return new AsyncAPIDocumentV2(json); - case '3': - return new AsyncAPIDocumentV3(json); - default: - throw new Error(`Unsupported version: ${version}`); - } -} \ No newline at end of file + const major = version.split(".")[0]; + switch (major) { + case '2': + return new AsyncAPIDocumentV2(json); + case '3': + return new AsyncAPIDocumentV3(json); + default: + throw new Error(`Unsupported version: ${version}`); + } +} diff --git a/src/models/base.ts b/src/models/base.ts index f5ac549b5..7e09c8007 100644 --- a/src/models/base.ts +++ b/src/models/base.ts @@ -1,6 +1,6 @@ export class BaseModel { constructor( - private readonly _json: Record, + protected readonly _json: Record, ) {} json>(): T; diff --git a/src/models/mixins/bindings.ts b/src/models/mixins/bindings.ts new file mode 100644 index 000000000..41ec9a5d0 --- /dev/null +++ b/src/models/mixins/bindings.ts @@ -0,0 +1,33 @@ +import { BaseModel } from "../base"; + +export interface BindingsMixinInterface { + hasBindings(): boolean; + hasBindings(protocol: string): boolean; + bindings(): any[]; // TODO: Change type to Tag + bindings(protocol: string): any; // TODO: Change type to Tag +} + +export abstract class BindingsMixin extends BaseModel implements BindingsMixinInterface { + hasBindings(): boolean; + hasBindings(protocol: string): boolean; + hasBindings(protocol?: string): boolean { + const bindings = this.bindings(protocol!); + if (typeof protocol === 'string') { + return Boolean(bindings); + } + return Object.keys(bindings || {}).length > 0; + }; + + + bindings(): any[]; + bindings(protocol: string): any; + bindings(protocol?: string): any | any[] { + if (typeof protocol === 'string') { + if (this._json.bindings && typeof this._json.bindings === 'object') { + return this._json.bindings[protocol]; + } + return; + } + return this._json.bindings || {}; + }; +} diff --git a/src/models/mixins/description.ts b/src/models/mixins/description.ts new file mode 100644 index 000000000..f97746b3f --- /dev/null +++ b/src/models/mixins/description.ts @@ -0,0 +1,16 @@ +import { BaseModel } from "../base"; + +export interface DescriptionMixinInterface { + hasDescription(): boolean; + description(): string | undefined; +} + +export abstract class DescriptionMixin extends BaseModel implements DescriptionMixinInterface { + hasDescription() { + return Boolean(this._json.description); + }; + + description(): string | undefined { + return this._json.description; + } +} diff --git a/src/models/mixins/external-docs.ts b/src/models/mixins/external-docs.ts new file mode 100644 index 000000000..6dd0e3969 --- /dev/null +++ b/src/models/mixins/external-docs.ts @@ -0,0 +1,17 @@ +import { BaseModel } from "../base"; + +export interface ExternalDocsMixinInterface { + hasExternalDocs(): boolean; + externalDocs(): any; // TODO: Change type to ExternalDocs +} + +export abstract class ExternalDocsMixin extends BaseModel implements ExternalDocsMixinInterface { + hasExternalDocs(): boolean { + return !!(this._json.externalDocs && Object.keys(this._json.externalDocs).length); + }; + + // TODO: implement it when the ExternalDocs class will be implemented + externalDocs(): any { + return; + }; +} diff --git a/src/models/mixins/index.ts b/src/models/mixins/index.ts new file mode 100644 index 000000000..6a3397514 --- /dev/null +++ b/src/models/mixins/index.ts @@ -0,0 +1,41 @@ +import type { BaseModel } from '../base'; + +export * from './bindings'; +export * from './description'; +export * from './external-docs'; +export * from './specification-extensions'; +export * from './tags'; + +export interface Constructor extends Function { + new (...any: any[]): T; +} + +export interface MixinType extends Function { + prototype: T; +} + +export function Mixin(a: typeof BaseModel): typeof BaseModel; +export function Mixin(a: typeof BaseModel, b: MixinType): typeof BaseModel & Constructor; +export function Mixin(a: typeof BaseModel, b: MixinType, c: MixinType): typeof BaseModel & Constructor & Constructor; +export function Mixin(a: typeof BaseModel, b: MixinType, c: MixinType, d: MixinType): typeof BaseModel & Constructor & Constructor & Constructor; +export function Mixin(a: typeof BaseModel, b: MixinType, c: MixinType, d: MixinType, e: MixinType): typeof BaseModel & Constructor & Constructor & Constructor & Constructor; +export function Mixin(a: typeof BaseModel, b: MixinType, c: MixinType, d: MixinType, e: MixinType, f: MixinType): typeof BaseModel & Constructor & Constructor & Constructor & Constructor & Constructor; +export function Mixin(baseModel: typeof BaseModel, ...constructors: any[]) { + return mixin(class extends baseModel {}, constructors); +} + +function mixin(derivedCtor: any, constructors: any[]): typeof BaseModel { + constructors.forEach((baseCtor) => { + Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => { + if (name === 'constructor') { + return; + } + Object.defineProperty( + derivedCtor.prototype, + name, + Object.getOwnPropertyDescriptor(baseCtor.prototype, name) || Object.create(null), + ); + }); + }); + return derivedCtor; +} \ No newline at end of file diff --git a/src/models/mixins/specification-extensions.ts b/src/models/mixins/specification-extensions.ts new file mode 100644 index 000000000..873e2fe45 --- /dev/null +++ b/src/models/mixins/specification-extensions.ts @@ -0,0 +1,39 @@ +import { BaseModel } from "../base"; + +import { EXTENSION_REGEX } from '../../constants'; + +export interface SpecificationExtensionsMixinInterface { + hasExtensions(): boolean; + hasExtensions(name: string): boolean; + extensions(): Record; + extensions(name: string): any; +} + +export abstract class SpecificationExtensionsMixin extends BaseModel implements SpecificationExtensionsMixinInterface { + hasExtensions(): boolean; + hasExtensions(name: string): boolean; + hasExtensions(name?: string): boolean { + const extensions = this.extensions(name!); + if (typeof name === 'string') { + return Boolean(extensions); + } + return Object.keys(extensions || {}).length > 0; + }; + + extensions(): any[]; + extensions(name: string): any; + extensions(name?: string): any | any[] { + if (typeof name === 'string') { + name = name.startsWith('x-') ? name : `x-${name}`; + return this._json[name]; + } + + const result: Record = {}; + Object.entries(this._json).forEach(([key, value]) => { + if (EXTENSION_REGEX.test(key)) { + result[String(key)] = value; + } + }); + return result; + }; +} diff --git a/src/models/mixins/tags.ts b/src/models/mixins/tags.ts new file mode 100644 index 000000000..2554b39a3 --- /dev/null +++ b/src/models/mixins/tags.ts @@ -0,0 +1,36 @@ +import { BaseModel } from "../base"; + +export interface TagsMixinInterface { + hasTags(): boolean; + hasTags(name: string): boolean; + tags(): any[]; // TODO: Change type to Tag + tags(name: string): any; // TODO: Change type to Tag +} + +export abstract class TagsMixin extends BaseModel implements TagsMixinInterface { + hasTags(): boolean; + hasTags(name: string): boolean; + hasTags(name?: string): boolean { + if (!Array.isArray(this._json.tags) || !this._json.tags.length) { + return false; + } + if (typeof name === 'string') { + return this._json.tags.some((t: any) => t.name === name); + } + return true; + }; + + + // TODO: return instance(s) of Tag model when the Tag class will be implemented + tags(): any[]; // TODO: Change type to Tag + tags(name: string): any; // TODO: Change type to Tag + tags(name?: string): any | any[] { // TODO: Change type to Tag + if (typeof name === 'string') { + if (Array.isArray(this._json.tags)) { + return this._json.tags.find((t: any) => t.name === name); + } + return; + } + return this._json.tags || []; + }; +} diff --git a/src/models/v2/asyncapi.ts b/src/models/v2/asyncapi.ts index e170a7716..7614fd5fc 100644 --- a/src/models/v2/asyncapi.ts +++ b/src/models/v2/asyncapi.ts @@ -2,12 +2,17 @@ import { AsyncAPIDocumentInterface } from "../../models"; import { BaseModel } from "../base"; import { Info } from "./info"; -export class AsyncAPIDocument extends BaseModel implements AsyncAPIDocumentInterface { - version(): string { - return this.json("asyncapi"); - } - - info(): Info { - return new Info(this.json("info")); - } +import { Mixin, ExternalDocsMixin, SpecificationExtensionsMixin, TagsMixin } from '../mixins'; + +export class AsyncAPIDocument + extends Mixin(BaseModel, ExternalDocsMixin, SpecificationExtensionsMixin, TagsMixin) + implements AsyncAPIDocumentInterface { + + version(): string { + return this.json("asyncapi"); + } + + info(): Info { + return new Info(this.json("info")); + } } diff --git a/src/models/v3/asyncapi.ts b/src/models/v3/asyncapi.ts index 08802da35..113a738fe 100644 --- a/src/models/v3/asyncapi.ts +++ b/src/models/v3/asyncapi.ts @@ -2,12 +2,17 @@ import { AsyncAPIDocumentInterface } from "../../models/asyncapi"; import { BaseModel } from "../base"; import { Info } from "./info"; -export class AsyncAPIDocument extends BaseModel implements AsyncAPIDocumentInterface { - version(): string { - return this.json("asyncapi"); - } +import { Mixin, ExternalDocsMixin, SpecificationExtensionsMixin, TagsMixin } from '../mixins'; - info(): Info { - return new Info(this.json("info")); - } +export class AsyncAPIDocument + extends Mixin(BaseModel, ExternalDocsMixin, SpecificationExtensionsMixin, TagsMixin) + implements AsyncAPIDocumentInterface { + + version(): string { + return this.json("asyncapi"); + } + + info(): Info { + return new Info(this.json("info")); + } } diff --git a/test/models/mixins/bindings.spec.ts b/test/models/mixins/bindings.spec.ts new file mode 100644 index 000000000..6438e391d --- /dev/null +++ b/test/models/mixins/bindings.spec.ts @@ -0,0 +1,49 @@ +import { BaseModel } from '../../../src/models/base'; +import { BindingsMixin, Mixin } from '../../../src/models/mixins'; + +class Model extends Mixin(BaseModel, BindingsMixin) {}; + +const doc1 = { bindings: { amqp: { test: 'test1' } } }; +const doc2 = { bindings: {} }; +const doc3 = {}; +const d1 = new Model(doc1); +const d2 = new Model(doc2); +const d3 = new Model(doc3); + +describe('Bindings mixin', function() { + describe('.hasBindings()', function() { + it('should return a boolean indicating if the object has bindings', function() { + expect(d1.hasBindings()).toEqual(true); + expect(d2.hasBindings()).toEqual(false); + expect(d3.hasBindings()).toEqual(false); + }); + + it('should return a boolean indicating if the bindings object has appropriate binding by name', function() { + expect(d1.hasBindings('amqp')).toEqual(true); + expect(d1.hasBindings('http')).toEqual(false); + expect(d2.hasBindings('amqp')).toEqual(false); + expect(d3.hasBindings('amqp')).toEqual(false); + }); + }); + + describe('.bindings()', function() { + it('should return a map of bindings', function() { + expect(d1.bindings()).toEqual(doc1.bindings); + }); + + it('should return an empty object', function() { + expect(d2.bindings()).toEqual({}); + expect(d3.bindings()).toEqual({}); + }); + + it('should return a binding object', function() { + expect(d1.bindings('amqp')).toEqual(doc1.bindings.amqp); + }); + + it('should return a undefined', function() { + expect(d1.bindings('http')).toEqual(undefined); + expect(d2.bindings('amqp')).toEqual(undefined); + expect(d3.bindings('amqp')).toEqual(undefined); + }); + }); +}); diff --git a/test/models/mixins/description.spec.ts b/test/models/mixins/description.spec.ts new file mode 100644 index 000000000..99027ac2b --- /dev/null +++ b/test/models/mixins/description.spec.ts @@ -0,0 +1,32 @@ +import { BaseModel } from '../../../src/models/base'; +import { DescriptionMixin, Mixin } from '../../../src/models/mixins'; + +class Model extends Mixin(BaseModel, DescriptionMixin) {}; + +const doc1 = { description: 'Testing' }; +const doc2 = { description: '' }; +const doc3 = {}; +const d1 = new Model(doc1); +const d2 = new Model(doc2); +const d3 = new Model(doc3); + +describe('Description mixin', function() { + describe('.hasDescription()', function() { + it('should return a boolean indicating if the object has description', function() { + expect(d1.hasDescription()).toEqual(true); + expect(d2.hasDescription()).toEqual(false); + expect(d3.hasDescription()).toEqual(false); + }); + }); + + describe('.description()', function() { + it('should return a value', function() { + expect(d1.description()).toEqual(doc1.description); + expect(d2.description()).toEqual(''); + }); + + it('should return an undefined', function() { + expect(d3.description()).toEqual(undefined); + }); + }); +}); diff --git a/test/models/mixins/external-docs.spec.ts b/test/models/mixins/external-docs.spec.ts new file mode 100644 index 000000000..ce722b893 --- /dev/null +++ b/test/models/mixins/external-docs.spec.ts @@ -0,0 +1,36 @@ +import { BaseModel } from '../../../src/models/base'; +import { ExternalDocsMixin, Mixin } from '../../../src/models/mixins'; + +class Model extends Mixin(BaseModel, ExternalDocsMixin) {}; + +const doc1 = { externalDocs: { url: 'test.com' } }; +const doc2 = { externalDocs: {} }; +const doc3 = {}; +const d1 = new Model(doc1); +const d2 = new Model(doc2); +const d3 = new Model(doc3); + +describe('ExternalDocs mixin', function() { + describe('.hasExternalDocs()', function() { + it('should return a boolean indicating if the object has externalDocs', function() { + expect(d1.hasExternalDocs()).toEqual(true); + expect(d2.hasExternalDocs()).toEqual(false); + expect(d3.hasExternalDocs()).toEqual(false); + }); + }); + + // TODO: implement it when the ExternalDocs class will be implemented + describe('.externalDocs()', function() { + // it('should return a externalDocs object', function() { + // expect(d1.externalDocs() instanceof ExternalDocs).toEqual(true); + // expect(d1.externalDocs().json()).toEqual(doc1.externalDocs); + + // expect(d2.externalDocs() instanceof ExternalDocs).toEqual(true); + // expect(d2.externalDocs().json()).toEqual(doc2.externalDocs); + // }); + + it('should return a undefined', function() { + expect(d3.externalDocs()).toEqual(undefined); + }); + }); +}); diff --git a/test/models/mixins/inheritance.ts b/test/models/mixins/inheritance.ts new file mode 100644 index 000000000..439027488 --- /dev/null +++ b/test/models/mixins/inheritance.ts @@ -0,0 +1,77 @@ +import { + BindingsMixin, + DescriptionMixin, + ExternalDocsMixin, + SpecificationExtensionsMixin, + TagsMixin, +} from '../../../src/models/mixins'; + +export function assertBindingsMixinInheritance(model: typeof BindingsMixin) { + describe('BindingsMixin inheritance', function() { + it(`check if ${model.name} model has inherited methods from BindingsMixin`, function() { + expect(model.prototype.hasBindings).not.toEqual(undefined); + expect(typeof model.prototype.hasBindings).toEqual('function'); + expect(model.prototype.hasBindings === BindingsMixin.prototype.hasBindings).toEqual(true); + + expect(model.prototype.bindings).not.toEqual(undefined); + expect(typeof model.prototype.bindings).toEqual('function'); + expect(model.prototype.bindings === BindingsMixin.prototype.bindings).toEqual(true); + }); + }); +} + +export function assertDescriptionMixinInheritance(model: typeof DescriptionMixin) { + describe('DescriptionMixin inheritance', function() { + it(`check if ${model.name} model has inherited methods from DescriptionMixin`, function() { + expect(model.prototype.hasDescription).not.toEqual(undefined); + expect(typeof model.prototype.hasDescription).toEqual('function'); + expect(model.prototype.hasDescription === DescriptionMixin.prototype.hasDescription).toEqual(true); + + expect(model.prototype.description).not.toEqual(undefined); + expect(typeof model.prototype.description).toEqual('function'); + expect(model.prototype.description === DescriptionMixin.prototype.description).toEqual(true); + }); + }); +} + +export function assertExternalDocsMixinInheritance(model: typeof ExternalDocsMixin) { + describe('ExternalDocsMixin inheritance', function() { + it(`check if ${model.name} model has inherited methods from ExternalDocsMixin`, function() { + expect(model.prototype.hasExternalDocs).not.toEqual(undefined); + expect(typeof model.prototype.hasExternalDocs).toEqual('function'); + expect(model.prototype.hasExternalDocs === ExternalDocsMixin.prototype.hasExternalDocs).toEqual(true); + + expect(model.prototype.externalDocs).not.toEqual(undefined); + expect(typeof model.prototype.externalDocs).toEqual('function'); + expect(model.prototype.externalDocs === ExternalDocsMixin.prototype.externalDocs).toEqual(true); + }); + }); +} + +export function assertSpecificationExtensionsMixinInheritance(model: typeof SpecificationExtensionsMixin) { + describe('SpecificationExtensionsMixin inheritance', function() { + it(`check if ${model.name} model has inherited methods from SpecificationExtensionsMixin`, function() { + expect(model.prototype.hasExtensions).not.toEqual(undefined); + expect(typeof model.prototype.hasExtensions).toEqual('function'); + expect(model.prototype.hasExtensions === SpecificationExtensionsMixin.prototype.hasExtensions).toEqual(true); + + expect(model.prototype.extensions).not.toEqual(undefined); + expect(typeof model.prototype.extensions).toEqual('function'); + expect(model.prototype.extensions === SpecificationExtensionsMixin.prototype.extensions).toEqual(true); + }); + }); +} + +export function assertTagsMixinInheritance(model: typeof TagsMixin) { + describe('TagsMixin inheritance', function() { + it(`check if ${model.name} model has inherited methods from TagsMixin`, function() { + expect(model.prototype.hasTags).not.toEqual(undefined); + expect(typeof model.prototype.hasTags).toEqual('function'); + expect(model.prototype.hasTags === TagsMixin.prototype.hasTags).toEqual(true); + + expect(model.prototype.tags).not.toEqual(undefined); + expect(typeof model.prototype.tags).toEqual('function'); + expect(model.prototype.tags === TagsMixin.prototype.tags).toEqual(true); + }); + }); +} diff --git a/test/models/mixins/specification-extensions.spec.ts b/test/models/mixins/specification-extensions.spec.ts new file mode 100644 index 000000000..3b08b33ab --- /dev/null +++ b/test/models/mixins/specification-extensions.spec.ts @@ -0,0 +1,60 @@ +import { BaseModel } from '../../../src/models/base'; +import { Mixin, SpecificationExtensionsMixin } from '../../../src/models/mixins'; + +class Model extends Mixin(BaseModel, SpecificationExtensionsMixin) {}; + +const doc1 = { 'x-test': 'testing', test: 'testing' }; +const doc2 = { test: 'testing' }; +const doc3 = {}; +const d1 = new Model(doc1); +const d2 = new Model(doc2); +const d3 = new Model(doc3); + +describe('SpecificationExtensions mixin', function() { + describe('.hasExtensions()', function() { + it('should return a boolean indicating if the object has extensions', function() { + expect(d1.hasExtensions()).toEqual(true); + expect(d2.hasExtensions()).toEqual(false); + expect(d3.hasExtensions()).toEqual(false); + }); + + it('should return a boolean indicating if the object has appropriate extension by key', function() { + expect(d1.hasExtensions('x-test')).toEqual(true); + expect(d1.hasExtensions('x-test2')).toEqual(false); + expect(d2.hasExtensions('x-test')).toEqual(false); + expect(d3.hasExtensions('x-test')).toEqual(false); + }); + + it('should return a boolean indicating if the object has appropriate extension by key (without x- prefix)', function() { + expect(d1.hasExtensions('test')).toEqual(true); + expect(d1.hasExtensions('test2')).toEqual(false); + expect(d2.hasExtensions('test')).toEqual(false); + expect(d3.hasExtensions('test')).toEqual(false); + }); + }); + + describe('.extensions()', function() { + it('should return a object with extensions', function() { + expect(d1.extensions()).toEqual({ 'x-test': 'testing' }); + }); + + it('should return a empty object', function() { + expect(d2.extensions()).toEqual({}); + expect(d3.extensions()).toEqual({}); + }); + + it('should return a value by key', function() { + expect(d1.extensions('x-test')).toEqual('testing'); + }); + + it('should return a value by key (without x- prefix)', function() { + expect(d1.extensions('test')).toEqual('testing'); + }); + + it('should return an undefined', function() { + expect(d1.extensions('x-test2')).toEqual(undefined); + expect(d2.extensions('x-test')).toEqual(undefined); + expect(d3.extensions('x-test')).toEqual(undefined); + }); + }); +}); diff --git a/test/models/mixins/tags.spec.ts b/test/models/mixins/tags.spec.ts new file mode 100644 index 000000000..c1389391d --- /dev/null +++ b/test/models/mixins/tags.spec.ts @@ -0,0 +1,55 @@ +import { BaseModel } from '../../../src/models/base'; +import { Mixin, TagsMixin } from '../../../src/models/mixins'; + +class Model extends Mixin(BaseModel, TagsMixin) {}; + +const doc1 = { tags: [{ name: 'test1' }, { name: 'test2' }] }; +const doc2 = { tags: [] }; +const doc3 = {}; +const d1 = new Model(doc1); +const d2 = new Model(doc2); +const d3 = new Model(doc3); + +describe('Tags mixin', function() { + describe('#hasTags()', function() { + it('should return a boolean indicating if the object has tags', function() { + expect(d1.hasTags()).toEqual(true); + expect(d2.hasTags()).toEqual(false); + expect(d3.hasTags()).toEqual(false); + }); + + it('should return a boolean indicating if the tags object has appropriate tag by name', function() { + expect(d1.hasTags('test1')).toEqual(true); + expect(d1.hasTags('test2')).toEqual(true); + expect(d1.hasTags('test3')).toEqual(false); + expect(d2.hasTags('test1')).toEqual(false); + expect(d3.hasTags('test1')).toEqual(false); + }); + }); + + describe('#tags()', function() { + it('should return an array of tag objects', function() { + expect(Array.isArray(d1.tags())).toEqual(true); + d1.tags().forEach((tag, i) => { + expect(tag).toEqual(doc1.tags[i]); + }); + }); + + it('should return an empty array', function() { + expect(d2.tags()).toEqual([]); + expect(d3.tags()).toEqual([]); + }); + + it('should return a tag object', function() { + expect(d1.tags('test1')).not.toEqual(undefined); + expect(d1.tags('test1')).toEqual(doc1.tags[0]); + expect(d1.tags('test2')).not.toEqual(undefined); + expect(d1.tags('test2')).toEqual(doc1.tags[1]); + }); + it('should return a undefined', function() { + expect(d1.tags('test3')).toEqual(undefined); + expect(d2.tags('test1')).toEqual(undefined); + expect(d3.tags('test1')).toEqual(undefined); + }); + }); +}); diff --git a/test/models/v2/asyncapi.spec.ts b/test/models/v2/asyncapi.spec.ts index cad7e418f..662938fd0 100644 --- a/test/models/v2/asyncapi.spec.ts +++ b/test/models/v2/asyncapi.spec.ts @@ -1,5 +1,11 @@ import { newAsyncAPIDocument, AsyncAPIDocumentV2, InfoV2, AsyncAPIDocumentV3 } from '../../../src/models'; +import { + assertExternalDocsMixinInheritance, + assertSpecificationExtensionsMixinInheritance, + assertTagsMixinInheritance, +} from '../mixins/inheritance'; + describe('AsyncAPIDocument model', function() { describe('.version()', function() { it('should return the value', function() { @@ -22,6 +28,12 @@ describe('AsyncAPIDocument model', function() { expect(d.info() instanceof InfoV2).toBeTruthy(); }); }); + + describe('mixins', function() { + assertExternalDocsMixinInheritance(AsyncAPIDocumentV2); + assertSpecificationExtensionsMixinInheritance(AsyncAPIDocumentV2); + assertTagsMixinInheritance(AsyncAPIDocumentV2); + }); }); describe('AsyncAPIDocument factory', function() { @@ -31,12 +43,14 @@ describe('AsyncAPIDocument factory', function() { expect(d.version()).toEqual(doc.asyncapi); expect(d).toBeInstanceOf(AsyncAPIDocumentV2); }); + it('should create a valid document from v3.0.0', function() { const doc = { asyncapi: "3.0.0" }; const d = newAsyncAPIDocument(doc) expect(d.version()).toEqual(doc.asyncapi); expect(d).toBeInstanceOf(AsyncAPIDocumentV3); }); + it('should fail trying to create a document from a non supported spec version', function() { const doc = { asyncapi: "99.99.99" }; expect(() => newAsyncAPIDocument(doc)).toThrow("Unsupported version: 99.99.99");