Merge pull request #1441 from strongloop/memory/throw-on-malformed-types
castPropertyValue: throw on malformed types
This commit is contained in:
commit
29676f6510
|
@ -350,9 +350,17 @@ Memory.prototype.fromDb = function(model, data) {
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
data = deserialize(data);
|
data = deserialize(data);
|
||||||
var props = this._models[model].properties;
|
var props = this._models[model].properties;
|
||||||
|
try {
|
||||||
for (var key in data) {
|
for (var key in data) {
|
||||||
data[key] = this._castPropertyValue(key, data[key], props);
|
data[key] = this._castPropertyValue(key, data[key], props);
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Modify error message and re-throw
|
||||||
|
err.message = g.f('Unable to convert to instance of "%s": %s', model,
|
||||||
|
err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -370,7 +378,15 @@ Memory.prototype._castPropertyValue = function(prop, val, props) {
|
||||||
|
|
||||||
var isArray = Array.isArray(props[prop].type);
|
var isArray = Array.isArray(props[prop].type);
|
||||||
var propType = isArray ? props[prop].type[0] : props[prop].type;
|
var propType = isArray ? props[prop].type[0] : props[prop].type;
|
||||||
|
if (!propType || !propType.name) {
|
||||||
|
if (isArray)
|
||||||
|
throw new Error(g.f(
|
||||||
|
'Property definition "%s" did not specify any sub-types!', prop));
|
||||||
|
else
|
||||||
|
throw new Error(g.f(
|
||||||
|
'Property definition "%s" was null or undefined!', prop
|
||||||
|
));
|
||||||
|
}
|
||||||
switch (propType.name) {
|
switch (propType.name) {
|
||||||
case 'Date':
|
case 'Date':
|
||||||
val = new Date(val.toString().replace(/GMT.*$/, 'GMT'));
|
val = new Date(val.toString().replace(/GMT.*$/, 'GMT'));
|
||||||
|
@ -383,7 +399,9 @@ Memory.prototype._castPropertyValue = function(prop, val, props) {
|
||||||
break;
|
break;
|
||||||
case 'ModelConstructor':
|
case 'ModelConstructor':
|
||||||
for (var subProp in val) {
|
for (var subProp in val) {
|
||||||
val[subProp] = this._castPropertyValue(subProp, val[subProp], propType.definition.properties);
|
if (propType.definition && propType.definition.properties)
|
||||||
|
val[subProp] = this._castPropertyValue(subProp, val[subProp],
|
||||||
|
propType.definition.properties);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
// License text available at https://opensource.org/licenses/MIT
|
// License text available at https://opensource.org/licenses/MIT
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var g = require('strong-globalize')();
|
||||||
var jdb = require('../');
|
var jdb = require('../');
|
||||||
var DataSource = jdb.DataSource;
|
var DataSource = jdb.DataSource;
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
@ -889,6 +890,106 @@ describe('Memory connector', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('_castPropertyValue', function() {
|
||||||
|
var mem = new Memory();
|
||||||
|
var ds = new DataSource({
|
||||||
|
connector: mem,
|
||||||
|
});
|
||||||
|
|
||||||
|
var Kwyjibo = ds.createModel('Kwyjibo', {
|
||||||
|
modelNumber: Number,
|
||||||
|
purpose: String,
|
||||||
|
});
|
||||||
|
|
||||||
|
testHappyPath('handles strings', 'name', 'foo', 'foo');
|
||||||
|
testHappyPath('handles numbers', 'age', '20', 20);
|
||||||
|
var hobbies = [
|
||||||
|
'swimming', 'biking', 'extreme bear fighting',
|
||||||
|
];
|
||||||
|
testHappyPath('handles boolean values', 'isAwesome', 'true', true);
|
||||||
|
var now = new Date();
|
||||||
|
testHappyPath('handles Dates', 'createdAt', now.toISOString(),
|
||||||
|
new Date(now));
|
||||||
|
testHappyPath('handles arrays', 'hobbies', hobbies, hobbies);
|
||||||
|
|
||||||
|
it('handles ModelConstructors', function() {
|
||||||
|
var samoflange = {
|
||||||
|
modelNumber: 12345,
|
||||||
|
purpose: 'To annoy others',
|
||||||
|
};
|
||||||
|
var kwyjibo = new Kwyjibo();
|
||||||
|
for (var item in samoflange) {
|
||||||
|
kwyjibo[item] = samoflange[item];
|
||||||
|
}
|
||||||
|
var result = mem._castPropertyValue('samoflange', samoflange, kwyjibo);
|
||||||
|
should.exist(result);
|
||||||
|
should.deepEqual(result, kwyjibo.__data);
|
||||||
|
});
|
||||||
|
|
||||||
|
var nullUndef = 'Property definition "%s" was null or undefined!';
|
||||||
|
var noSubTypes = 'Property definition "%s" did not specify any sub-types!';
|
||||||
|
testUnhappyPath('throws on empty array property def', 'hobbies', hobbies,
|
||||||
|
g.f(noSubTypes, 'hobbies'));
|
||||||
|
testUnhappyPath('throws on empty object property def', 'age', 20,
|
||||||
|
g.f(nullUndef, 'age'));
|
||||||
|
testUnhappyPath('throws on null property def', 'name', 'foo',
|
||||||
|
g.f(nullUndef, 'name'));
|
||||||
|
testUnhappyPath('throws on undefined property def', 'title', 'peon',
|
||||||
|
g.f(nullUndef, 'title'));
|
||||||
|
|
||||||
|
function testHappyPath(testName, prop, val, expected) {
|
||||||
|
var props = {
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
age: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
hobbies: {
|
||||||
|
type: [
|
||||||
|
String,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
isAwesome: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: Date,
|
||||||
|
},
|
||||||
|
samoflange: {
|
||||||
|
type: Kwyjibo,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
it(testName, function() {
|
||||||
|
var result = mem._castPropertyValue(prop, val, props);
|
||||||
|
result.should.deepEqual(expected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testUnhappyPath(testName, prop, val, expected) {
|
||||||
|
var props = {
|
||||||
|
name: {
|
||||||
|
type: null,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
age: {
|
||||||
|
type: {},
|
||||||
|
},
|
||||||
|
hobbies: {
|
||||||
|
type: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
it(testName, function() {
|
||||||
|
(function() {
|
||||||
|
mem._castPropertyValue(prop, val, props);
|
||||||
|
}).should.throw(expected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Optimized connector', function() {
|
describe('Optimized connector', function() {
|
||||||
|
|
Loading…
Reference in New Issue