diff --git a/lib/models/asyncapi.js b/lib/models/asyncapi.js index 8bb3bc29f..164ceb63d 100644 --- a/lib/models/asyncapi.js +++ b/lib/models/asyncapi.js @@ -72,6 +72,14 @@ class AsyncAPIDocument extends Base { return createMapOfType(this._json.servers, Server); } + /** + * @returns {string[]} + */ + serverNames() { + if (!this._json.servers) return []; + return Object.keys(this._json.servers); + } + /** * @param {string} name - Name of the server. * @returns {Server} @@ -80,6 +88,20 @@ class AsyncAPIDocument extends Base { return getMapValueOfType(this._json.servers, name, Server); } + /** + * @returns {boolean} + */ + hasDefaultContentType() { + return !!this._json.defaultContentType; + } + + /** + * @returns {string|null} + */ + defaultContentType() { + return this._json.defaultContentType || null; + } + /** * @returns {boolean} */ @@ -110,13 +132,6 @@ class AsyncAPIDocument extends Base { return getMapValueOfType(this._json.channels, name, Channel, this); } - /** - * @returns {string} - */ - defaultContentType() { - return this._json.defaultContentType || null; - } - /** * @returns {boolean} */ diff --git a/lib/models/components.js b/lib/models/components.js index ac442df63..cad1a850a 100644 --- a/lib/models/components.js +++ b/lib/models/components.js @@ -28,6 +28,14 @@ class Components extends Base { } /** + * @returns {boolean} + */ + hasMessages() { + return !!this._json.messages; + } + + /** + * @param {string} name - Name of the message. * @returns {Message} */ message(name) { @@ -42,6 +50,14 @@ class Components extends Base { } /** + * @returns {boolean} + */ + hasSchemas() { + return !!this._json.schemas; + } + + /** + * @param {string} name - Name of the schema. * @returns {Schema} */ schema(name) { @@ -54,8 +70,16 @@ class Components extends Base { securitySchemes() { return createMapOfType(this._json.securitySchemes, SecurityScheme); } + + /** + * @returns {boolean} + */ + hasSecuritySchemes() { + return !!this._json.securitySchemes; + } /** + * @param {string} name - Name of the security schema. * @returns {SecurityScheme} */ securityScheme(name) { @@ -70,6 +94,14 @@ class Components extends Base { } /** + * @returns {boolean} + */ + hasParameters() { + return !!this._json.parameters; + } + + /** + * @param {string} name - Name of the channel parameter. * @returns {ChannelParameter} */ parameter(name) { @@ -84,6 +116,14 @@ class Components extends Base { } /** + * @returns {boolean} + */ + hasCorrelationIds() { + return !!this._json.correlationIds; + } + + /** + * @param {string} name - Name of the correlationId. * @returns {CorrelationId} */ correlationId(name) { @@ -98,6 +138,14 @@ class Components extends Base { } /** + * @returns {boolean} + */ + hasOperationTraits() { + return !!this._json.operationTraits; + } + + /** + * @param {string} name - Name of the operation trait. * @returns {OperationTrait} */ operationTrait(name) { @@ -112,6 +160,14 @@ class Components extends Base { } /** + * @returns {boolean} + */ + hasMessageTraits() { + return !!this._json.messageTraits; + } + + /** + * @param {string} name - Name of the message trait. * @returns {MessageTrait} */ messageTrait(name) { diff --git a/lib/models/schema.js b/lib/models/schema.js index cf9173405..2fcb40a62 100644 --- a/lib/models/schema.js +++ b/lib/models/schema.js @@ -1,4 +1,4 @@ -const { createMapOfType, mix } = require('../utils'); +const { createMapOfType, getMapValueOfType, mix } = require('../utils'); const Base = require('./base'); @@ -192,6 +192,14 @@ class Schema extends Base { properties() { return createMapOfType(this._json.properties, Schema); } + + /** + * @param {string} name - Name of the property. + * @returns {Schema} + */ + property(name) { + return getMapValueOfType(this._json.properties, name, Schema); + } /** * @returns {boolean|Schema} diff --git a/package.json b/package.json index cca3f6b4e..0e6b59f3d 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "test": "test" }, "scripts": { - "test": "nyc --reporter=html --reporter=text mocha --exclude test/browser_test.js --recursive && npm run test-browser", + "test": "npm run test-lib && npm run test-browser", "bundle": "browserify lib/browser.js | uglifyjs > dist/bundle.js", "docs": "jsdoc2md lib/parser.js -f lib/**/*.js > API.md", "types": "jsdoc -t node_modules/tsd-jsdoc/dist -r lib -d ./ && node ./scripts/fix-ts-types.js", @@ -17,6 +17,7 @@ "get-version": "echo $npm_package_version", "lint": "eslint --max-warnings 0 --config .eslintrc .", "gen-readme-toc": "markdown-toc -i README.md", + "test-lib": "nyc --reporter=html --reporter=text mocha --exclude test/browser_test.js --recursive", "test-browser": "npm run bundle && cp dist/bundle.js test/sample_browser/ && start-server-and-test 'http-server test/sample_browser --cors -s' 8080 'mocha --timeout 3000 test/browser_test.js' && rimraf test/sample_browser/bundle.js" }, "bugs": { diff --git a/test/models/asyncapi_test.js b/test/models/asyncapi_test.js index 12a395bd2..d654c01dc 100644 --- a/test/models/asyncapi_test.js +++ b/test/models/asyncapi_test.js @@ -56,6 +56,29 @@ describe('AsyncAPIDocument', function() { expect(d.servers().test2.constructor.name).to.equal('Server'); expect(d.servers().test2.json()).to.equal(doc.servers.test2); }); + + it('should return an empty object if the AsyncAPI document has no defined servers', function() { + const doc = {}; + const d = new AsyncAPIDocument(doc); + expect(typeof d.servers()).to.be.equal('object'); + expect(d.servers()).to.deep.equal({}); + }); + }); + + describe('#serverNames()', function() { + it('should return an array of strings', function() { + const doc = { servers: { test1: { url: 'test1' }, test2: { url: 'test2' } } }; + const d = new AsyncAPIDocument(doc); + expect(Array.isArray(d.serverNames())).to.be.equal(true); + expect(d.serverNames()).to.deep.equal(['test1', 'test2']); + }); + + it('should return an empty array if the AsyncAPI document has no defined servers', function() { + const doc = {}; + const d = new AsyncAPIDocument(doc); + expect(Array.isArray(d.serverNames())).to.be.equal(true); + expect(d.serverNames()).to.deep.equal([]); + }); }); describe('#server()', function() { @@ -79,6 +102,34 @@ describe('AsyncAPIDocument', function() { }); }); + describe('#hasDefaultContentType()', function() { + it('should return true if field exists', function() { + const doc = { defaultContentType: 'application/json' }; + const d = new AsyncAPIDocument(doc); + expect(d.hasDefaultContentType()).to.be.equal(true); + }); + + it('should return false if field does not exist', function() { + const doc = {}; + const d = new AsyncAPIDocument(doc); + expect(d.hasDefaultContentType()).to.be.equal(false); + }); + }); + + describe('#defaultContentType()', function() { + it('should return string if field exists', function() { + const doc = { defaultContentType: 'application/json' }; + const d = new AsyncAPIDocument(doc); + expect(d.defaultContentType()).to.be.equal('application/json'); + }); + + it('should return null if field does not exist', function() { + const doc = {}; + const d = new AsyncAPIDocument(doc); + expect(d.defaultContentType()).to.be.equal(null); + }); + }); + describe('#hasChannels()', function() { it('should return a boolean indicating if the AsyncAPI document has channels', function() { const doc = { channels: { test1: { description: 'test1' }, test2: { description: 'test2' } } }; @@ -100,6 +151,13 @@ describe('AsyncAPIDocument', function() { expect(d.channels().test2.constructor.name).to.equal('Channel'); expect(d.channels().test2.json()).to.equal(doc.channels.test2); }); + + it('should return an empty object if the AsyncAPI document has no defined channels', function() { + const doc = {}; + const d = new AsyncAPIDocument(doc); + expect(typeof d.channels()).to.be.equal('object'); + expect(d.servers()).to.deep.equal({}); + }); }); describe('#channelNames()', function() { @@ -109,6 +167,13 @@ describe('AsyncAPIDocument', function() { expect(Array.isArray(d.channelNames())).to.be.equal(true); expect(d.channelNames()).to.deep.equal(['test1', 'test2']); }); + + it('should return an empty array if the AsyncAPI document has no defined channels', function() { + const doc = {}; + const d = new AsyncAPIDocument(doc); + expect(Array.isArray(d.channelNames())).to.be.equal(true); + expect(d.channelNames()).to.deep.equal([]); + }); }); describe('#channel()', function() { diff --git a/test/models/components_test.js b/test/models/components_test.js index b3a267e7b..07c99d916 100644 --- a/test/models/components_test.js +++ b/test/models/components_test.js @@ -15,6 +15,24 @@ describe('Components', function() { expect(d.messages().test2.constructor.name).to.equal('Message'); expect(d.messages().test2.json()).to.equal(doc.messages.test2); }); + + it('should return an empty object if the components field has no defined messages', function() { + const doc = {}; + const d = new Components(doc); + expect(typeof d.messages()).to.be.equal('object'); + expect(d.messages()).to.deep.equal({}); + }); + }); + + describe('#hasMessages()', function() { + it('should return a boolean indicating if the components field has messages', function() { + const doc = { messages: { test1: { test: 'test1' }, test2: { test: 'test2' } } }; + const docNoMessages = { schemas: {} }; + const d = new Components(doc); + const d2 = new Components(docNoMessages); + expect(d.hasMessages()).to.equal(true); + expect(d2.hasMessages()).to.equal(false); + }); }); describe('#message()', function() { @@ -48,6 +66,24 @@ describe('Components', function() { expect(d.schemas().test2.constructor.name).to.equal('Schema'); expect(d.schemas().test2.json()).to.equal(doc.schemas.test2); }); + + it('should return an empty object if the components field has no defined schemas', function() { + const doc = {}; + const d = new Components(doc); + expect(typeof d.schemas()).to.be.equal('object'); + expect(d.schemas()).to.deep.equal({}); + }); + }); + + describe('#hasSchemas()', function() { + it('should return a boolean indicating if the components field has schemas', function() { + const doc = { schemas: { test1: { test: 'test1' }, test2: { test: 'test2' } } }; + const docNoSchemas = { messages: {} }; + const d = new Components(doc); + const d2 = new Components(docNoSchemas); + expect(d.hasSchemas()).to.equal(true); + expect(d2.hasSchemas()).to.equal(false); + }); }); describe('#schema()', function() { @@ -81,6 +117,24 @@ describe('Components', function() { expect(d.securitySchemes().test2.constructor.name).to.equal('SecurityScheme'); expect(d.securitySchemes().test2.json()).to.equal(doc.securitySchemes.test2); }); + + it('should return an empty object if the components field has no defined securitySchemes', function() { + const doc = {}; + const d = new Components(doc); + expect(typeof d.securitySchemes()).to.be.equal('object'); + expect(d.securitySchemes()).to.deep.equal({}); + }); + }); + + describe('#hasSecuritySchemes()', function() { + it('should return a boolean indicating if the components field has securitySchemes', function() { + const doc = { securitySchemes: { test1: { test: 'test1' }, test2: { test: 'test2' } } }; + const docNoSchemas = { messages: {} }; + const d = new Components(doc); + const d2 = new Components(docNoSchemas); + expect(d.hasSecuritySchemes()).to.equal(true); + expect(d2.hasSecuritySchemes()).to.equal(false); + }); }); describe('#securityScheme()', function() { @@ -114,6 +168,24 @@ describe('Components', function() { expect(d.parameters().test2.constructor.name).to.equal('ChannelParameter'); expect(d.parameters().test2.json()).to.equal(doc.parameters.test2); }); + + it('should return an empty object if the components field has no defined parameters', function() { + const doc = {}; + const d = new Components(doc); + expect(typeof d.parameters()).to.be.equal('object'); + expect(d.parameters()).to.deep.equal({}); + }); + }); + + describe('#hasParameters()', function() { + it('should return a boolean indicating if the components field has parameters', function() { + const doc = { parameters: { test1: { test: 'test1' }, test2: { test: 'test2' } } }; + const docNoSchemas = { messages: {} }; + const d = new Components(doc); + const d2 = new Components(docNoSchemas); + expect(d.hasParameters()).to.equal(true); + expect(d2.hasParameters()).to.equal(false); + }); }); describe('#parameter()', function() { @@ -147,6 +219,24 @@ describe('Components', function() { expect(d.correlationIds().test2.constructor.name).to.equal('CorrelationId'); expect(d.correlationIds().test2.json()).to.equal(doc.correlationIds.test2); }); + + it('should return an empty object if the components field has no defined correlationIds', function() { + const doc = {}; + const d = new Components(doc); + expect(typeof d.correlationIds()).to.be.equal('object'); + expect(d.correlationIds()).to.deep.equal({}); + }); + }); + + describe('#hasCorrelationIds()', function() { + it('should return a boolean indicating if the components field has correlationIds', function() { + const doc = { correlationIds: { test1: { test: 'test1' }, test2: { test: 'test2' } } }; + const docNoSchemas = { messages: {} }; + const d = new Components(doc); + const d2 = new Components(docNoSchemas); + expect(d.hasCorrelationIds()).to.equal(true); + expect(d2.hasCorrelationIds()).to.equal(false); + }); }); describe('#correlationId()', function() { @@ -180,6 +270,24 @@ describe('Components', function() { expect(d.operationTraits().test2.constructor.name).to.equal('OperationTrait'); expect(d.operationTraits().test2.json()).to.equal(doc.operationTraits.test2); }); + + it('should return an empty object if the components field has no defined operationTraits', function() { + const doc = {}; + const d = new Components(doc); + expect(typeof d.operationTraits()).to.be.equal('object'); + expect(d.operationTraits()).to.deep.equal({}); + }); + }); + + describe('#hasOperationTraits()', function() { + it('should return a boolean indicating if the components field has operationTraits', function() { + const doc = { operationTraits: { test1: { test: 'test1' }, test2: { test: 'test2' } } }; + const docNoSchemas = { messages: {} }; + const d = new Components(doc); + const d2 = new Components(docNoSchemas); + expect(d.hasOperationTraits()).to.equal(true); + expect(d2.hasOperationTraits()).to.equal(false); + }); }); describe('#operationTrait()', function() { @@ -213,6 +321,24 @@ describe('Components', function() { expect(d.messageTraits().test2.constructor.name).to.equal('MessageTrait'); expect(d.messageTraits().test2.json()).to.equal(doc.messageTraits.test2); }); + + it('should return an empty object if the components field has no defined messageTraits', function() { + const doc = {}; + const d = new Components(doc); + expect(typeof d.messageTraits()).to.be.equal('object'); + expect(d.messageTraits()).to.deep.equal({}); + }); + }); + + describe('#hasMessageTraits()', function() { + it('should return a boolean indicating if the components field has messageTraits', function() { + const doc = { messageTraits: { test1: { test: 'test1' }, test2: { test: 'test2' } } }; + const docNoSchemas = { messages: {} }; + const d = new Components(doc); + const d2 = new Components(docNoSchemas); + expect(d.hasMessageTraits()).to.equal(true); + expect(d2.hasMessageTraits()).to.equal(false); + }); }); describe('#messageTrait()', function() { diff --git a/test/models/schema_test.js b/test/models/schema_test.js index ba76516eb..e5978c468 100644 --- a/test/models/schema_test.js +++ b/test/models/schema_test.js @@ -260,6 +260,15 @@ describe('Schema', function() { }); }); + describe('#property()', function() { + it('should return a specific Schema object', function() { + const doc = { properties: { test: { type: 'string' } } }; + const d = new Schema(doc); + expect(d.property('test').constructor.name).to.be.equal('Schema'); + expect(d.property('test').json()).to.equal(doc.properties.test); + }); + }); + describe('#additionalProperties()', function() { it('should return a Schema object', function() { const doc = { additionalProperties: { type: 'string' } }; @@ -469,6 +478,14 @@ describe('Schema', function() { }); }); + describe('#default()', function() { + it('should return a value', function() { + const doc = { type: 'string', default: 'test' }; + const d = new Schema(doc); + expect(d.default()).to.be.equal('test'); + }); + }); + describe('#deprecated()', function() { it('should return a boolean', function() { const doc = { type: 'string', deprecated: true };