295 lines
9.3 KiB
JavaScript
295 lines
9.3 KiB
JavaScript
'use strict';
|
|
|
|
var modelHelper = require('../lib/model-helper');
|
|
var _defaults = require('lodash').defaults;
|
|
var loopback = require('loopback');
|
|
var expect = require('chai').expect;
|
|
|
|
describe('model-helper', function() {
|
|
describe('properly converts LDL definitions to swagger types', function() {
|
|
it('converts constructor types', function() {
|
|
var def = buildSwaggerModels({
|
|
str: String, // 'string'
|
|
num: Number, // {type: 'number', format: 'double'}
|
|
date: Date, // {type: 'string', format: 'date'}
|
|
bool: Boolean, // 'boolean'
|
|
buf: Buffer // {type: 'string', format: 'byte'}
|
|
});
|
|
var props = def.properties;
|
|
expect(props.str).to.eql({ type: 'string' });
|
|
expect(props.num).to.eql({ type: 'number', format: 'double' });
|
|
expect(props.date).eql({ type: 'string', format: 'date' });
|
|
expect(props.bool).to.eql({ type: 'boolean' });
|
|
expect(props.buf).to.eql({ type: 'string', format: 'byte' });
|
|
});
|
|
it('converts string types', function() {
|
|
var def = buildSwaggerModels({
|
|
str: 'string', // 'string'
|
|
num: 'number', // {type: 'number', format: 'double'}
|
|
date: 'date', // {type: 'string', format: 'date'}
|
|
bool: 'boolean', // 'boolean'
|
|
buf: 'buffer' // {type: 'string', format: 'byte'}
|
|
});
|
|
var props = def.properties;
|
|
expect(props.str).to.eql({ type: 'string' });
|
|
expect(props.num).to.eql({ type: 'number', format: 'double' });
|
|
expect(props.date).eql({ type: 'string', format: 'date' });
|
|
expect(props.bool).to.eql({ type: 'boolean' });
|
|
expect(props.buf).to.eql({ type: 'string', format: 'byte' });
|
|
});
|
|
describe('array definitions', function() {
|
|
// There are three types we want to checK:
|
|
// [String]
|
|
// ["string"],
|
|
// [{type: String, ...}]
|
|
it('converts [Constructor] type', function() {
|
|
var def = buildSwaggerModels({
|
|
array: [String]
|
|
});
|
|
var props = def.properties;
|
|
expect(props.array).to.eql({ type: 'array', items: {
|
|
type: 'string'
|
|
}});
|
|
});
|
|
|
|
it('converts ["string"] type', function() {
|
|
var def = buildSwaggerModels({
|
|
array: ['string']
|
|
});
|
|
var props = def.properties;
|
|
expect(props.array).to.eql({ type: 'array', items: {
|
|
type: 'string'
|
|
}});
|
|
});
|
|
|
|
it('converts [{type: "string", length: 64}] type', function() {
|
|
var def = buildSwaggerModels({
|
|
array: [{type: 'string', length: 64}]
|
|
});
|
|
var props = def.properties;
|
|
expect(props.array).to.eql({ type: 'array', items: {
|
|
type: 'string',
|
|
length: 64
|
|
}});
|
|
});
|
|
|
|
it('converts [{type: "date"}] type (with `format`)', function() {
|
|
var def = buildSwaggerModels({
|
|
array: [{type: 'date'}]
|
|
});
|
|
var props = def.properties;
|
|
expect(props.array).to.eql({ type: 'array', items: {
|
|
type: 'string', format: 'date'
|
|
}});
|
|
});
|
|
|
|
it('converts [] type', function() {
|
|
var def = buildSwaggerModels({
|
|
array: []
|
|
});
|
|
var prop = def.properties.array;
|
|
expect(prop).to.eql({
|
|
type: 'array',
|
|
items: { type: 'any' }
|
|
});
|
|
});
|
|
|
|
it('converts [undefined] type', function() {
|
|
var def = buildSwaggerModels({
|
|
// This value is somehow provided by loopback-boot called from
|
|
// loopback-workspace.
|
|
array: [undefined]
|
|
});
|
|
var prop = def.properties.array;
|
|
expect(prop).to.eql({ type: 'array', items: { type: 'any' } });
|
|
});
|
|
|
|
it('converts "array" type', function() {
|
|
var def = buildSwaggerModels({
|
|
array: 'array'
|
|
});
|
|
var prop = def.properties.array;
|
|
expect(prop).to.eql({ type: 'array', items: { type: 'any' } });
|
|
});
|
|
|
|
it('converts Model type', function() {
|
|
var Address = loopback.createModel('Address', {street: String});
|
|
var def = buildSwaggerModels({
|
|
str: String,
|
|
address: Address
|
|
});
|
|
var prop = def.properties.address;
|
|
expect(prop).to.eql({ type: 'Address' });
|
|
});
|
|
|
|
});
|
|
|
|
it('converts model property field `doc`', function() {
|
|
var def = buildSwaggerModels({
|
|
name: { type: String, doc: 'a-description' }
|
|
});
|
|
var nameProp = def.properties.name;
|
|
expect(nameProp).to.have.property('description', 'a-description');
|
|
});
|
|
|
|
it('converts model property field `description`', function() {
|
|
var def = buildSwaggerModels({
|
|
name: { type: String, description: 'a-description' }
|
|
});
|
|
var nameProp = def.properties.name;
|
|
expect(nameProp).to.have.property('description', 'a-description');
|
|
});
|
|
|
|
it('converts model field `description`', function() {
|
|
var def = buildSwaggerModels({}, { description: 'a-description' });
|
|
expect(def).to.have.property('description', 'a-description');
|
|
});
|
|
});
|
|
|
|
describe('related models', function() {
|
|
it('should include related models', function () {
|
|
var defs = buildSwaggerModelsWithRelations({
|
|
str: String // 'string'
|
|
});
|
|
expect(defs).has.property('testModel');
|
|
expect(defs).has.property('relatedModel');
|
|
});
|
|
|
|
it('should include nesting models', function() {
|
|
var Model2 = loopback.createModel('Model2', {street: String});
|
|
var Model1 = loopback.createModel('Model1', {
|
|
str: String, // 'string'
|
|
address: Model2
|
|
});
|
|
var defs = modelHelper.generateModelDefinition(Model1, {});
|
|
expect(defs).has.property('Model1');
|
|
expect(defs).has.property('Model2');
|
|
});
|
|
|
|
it('should include used models', function() {
|
|
var Model4 = loopback.createModel('Model4', {street: String});
|
|
var Model3 = loopback.createModel('Model3', {
|
|
str: String, // 'string'
|
|
}, {models: {model4: 'Model4'}});
|
|
var defs = modelHelper.generateModelDefinition(Model3, {});
|
|
expect(defs).has.property('Model3');
|
|
expect(defs).has.property('Model4');
|
|
});
|
|
|
|
it('should include nesting models in array', function() {
|
|
var Model6 = loopback.createModel('Model6', {street: String});
|
|
var Model5 = loopback.createModel('Model5', {
|
|
str: String, // 'string'
|
|
addresses: [Model6]
|
|
});
|
|
var defs = modelHelper.generateModelDefinition(Model5, {});
|
|
expect(defs).has.property('Model5');
|
|
expect(defs).has.property('Model6');
|
|
});
|
|
|
|
// https://github.com/strongloop/loopback-explorer/issues/49
|
|
it('should work if Array class is extended and no related models are found',
|
|
function() {
|
|
var Model7 = loopback.createModel('Model7', {street: String});
|
|
Array.prototype.customFunc = function() {
|
|
};
|
|
var defs = modelHelper.generateModelDefinition(Model7, {});
|
|
expect(defs).has.property('Model7');
|
|
expect(Object.keys(defs)).has.property('length', 1);
|
|
});
|
|
|
|
// https://github.com/strongloop/loopback-explorer/issues/71
|
|
it('should skip unknown types', function() {
|
|
var Model8 = loopback.createModel('Model8', {
|
|
patient: {
|
|
model: 'physician',
|
|
type: 'hasMany',
|
|
through: 'appointment'
|
|
}
|
|
});
|
|
var defs = modelHelper.generateModelDefinition(Model8, {});
|
|
expect(Object.keys(defs)).to.not.contain('hasMany');
|
|
});
|
|
});
|
|
|
|
describe('hidden properties', function() {
|
|
it('should hide properties marked as "hidden"', function() {
|
|
var aClass = createModelCtor({
|
|
visibleProperty: 'string',
|
|
hiddenProperty: 'string'
|
|
});
|
|
aClass.ctor.definition.settings = {
|
|
hidden: ['hiddenProperty']
|
|
};
|
|
var def = modelHelper.generateModelDefinition(aClass.ctor, {}).testModel;
|
|
expect(def.properties).to.not.have.property('hiddenProperty');
|
|
expect(def.properties).to.have.property('visibleProperty');
|
|
});
|
|
});
|
|
|
|
describe('getPropType', function() {
|
|
it('converts anonymous object types', function() {
|
|
var type = modelHelper.getPropType({ name: 'string', value: 'string' });
|
|
expect(type).to.eql('object');
|
|
});
|
|
});
|
|
});
|
|
|
|
// Simulates the format of a remoting class.
|
|
function buildSwaggerModels(modelProperties, modelOptions) {
|
|
var aClass = createModelCtor(modelProperties, modelOptions);
|
|
return modelHelper.generateModelDefinition(aClass.ctor, {}).testModel;
|
|
}
|
|
|
|
function createModelCtor(properties, modelOptions) {
|
|
Object.keys(properties).forEach(function(name) {
|
|
var type = properties[name];
|
|
if (typeof type !== 'object' || Array.isArray(type))
|
|
properties[name] = { type: type };
|
|
});
|
|
|
|
var definition = {
|
|
name: 'testModel',
|
|
properties: properties
|
|
};
|
|
_defaults(definition, modelOptions);
|
|
|
|
var aClass = {
|
|
ctor: {
|
|
definition: definition
|
|
}
|
|
};
|
|
return aClass;
|
|
}
|
|
|
|
function buildSwaggerModelsWithRelations(model) {
|
|
Object.keys(model).forEach(function(name) {
|
|
model[name] = {type: model[name]};
|
|
});
|
|
// Mock up the related model
|
|
var relatedModel = {
|
|
definition: {
|
|
name: 'relatedModel',
|
|
properties: {
|
|
fk: String
|
|
}
|
|
}
|
|
};
|
|
var aClass = {
|
|
ctor: {
|
|
definition: {
|
|
name: 'testModel',
|
|
properties: model
|
|
},
|
|
// Mock up relations
|
|
relations: {
|
|
other: {
|
|
modelTo: relatedModel
|
|
}
|
|
}
|
|
}
|
|
};
|
|
return modelHelper.generateModelDefinition(aClass.ctor, {});
|
|
}
|
|
|