Add integration tests for included models
Add tests verifying that Swagger docs include model description for recursively nested references to Models and Arrays of Models in properties, modelTo and modelThrough relations, accepts, returns and errors. Fix bugs discovered along the way.
This commit is contained in:
parent
d05dcb71df
commit
6fb81c279b
|
@ -91,7 +91,11 @@ function Swagger(loopbackApplication, swaggerApp, opts) {
|
||||||
classDoc.apis.forEach(function(api) {
|
classDoc.apis.forEach(function(api) {
|
||||||
api.operations.forEach(function(routeDoc) {
|
api.operations.forEach(function(routeDoc) {
|
||||||
routeDoc.parameters.forEach(function(param) {
|
routeDoc.parameters.forEach(function(param) {
|
||||||
addTypeToModels(param.type);
|
var type = param.type;
|
||||||
|
if (type === 'array' && param.items)
|
||||||
|
type = param.items.type;
|
||||||
|
|
||||||
|
addTypeToModels(type);
|
||||||
});
|
});
|
||||||
|
|
||||||
addTypeToModels(routeDoc.type);
|
addTypeToModels(routeDoc.type);
|
||||||
|
|
|
@ -196,12 +196,108 @@ describe('swagger definition', function() {
|
||||||
responseModel: 'ValidationError'
|
responseModel: 'ValidationError'
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
mountExplorer(app);
|
|
||||||
|
|
||||||
getAPIDeclaration(app, 'products').end(function(err, res) {
|
expectProductDocIncludesModels(app, 'ValidationError', done);
|
||||||
expect(Object.keys(res.body.models)).to.include('ValidationError');
|
});
|
||||||
done();
|
|
||||||
|
it('includes nested model references in properties', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
app.models.Product.defineProperty('location', { type: 'Warehouse' });
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested array model references in properties', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
app.models.Product.defineProperty('location', { type: ['Warehouse'] });
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested model references in modelTo relation', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
app.models.Product.belongsTo(app.models.Warehouse);
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested model references in modelTo relation', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
givenPrivateAppModel(app, 'ProductLocations');
|
||||||
|
|
||||||
|
app.models.Product.hasMany(app.models.Warehouse,
|
||||||
|
{ through: app.models.ProductLocations });
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(
|
||||||
|
app,
|
||||||
|
['Address', 'Warehouse', 'ProductLocations'],
|
||||||
|
done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested model references in accept args', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
givenSharedMethod(app.models.Product, 'aMethod', {
|
||||||
|
accepts: { arg: 'w', type: 'Warehouse' }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested array model references in accept args', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
givenSharedMethod(app.models.Product, 'aMethod', {
|
||||||
|
accepts: { arg: 'w', type: [ 'Warehouse' ] }
|
||||||
|
});
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested model references in return args', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
givenSharedMethod(app.models.Product, 'aMethod', {
|
||||||
|
returns: { arg: 'w', type: 'Warehouse', root: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested array model references in return args', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
givenSharedMethod(app.models.Product, 'aMethod', {
|
||||||
|
returns: { arg: 'w', type: ['Warehouse'], root: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes nested model references in error responses', function(done) {
|
||||||
|
var app = createLoopbackAppWithModel();
|
||||||
|
givenWarehouseWithAddressModels(app);
|
||||||
|
|
||||||
|
givenSharedMethod(app.models.Product, 'aMethod', {
|
||||||
|
errors: {
|
||||||
|
code: '222',
|
||||||
|
message: 'Warehouse',
|
||||||
|
responseModel: 'Warehouse'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expectProductDocIncludesModels(app, ['Address', 'Warehouse'], done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -234,8 +330,8 @@ describe('swagger definition', function() {
|
||||||
return request(app)
|
return request(app)
|
||||||
.get(urlJoin(restPath || '/explorer', '/resources', classPath || ''))
|
.get(urlJoin(restPath || '/explorer', '/resources', classPath || ''))
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.expect('Content-Type', /json/)
|
.expect(200)
|
||||||
.expect(200);
|
.expect('Content-Type', /json/);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAPIDeclaration(app, className) {
|
function getAPIDeclaration(app, className) {
|
||||||
|
@ -284,8 +380,27 @@ describe('swagger definition', function() {
|
||||||
loopback.remoteMethod(model[name], metadata);
|
loopback.remoteMethod(model[name], metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
function givenPrivateAppModel(app, name) {
|
function givenPrivateAppModel(app, name, properties) {
|
||||||
var model = loopback.createModel(name);
|
var model = loopback.createModel(name, properties);
|
||||||
app.model(model, { dataSource: 'db', public: false} );
|
app.model(model, { dataSource: 'db', public: false} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function givenWarehouseWithAddressModels(app) {
|
||||||
|
givenPrivateAppModel(app, 'Address');
|
||||||
|
givenPrivateAppModel(app, 'Warehouse', {
|
||||||
|
shippingAddress: { type: 'Address' }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectProductDocIncludesModels(app, modelNames, done) {
|
||||||
|
if (!Array.isArray(modelNames)) modelNames = [modelNames];
|
||||||
|
|
||||||
|
mountExplorer(app);
|
||||||
|
|
||||||
|
getAPIDeclaration(app, 'products').end(function(err, res) {
|
||||||
|
if (err) return done(err);
|
||||||
|
expect(Object.keys(res.body.models)).to.include.members(modelNames);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue