mirror of https://gitee.com/bigwinds/arangodb
Basic swagger tests
This commit is contained in:
parent
a71fc92c6f
commit
a31bf33892
|
@ -158,7 +158,7 @@ module.exports = exports = class SwaggerContext {
|
|||
}
|
||||
|
||||
this._bodyParam = {
|
||||
model: model || null,
|
||||
model: model,
|
||||
multiple: multiple,
|
||||
contentTypes: contentTypes,
|
||||
description: description
|
||||
|
@ -257,7 +257,7 @@ module.exports = exports = class SwaggerContext {
|
|||
}
|
||||
|
||||
this._responses.set(statusCode, {
|
||||
model: model || null,
|
||||
model: model,
|
||||
multiple: multiple,
|
||||
contentTypes: contentTypes,
|
||||
description: description
|
||||
|
|
|
@ -139,11 +139,6 @@ exports.routeApp = function (service, throwOnErrors) {
|
|||
let error = null;
|
||||
if (service.legacy) {
|
||||
error = routeLegacyService(service, throwOnErrors);
|
||||
} else {
|
||||
service.routes = {
|
||||
name: `foxx("${service.mount}")`,
|
||||
routes: []
|
||||
};
|
||||
}
|
||||
|
||||
if (service.manifest.files) {
|
||||
|
|
|
@ -348,7 +348,10 @@ module.exports = class FoxxService {
|
|||
this.main.context = new FoxxContext(this);
|
||||
this.router = new Router();
|
||||
this.types = new Map(defaultTypes);
|
||||
|
||||
this.routes = {
|
||||
name: `foxx("${this.mount}")`,
|
||||
routes: []
|
||||
};
|
||||
|
||||
if (this.legacy) {
|
||||
this.main.context.foxxFilename = this.main.context.fileName;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*global describe, it, beforeEach */
|
||||
'use strict';
|
||||
|
||||
const Router = require('@arangodb/foxx/router/router');
|
||||
const Tree = require('@arangodb/foxx/router/tree');
|
||||
const expect = require('chai').expect;
|
||||
|
@ -407,106 +406,3 @@ describe('Tree', function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tree#buildSwaggerPaths', function () {
|
||||
it('disambiguates duplicate path parameter names', function () {
|
||||
const child = new Router();
|
||||
child.get('/:x', function () {});
|
||||
const router = new Router();
|
||||
router.use('/:x', child);
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/:x/:x2')
|
||||
.with.a.property('get').that.is.an('object');
|
||||
});
|
||||
|
||||
it('sets the "consumes" info to the default body mime type', function () {
|
||||
const router = new Router();
|
||||
router.post('/data', function () {});
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/data')
|
||||
.with.a.deep.property('post.consumes')
|
||||
.that.is.eql(['application/json']);
|
||||
});
|
||||
|
||||
it('sets the "consumes" info to the body mime type', function () {
|
||||
const mimeType = 'banana';
|
||||
const router = new Router();
|
||||
const route = router.post('/data', function () {});
|
||||
route._bodyParam.contentTypes[0] = mimeType;
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/data')
|
||||
.with.a.deep.property('post.consumes')
|
||||
.that.is.eql([mimeType]);
|
||||
});
|
||||
|
||||
it('does not set the "consumes" info for body-free methods', function () {
|
||||
const router = new Router();
|
||||
router.get('/no-data', function () {});
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/no-data')
|
||||
.with.not.a.deep.property('get.consumes'); // this may not work?
|
||||
});
|
||||
|
||||
it('sets the "consumes" info to empty if explicitly forbidden', function () {
|
||||
const router = new Router();
|
||||
router.post('/no-data', function () {})
|
||||
.body(null);
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/no-data')
|
||||
.with.a.deep.property('post.consumes')
|
||||
.that.is.eql([]);
|
||||
});
|
||||
|
||||
it('sets the "produces" info to the default response mime type', function () {
|
||||
const router = new Router();
|
||||
router.get('/body', function () {});
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/body')
|
||||
.with.a.deep.property('get.produces')
|
||||
.that.is.eql(['application/json']);
|
||||
});
|
||||
|
||||
it('sets the "produces" info to all response mime types', function () {
|
||||
const mimeType = 'banana';
|
||||
const router = new Router();
|
||||
const route = router.get('/body', function () {});
|
||||
route._responses.set(200, {contentTypes: [mimeType]});
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/body')
|
||||
.with.a.deep.property('get.produces')
|
||||
.that.is.eql([mimeType, 'application/json']);
|
||||
});
|
||||
|
||||
it('only sets the "produces" info once per response mime type', function () {
|
||||
const mimeType = 'banana';
|
||||
const router = new Router();
|
||||
const route = router.get('/body', function () {});
|
||||
route._responses.set(200, {contentTypes: [mimeType]});
|
||||
route._responses.set(400, {contentTypes: [mimeType]});
|
||||
const tree = new Tree({}, router);
|
||||
const docs = tree.buildSwaggerPaths();
|
||||
expect(docs).to.have.a.property('/body')
|
||||
.with.a.deep.property('get.produces')
|
||||
.that.is.eql([mimeType, 'application/json']);
|
||||
});
|
||||
|
||||
it.skip('sets the path parameters');
|
||||
it.skip('sets the query parameters');
|
||||
it.skip('sets the header parameters');
|
||||
it.skip('sets the body parameter');
|
||||
it.skip('uses the default body parameter if body is implied');
|
||||
it.skip('omits the body parameter if no body is set');
|
||||
it.skip('omits the body parameter if body is explicitly disabled');
|
||||
it.skip('sets the default response');
|
||||
it.skip('sets the response bodies');
|
||||
it.skip('omits the response body if body is explicitly disabled');
|
||||
it.skip('sets the form parameters if route consumes form type but not json');
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
/*global describe, it, beforeEach */
|
||||
'use strict';
|
||||
require('chai').config.truncateThreshold = 0;
|
||||
const expect = require('chai').expect;
|
||||
const Service = require('@arangodb/foxx/service');
|
||||
const createRouter = require('@arangodb/foxx/router');
|
||||
|
||||
describe('Foxx Swagger', function () {
|
||||
let service;
|
||||
beforeEach(function () {
|
||||
service = createService();
|
||||
});
|
||||
|
||||
it('adds all the basic metadata', function () {
|
||||
service.buildRoutes();
|
||||
expect(service.docs).to.eql({
|
||||
swagger: '2.0',
|
||||
basePath: `/_db/_system${service.mount}`,
|
||||
paths: {},
|
||||
info: {
|
||||
title: service.manifest.name,
|
||||
description: service.manifest.description,
|
||||
version: service.manifest.version,
|
||||
license: {
|
||||
name: service.manifest.license
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Route Info', function () {
|
||||
it('formats path param names', function () {
|
||||
service.router.get('/:x', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/{x}')
|
||||
.with.a.property('get');
|
||||
});
|
||||
|
||||
it('disambiguates duplicate path param names', function () {
|
||||
const child = createRouter();
|
||||
child.get('/:x', noop());
|
||||
service.router.use('/:x', child);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/{x}/{x2}')
|
||||
.with.a.property('get');
|
||||
});
|
||||
|
||||
it('supports multiple methods on the same path', function () {
|
||||
service.router.get('/a', noop()).description('x');
|
||||
service.router.post('/a', noop()).description('y');
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/a')
|
||||
.with.a.deep.property('get.description', 'x');
|
||||
expect(service.docs.paths).to.have.a.property('/a')
|
||||
.with.a.deep.property('post.description', 'y');
|
||||
});
|
||||
|
||||
describe('"deprecated"', function () {
|
||||
it('is omitted by default', function () {
|
||||
service.router.get('/hello', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.not.a.deep.property('get.deprecated');
|
||||
});
|
||||
|
||||
it('is set to true if the route is marked deprecated', function () {
|
||||
service.router.get('/hello', noop()).deprecated();
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('get.deprecated')
|
||||
.that.is.equal(true);
|
||||
});
|
||||
|
||||
it('is set to true if a parent is marked deprecated', function () {
|
||||
const child = createRouter();
|
||||
child.get('/hello', noop()).deprecated(false);
|
||||
service.router.use(child).deprecated();
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('get.deprecated')
|
||||
.that.is.equal(true);
|
||||
});
|
||||
|
||||
it('is omitted if the route is marked un-deprecated', function () {
|
||||
service.router.get('/hello', noop()).deprecated(false);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.not.a.deep.property('get.deprecated');
|
||||
});
|
||||
});
|
||||
|
||||
['description', 'summary'].forEach(function (field) {
|
||||
describe(`"${field}"`, function () {
|
||||
it('is omitted by default', function () {
|
||||
service.router.get('/hello', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.not.a.deep.property(`get.${field}`);
|
||||
});
|
||||
|
||||
it(`is set to the ${field} if provided`, function () {
|
||||
const str = 'Hello World!';
|
||||
service.router.get('/hello', noop())[field](str);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property(`get.${field}`)
|
||||
.that.is.equal(str);
|
||||
});
|
||||
|
||||
it(`is omitted if the ${field} is empty`, function () {
|
||||
service.router.get('/hello', noop())[field]('');
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.not.a.deep.property(`get.${field}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('"consumes"', function () {
|
||||
['patch', 'post', 'put'].forEach(function (method) {
|
||||
it(`defaults to JSON for ${method.toUpperCase()}`, function () {
|
||||
service.router[method]('/hello', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property(`${method}.consumes`)
|
||||
.that.is.eql(['application/json']);
|
||||
});
|
||||
});
|
||||
|
||||
['get', 'head', 'delete'].forEach(function (method) {
|
||||
it(`is omitted for ${method.toUpperCase()}`, function () {
|
||||
service.router[method]('/hello', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.not.a.deep.property(`${method}.consumes`);
|
||||
});
|
||||
});
|
||||
|
||||
it('is set to the body mime type', function () {
|
||||
service.router.post('/hello', noop()).body(['text/plain']);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('post.consumes')
|
||||
.that.is.eql(['text/plain']);
|
||||
});
|
||||
|
||||
['get', 'head', 'delete'].forEach(function (method) {
|
||||
it(`is set for ${method.toUpperCase()} if explicitly defined`, function () {
|
||||
service.router[method]('/hello', noop()).body(['text/plain']);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property(`${method}.consumes`)
|
||||
.that.is.eql(['text/plain']);
|
||||
});
|
||||
});
|
||||
|
||||
['patch', 'post', 'put'].forEach(function (method) {
|
||||
it(`is empty for ${method.toUpperCase()} if explicitly set to null`, function () {
|
||||
service.router[method]('/hello', noop()).body(null);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property(`${method}.consumes`)
|
||||
.that.is.eql([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('"produces"', function () {
|
||||
it('defaults to JSON', function () {
|
||||
service.router.get('/hello', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('get.produces')
|
||||
.that.is.eql(['application/json']);
|
||||
});
|
||||
|
||||
it('includes explicit response types', function () {
|
||||
service.router.get('/hello', noop()).response(['text/plain']);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('get.produces')
|
||||
.that.is.eql(['text/plain', 'application/json']);
|
||||
});
|
||||
|
||||
it('includes non-200 response types', function () {
|
||||
service.router.get('/hello', noop())
|
||||
.response(['text/plain'])
|
||||
.response(499, ['text/html']);
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('get.produces')
|
||||
.that.is.eql(['text/plain', 'text/html', 'application/json']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"responses"', function () {
|
||||
it('provides a default response', function () {
|
||||
service.router.get('/hello', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('get.responses.default')
|
||||
.that.has.a.property('description', 'Unexpected error');
|
||||
});
|
||||
|
||||
it('provides a default 200 response', function () {
|
||||
service.router.get('/hello', noop());
|
||||
service.buildRoutes();
|
||||
expect(service.docs.paths).to.have.a.property('/hello')
|
||||
.with.a.deep.property('get.responses.200')
|
||||
.that.has.a.property('description', 'Undocumented response body');
|
||||
});
|
||||
|
||||
it('TODO');
|
||||
});
|
||||
|
||||
describe('"parameters"', function () {
|
||||
describe('in:body', function () {
|
||||
it('TODO');
|
||||
});
|
||||
|
||||
describe('in:path', function () {
|
||||
it('TODO');
|
||||
});
|
||||
|
||||
describe('in:query', function () {
|
||||
it('TODO');
|
||||
});
|
||||
|
||||
describe('in:header', function () {
|
||||
it('TODO');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function createService() {
|
||||
return new Service({
|
||||
path: '/tmp/$dummy$',
|
||||
mount: '/__dummy__',
|
||||
manifest: {
|
||||
name: 'DUMMY APP',
|
||||
version: '1.0.0',
|
||||
license: 'The Unlicense',
|
||||
description: 'Dummy app for Foxx.',
|
||||
main: '$dummy$',
|
||||
engines: {
|
||||
arangodb: '^3.0.0'
|
||||
}
|
||||
},
|
||||
options: {}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function noop() {
|
||||
return noop;
|
||||
}
|
Loading…
Reference in New Issue