Merge pull request #1594 from strongloop/upgrade-deps

Drop support for Node.js 4.x + update dependencies
This commit is contained in:
Miroslav Bajtoš 2018-06-12 16:26:07 +02:00 committed by GitHub
commit 751fd7b245
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 2593 additions and 2570 deletions

1
.npmrc Normal file
View File

@ -0,0 +1 @@
package-lock=false

View File

@ -1,8 +1,8 @@
sudo: false sudo: false
language: node_js language: node_js
node_js: node_js:
- "4"
- "6" - "6"
- "8" - "8"
- "10"
after_success: npm run coverage after_success: npm run coverage

View File

@ -67,8 +67,8 @@ Transient.prototype.generateId = function(model, data, idName) {
return Math.floor(Math.random() * 10000); // max. 4 digits return Math.floor(Math.random() * 10000); // max. 4 digits
} else { } else {
return crypto.randomBytes(Math.ceil(24 / 2)) return crypto.randomBytes(Math.ceil(24 / 2))
.toString('hex') // convert to hexadecimal format .toString('hex') // convert to hexadecimal format
.slice(0, 24); // return required number of characters .slice(0, 24); // return required number of characters
} }
}; };

View File

@ -487,7 +487,7 @@ function stillConnecting(dataSource, obj, args) {
// promise variant // promise variant
var promiseArgs = Array.prototype.slice.call(args); var promiseArgs = Array.prototype.slice.call(args);
promiseArgs.callee = args.callee; promiseArgs.callee = args.callee;
var cb = utils.createPromiseCallback(); var cb = utils.createPromiseCallback();
promiseArgs.push(cb); promiseArgs.push(cb);
if (dataSource.ready(obj, promiseArgs)) { if (dataSource.ready(obj, promiseArgs)) {
return cb.promise; return cb.promise;
@ -801,7 +801,7 @@ DataAccessObject.upsertWithWhere = function(where, data, options, cb) {
function callConnector() { function callConnector() {
try { try {
// Support an optional where object // Support an optional where object
var handleUndefined = Model._getSetting('normalizeUndefinedInQuery'); var handleUndefined = Model._getSetting('normalizeUndefinedInQuery');
// alter configuration of how removeUndefined handles undefined values // alter configuration of how removeUndefined handles undefined values
ctx.where = removeUndefined(ctx.where, handleUndefined); ctx.where = removeUndefined(ctx.where, handleUndefined);
ctx.where = Model._coerce(ctx.where, options); ctx.where = Model._coerce(ctx.where, options);
@ -864,7 +864,7 @@ DataAccessObject.upsertWithWhere = function(where, data, options, cb) {
self.find({where: ctx.query.where}, opts, function(err, instances) { self.find({where: ctx.query.where}, opts, function(err, instances) {
if (err) return cb(err); if (err) return cb(err);
var modelsLength = instances.length; var modelsLength = instances.length;
if (modelsLength === 0) { if (modelsLength === 0) {
self.create(data, options, cb); self.create(data, options, cb);
} else if (modelsLength === 1) { } else if (modelsLength === 1) {
var modelInst = instances[0]; var modelInst = instances[0];
@ -1089,7 +1089,7 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
// query will be built from data, and method will return Promise // query will be built from data, and method will return Promise
data = query; data = query;
query = {where: data}; query = {where: data};
} else if (options === undefined && cb === undefined) { } else if (options === undefined && cb === undefined) {
if (typeof data === 'function') { if (typeof data === 'function') {
// findOrCreate(data, cb); // findOrCreate(data, cb);
// query will be built from data // query will be built from data
@ -1517,7 +1517,7 @@ DataAccessObject._normalize = function(filter, options) {
} }
if (isNaN(offset) || offset < 0 || Math.ceil(offset) !== offset) { if (isNaN(offset) || offset < 0 || Math.ceil(offset) !== offset) {
err = new Error(g.f('The {{offset/skip}} parameter %j is not valid', err = new Error(g.f('The {{offset/skip}} parameter %j is not valid',
filter.skip || filter.offset)); filter.skip || filter.offset));
err.statusCode = 400; err.statusCode = 400;
throw err; throw err;
} }
@ -1574,7 +1574,7 @@ DataAccessObject._normalize = function(filter, options) {
Object.keys(this.definition.properties), this.settings.strict); Object.keys(this.definition.properties), this.settings.strict);
} }
var handleUndefined = this._getSetting('normalizeUndefinedInQuery'); var handleUndefined = this._getSetting('normalizeUndefinedInQuery');
// alter configuration of how removeUndefined handles undefined values // alter configuration of how removeUndefined handles undefined values
filter = removeUndefined(filter, handleUndefined); filter = removeUndefined(filter, handleUndefined);
this._coerce(filter.where, options); this._coerce(filter.where, options);
@ -2118,7 +2118,7 @@ DataAccessObject.find = function find(query, options, cb) {
if (options.notify === false) { if (options.notify === false) {
invokeConnectorMethod(connector, 'all', self, [query], options, allCb); invokeConnectorMethod(connector, 'all', self, [query], options, allCb);
} else { } else {
var context = { var context = {
Model: this, Model: this,
query: query, query: query,
hookState: hookState, hookState: hookState,
@ -2271,7 +2271,7 @@ DataAccessObject.destroyAll = function destroyAll(where, options, cb) {
} else { } else {
try { try {
// Support an optional where object // Support an optional where object
var handleUndefined = Model._getSetting('normalizeUndefinedInQuery'); var handleUndefined = Model._getSetting('normalizeUndefinedInQuery');
// alter configuration of how removeUndefined handles undefined values // alter configuration of how removeUndefined handles undefined values
where = removeUndefined(where, handleUndefined); where = removeUndefined(where, handleUndefined);
where = Model._coerce(where, options); where = Model._coerce(where, options);
@ -2426,7 +2426,7 @@ DataAccessObject.count = function(where, options, cb) {
where = query.where; where = query.where;
try { try {
var handleUndefined = Model._getSetting('normalizeUndefinedInQuery'); var handleUndefined = Model._getSetting('normalizeUndefinedInQuery');
// alter configuration of how removeUndefined handles undefined values // alter configuration of how removeUndefined handles undefined values
where = removeUndefined(where, handleUndefined); where = removeUndefined(where, handleUndefined);
where = this._coerce(where, options); where = this._coerce(where, options);
@ -2478,7 +2478,7 @@ DataAccessObject.prototype.save = function(options, cb) {
if (isPKMissing(Model, cb)) { if (isPKMissing(Model, cb)) {
return cb.promise; return cb.promise;
} else if (this.isNewRecord()) { } else if (this.isNewRecord()) {
return Model.create(this, options, cb); return Model.create(this, options, cb);
} }
@ -2719,7 +2719,7 @@ DataAccessObject.updateAll = function(where, data, options, cb) {
function doUpdate(where, data) { function doUpdate(where, data) {
try { try {
// Support an optional where object // Support an optional where object
var handleUndefined = Model._getSetting('normalizeUndefinedInQuery'); var handleUndefined = Model._getSetting('normalizeUndefinedInQuery');
// alter configuration of how removeUndefined handles undefined values // alter configuration of how removeUndefined handles undefined values
where = removeUndefined(where, handleUndefined); where = removeUndefined(where, handleUndefined);
where = Model._coerce(where, options); where = Model._coerce(where, options);
@ -2982,7 +2982,7 @@ DataAccessObject.replaceById = function(id, data, options, cb) {
options = options || {}; options = options || {};
assert((typeof data === 'object') && (data !== null), assert((typeof data === 'object') && (data !== null),
'The data argument must be an object'); 'The data argument must be an object');
assert(typeof options === 'object', 'The options argument must be an object'); assert(typeof options === 'object', 'The options argument must be an object');
assert(typeof cb === 'function', 'The cb argument must be a function'); assert(typeof cb === 'function', 'The cb argument must be a function');
@ -3101,7 +3101,7 @@ DataAccessObject.replaceById = function(id, data, options, cb) {
Model._warned.cannotOverwritePKInLoadedHook = true; Model._warned.cannotOverwritePKInLoadedHook = true;
g.warn('WARNING: {{id}} property cannot be changed from %s to %s for model:%s in ' + g.warn('WARNING: {{id}} property cannot be changed from %s to %s for model:%s in ' +
'{{\'loaded\'}} operation hook', '{{\'loaded\'}} operation hook',
id, ctx.data[pkName], Model.modelName); id, ctx.data[pkName], Model.modelName);
} }
inst.__persisted = true; inst.__persisted = true;
@ -3208,7 +3208,7 @@ function(data, options, cb) {
if (data[idName] !== undefined && !idEquals(data[idName], inst[idName])) { if (data[idName] !== undefined && !idEquals(data[idName], inst[idName])) {
var err = new Error(g.f('{{id}} cannot be updated from ' + var err = new Error(g.f('{{id}} cannot be updated from ' +
'%s to %s when {{forceId}} is set to true', '%s to %s when {{forceId}} is set to true',
inst[idName], data[idName])); inst[idName], data[idName]));
err.statusCode = 400; err.statusCode = 400;
process.nextTick(function() { process.nextTick(function() {
cb(err); cb(err);

View File

@ -227,7 +227,7 @@ function connectorModuleNames(name) {
} }
// Only try the short name if the connector is not from StrongLoop // Only try the short name if the connector is not from StrongLoop
if (['mongodb', 'oracle', 'mysql', 'postgresql', 'mssql', 'rest', 'soap', 'db2', 'cloudant'] if (['mongodb', 'oracle', 'mysql', 'postgresql', 'mssql', 'rest', 'soap', 'db2', 'cloudant']
.indexOf(name) === -1) { .indexOf(name) === -1) {
names.push(name); names.push(name);
} }
return names; return names;
@ -272,7 +272,7 @@ DataSource._resolveConnector = function(name, loader) {
if (!connector) { if (!connector) {
error = g.f('\nWARNING: {{LoopBack}} connector "%s" is not installed ' + error = g.f('\nWARNING: {{LoopBack}} connector "%s" is not installed ' +
'as any of the following modules:\n\n %s\n\nTo fix, run:\n\n {{npm install %s --save}}\n', 'as any of the following modules:\n\n %s\n\nTo fix, run:\n\n {{npm install %s --save}}\n',
name, names.join('\n'), names[names.length - 1]); name, names.join('\n'), names[names.length - 1]);
} }
return { return {
connector: connector, connector: connector,
@ -498,7 +498,7 @@ DataSource.prototype.setup = function(dsName, settings) {
} catch (err) { } catch (err) {
if (err.message) { if (err.message) {
err.message = 'Cannot initialize connector ' + err.message = 'Cannot initialize connector ' +
JSON.stringify(connectorName) + ': ' + JSON.stringify(connectorName) + ': ' +
err.message; err.message;
} }
throw err; throw err;
@ -1101,7 +1101,7 @@ DataSource.prototype.autoupdate = function(models, cb) {
if (invalidModels.length) { if (invalidModels.length) {
process.nextTick(function() { process.nextTick(function() {
cb(new Error(g.f('Cannot migrate models not attached to this datasource: %s', cb(new Error(g.f('Cannot migrate models not attached to this datasource: %s',
invalidModels.join(' ')))); invalidModels.join(' '))));
}); });
return cb.promise; return cb.promise;
} }

View File

@ -106,7 +106,7 @@ function deprecateHook(ctor, prefixes, capitalizedName) {
var hookName = candidateNames.filter(function(hook) { return !!ctor[hook]; })[0]; var hookName = candidateNames.filter(function(hook) { return !!ctor[hook]; })[0];
if (!hookName) return; // just to be sure, this should never happen if (!hookName) return; // just to be sure, this should never happen
if (ctor.modelName) hookName = ctor.modelName + '.' + hookName; if (ctor.modelName) hookName = ctor.modelName + '.' + hookName;
deprecated(g.f('Model hook "%s" is deprecated, ' + deprecated(g.f('Model hook "%s" is deprecated, ' +
'use Operation hooks instead. ' + 'use Operation hooks instead. ' +
'{{http://docs.strongloop.com/display/LB/Operation+hooks}}', hookName)); '{{http://docs.strongloop.com/display/LB/Operation+hooks}}', hookName));

View File

@ -575,7 +575,7 @@ function lookupModelTo(modelFrom, modelToRef, params, singularize) {
if (!modelTo) { if (!modelTo) {
// lookup by modelTo name was not successful. Now looking-up by relationTo name // lookup by modelTo name was not successful. Now looking-up by relationTo name
var relationToName = params.as || modelToRef; // modelToRef might be relationTo name var relationToName = params.as || modelToRef; // modelToRef might be relationTo name
modelToName = (singularize ? i8n.singularize(relationToName) : relationToName).toLowerCase(); modelToName = (singularize ? i8n.singularize(relationToName) : relationToName).toLowerCase();
modelTo = lookupModel(modelFrom.dataSource.modelBuilder.models, modelToName); modelTo = lookupModel(modelFrom.dataSource.modelBuilder.models, modelToName);
} }
@ -787,7 +787,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelToRef, params) {
if (relation.type === RelationTypes.belongsTo && if (relation.type === RelationTypes.belongsTo &&
(relation.polymorphic && !relation.modelTo || relation.modelTo === definition.modelTo) && (relation.polymorphic && !relation.modelTo || relation.modelTo === definition.modelTo) &&
(relation.keyFrom === definition.keyThrough) (relation.keyFrom === definition.keyThrough)
) { ) {
throughRelationName = relation.name; throughRelationName = relation.name;
break; break;
} }
@ -992,7 +992,7 @@ var throughKeys = function(definition) {
}); });
} else { } else {
fk1 = findBelongsTo(modelThrough, definition.modelFrom, fk1 = findBelongsTo(modelThrough, definition.modelFrom,
definition.keyFrom)[0]; definition.keyFrom)[0];
fk2 = findBelongsTo(modelThrough, definition.modelTo, pk2)[0]; fk2 = findBelongsTo(modelThrough, definition.modelTo, pk2)[0];
} }
return [fk1, fk2]; return [fk1, fk2];
@ -1022,8 +1022,8 @@ HasManyThrough.prototype.findById = function(fkId, options, cb) {
if (!err) { if (!err) {
err = new Error(g.f('No relation found in %s' + err = new Error(g.f('No relation found in %s' +
' for (%s.%s,%s.%s)', ' for (%s.%s,%s.%s)',
modelThrough.modelName, self.definition.modelFrom.modelName, modelThrough.modelName, self.definition.modelFrom.modelName,
modelInstance[pk], modelTo.modelName, fkId)); modelInstance[pk], modelTo.modelName, fkId));
err.statusCode = 404; err.statusCode = 404;
} }
return cb(err); return cb(err);
@ -1825,7 +1825,7 @@ HasOne.prototype.create = function(targetModelData, options, cb) {
} else { } else {
cb && cb(new Error(g.f( cb && cb(new Error(g.f(
'{{HasOne}} relation cannot create more than one instance of %s', '{{HasOne}} relation cannot create more than one instance of %s',
modelTo.modelName))); modelTo.modelName)));
} }
}); });
return cb.promise; return cb.promise;
@ -2472,10 +2472,10 @@ RelationDefinition.embedsMany = function embedsMany(modelFrom, modelToRef, param
var opts = Object.assign( var opts = Object.assign(
params.options && params.options.property ? params.options.property : {}, params.options && params.options.property ? params.options.property : {},
params.options && params.options.omitDefaultEmbeddedItem ? {type: [modelTo]} : params.options && params.options.omitDefaultEmbeddedItem ? {type: [modelTo]} :
{ {
type: [modelTo], type: [modelTo],
default: function() { return []; }, default: function() { return []; },
} }
); );
modelFrom.dataSource.defineProperty(modelFrom.modelName, propertyName, opts); modelFrom.dataSource.defineProperty(modelFrom.modelName, propertyName, opts);
@ -2785,12 +2785,12 @@ EmbedsMany.prototype.updateById = function(fkId, data, options, cb) {
if (typeof cb === 'function') { if (typeof cb === 'function') {
modelInstance.updateAttribute(propertyName, embeddedList, options, modelInstance.updateAttribute(propertyName, embeddedList, options,
function(err) { function(err) {
if (err) return cb(err, inst); if (err) return cb(err, inst);
modelTo.notifyObserversOf('after save', context, function(err) { modelTo.notifyObserversOf('after save', context, function(err) {
cb(err, inst); cb(err, inst);
});
}); });
});
} else { } else {
modelTo.notifyObserversOf('after save', context, function(err) { modelTo.notifyObserversOf('after save', context, function(err) {
if (!err) return; if (!err) return;

View File

@ -63,7 +63,7 @@ function setScopeValuesFromWhere(data, where, targetModel) {
if (prop) { if (prop) {
var val = where[i]; var val = where[i];
if (typeof val !== 'object' || val instanceof prop.type || if (typeof val !== 'object' || val instanceof prop.type ||
prop.type.name === 'ObjectID' || // MongoDB key prop.type.name === 'ObjectID' || // MongoDB key
prop.type.name === 'uuidFromString') { // C* prop.type.name === 'uuidFromString') { // C*
// Only pick the {propertyName: propertyValue} // Only pick the {propertyName: propertyValue}
data[i] = where[i]; data[i] = where[i];
@ -358,7 +358,7 @@ function parseSettings(urlStr) {
settings.port = uri.port && Number(uri.port); // port is a string settings.port = uri.port && Number(uri.port); // port is a string
settings.user = settings.username = uri.auth && uri.auth.split(':')[0]; // <username>:<password> settings.user = settings.username = uri.auth && uri.auth.split(':')[0]; // <username>:<password>
settings.password = uri.auth && uri.auth.split(':')[1]; settings.password = uri.auth && uri.auth.split(':')[1];
settings.database = uri.pathname && uri.pathname.split('/')[1]; // remove the leading / settings.database = uri.pathname && uri.pathname.split('/')[1]; // remove the leading /
settings.url = urlStr; settings.url = urlStr;
if (uri.query) { if (uri.query) {
var params = qs.parse(uri.query); var params = qs.parse(uri.query);

View File

@ -869,8 +869,8 @@ function ValidationError(obj) {
var context = obj && obj.constructor && obj.constructor.modelName; var context = obj && obj.constructor && obj.constructor.modelName;
this.message = g.f( this.message = g.f(
'The %s instance is not valid. Details: %s.', 'The %s instance is not valid. Details: %s.',
context ? '`' + context + '`' : 'model', context ? '`' + context + '`' : 'model',
formatErrors(obj.errors, obj.toJSON()) || '(unknown)' formatErrors(obj.errors, obj.toJSON()) || '(unknown)'
); );
this.statusCode = 422; this.statusCode = 422;

View File

@ -15,7 +15,7 @@
"ORM" "ORM"
], ],
"engines": { "engines": {
"node": ">=4.0.0" "node": ">=6"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -37,12 +37,12 @@
"@types/node": "^10.0.8", "@types/node": "^10.0.8",
"async-iterators": "^0.2.2", "async-iterators": "^0.2.2",
"bson": "^1.0.4", "bson": "^1.0.4",
"coveralls": "^2.13.1", "coveralls": "^3.0.1",
"eslint": "^3.12.2", "eslint": "^4.19.1",
"eslint-config-loopback": "^8.0.0", "eslint-config-loopback": "^10.0.0",
"loopback-connector-throwing": "file:./test/fixtures/loopback-connector-throwing", "loopback-connector-throwing": "file:./test/fixtures/loopback-connector-throwing",
"mocha": "^3.2.0", "mocha": "^5.2.0",
"nyc": "^11.1.0", "nyc": "^12.0.2",
"should": "^8.4.0", "should": "^8.4.0",
"typescript": "^2.8.3" "typescript": "^2.8.3"
}, },
@ -57,7 +57,7 @@
"minimatch": "^3.0.3", "minimatch": "^3.0.3",
"qs": "^6.5.0", "qs": "^6.5.0",
"shortid": "^2.2.6", "shortid": "^2.2.6",
"strong-globalize": "^3.1.0", "strong-globalize": "^4.1.1",
"traverse": "^0.6.6", "traverse": "^0.6.6",
"uuid": "^3.0.1" "uuid": "^3.0.1"
}, },

View File

@ -137,27 +137,27 @@ describe('basic-querying', function() {
createdUsers[1].id, createdUsers[1].id,
createdUsers[2].id, createdUsers[2].id,
createdUsers[3].id], createdUsers[3].id],
{where: {vip: true}}, function(err, users) { {where: {vip: true}}, function(err, users) {
should.exist(users); should.exist(users);
should.not.exist(err); should.not.exist(err);
var names = users.map(function(u) { var names = users.map(function(u) {
return u.name; return u.name;
});
names.should.eql(createdUsers.slice(0, 4).
filter(function(u) {
return u.vip;
}).map(function(u) {
return u.name;
}));
done();
}); });
names.should.eql(createdUsers.slice(0, 4).
filter(function(u) {
return u.vip;
}).map(function(u) {
return u.name;
}));
done();
});
}); });
bdd.itIf(connectorCapabilities.nullDataValueExists !== false, bdd.itIf(connectorCapabilities.nullDataValueExists !== false,
'should query by ids to check null property', function(done) { 'should query by ids to check null property', function(done) {
User.findByIds([ User.findByIds([
createdUsers[0].id, createdUsers[0].id,
createdUsers[1].id], createdUsers[1].id],
{where: {vip: null}}, function(err, users) { {where: {vip: null}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
@ -165,7 +165,7 @@ describe('basic-querying', function() {
users[0].name.should.eql(createdUsers[1].name); users[0].name.should.eql(createdUsers[1].name);
done(); done();
}); });
}); });
}); });
describe('find', function() { describe('find', function() {
@ -334,28 +334,28 @@ describe('basic-querying', function() {
}); });
bdd.itIf(connectorCapabilities.nullDataValueExists !== false, bdd.itIf(connectorCapabilities.nullDataValueExists !== false,
'should support where date "neq" null', function(done) { 'should support where date "neq" null', function(done) {
User.find({where: {birthday: {'neq': null}, User.find({where: {birthday: {'neq': null},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.should.have.property('length', 2); users.should.have.property('length', 2);
should(users[0].name).be.oneOf('John Lennon', 'Paul McCartney'); should(users[0].name).be.oneOf('John Lennon', 'Paul McCartney');
should(users[1].name).be.oneOf('John Lennon', 'Paul McCartney'); should(users[1].name).be.oneOf('John Lennon', 'Paul McCartney');
done(); done();
});
}); });
});
bdd.itIf(connectorCapabilities.nullDataValueExists !== false, bdd.itIf(connectorCapabilities.nullDataValueExists !== false,
'should support where date is null', function(done) { 'should support where date is null', function(done) {
User.find({where: {birthday: null, User.find({where: {birthday: null,
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.should.have.property('length', 4); users.should.have.property('length', 4);
done(); done();
});
}); });
});
it('should support date "gte" that is satisfied', function(done) { it('should support date "gte" that is satisfied', function(done) {
User.find({where: {birthday: {'gte': new Date('1980-12-08')}, User.find({where: {birthday: {'gte': new Date('1980-12-08')},
@ -887,13 +887,13 @@ describe('basic-querying', function() {
'should support nested property for order in query', 'should support nested property for order in query',
function(done) { function(done) {
User.find({where: {'address.state': 'CA'}, order: 'address.city DESC'}, User.find({where: {'address.state': 'CA'}, order: 'address.city DESC'},
function(err, users) { function(err, users) {
if (err) return done(err); if (err) return done(err);
users.length.should.be.equal(2); users.length.should.be.equal(2);
users[0].address.city.should.be.eql('San Mateo'); users[0].address.city.should.be.eql('San Mateo');
users[1].address.city.should.be.eql('San Jose'); users[1].address.city.should.be.eql('San Jose');
done(); done();
}); });
}); });
it('should support multi-level nested array property in query', function(done) { it('should support multi-level nested array property in query', function(done) {
@ -907,13 +907,13 @@ describe('basic-querying', function() {
}); });
it('should fail when querying with an invalid value for a type', it('should fail when querying with an invalid value for a type',
function(done) { function(done) {
User.find({where: {birthday: 'notadate'}}, function(err, users) { User.find({where: {birthday: 'notadate'}}, function(err, users) {
should.exist(err); should.exist(err);
err.message.should.equal('Invalid date: notadate'); err.message.should.equal('Invalid date: notadate');
done(); done();
});
}); });
});
}); });
}); });
@ -1160,16 +1160,16 @@ describe.skip('queries', function() {
}); });
it('should return an error for deleteById/destroyById/removeById', it('should return an error for deleteById/destroyById/removeById',
function(done) { function(done) {
var aliases = ['deleteById', 'destroyById', 'removeById']; var aliases = ['deleteById', 'destroyById', 'removeById'];
async.each(aliases, function(alias, cb) { async.each(aliases, function(alias, cb) {
Todo[alias](1, function(err) { Todo[alias](1, function(err) {
should.exist(err); should.exist(err);
err.message.should.equal(expectedErrMsg); err.message.should.equal(expectedErrMsg);
cb(); cb();
}); });
}, done); }, done);
}); });
it('should return an error for instance.save', function(done) { it('should return an error for instance.save', function(done) {
var todo = new Todo(); var todo = new Todo();

View File

@ -90,6 +90,7 @@ function clearAndCreate(model, data, callback) {
} }
} }
/* eslint-disable mocha/handle-done-callback */
function testOrm(dataSource) { function testOrm(dataSource) {
var requestsAreCounted = dataSource.name !== 'mongodb'; var requestsAreCounted = dataSource.name !== 'mongodb';
@ -407,7 +408,7 @@ function testOrm(dataSource) {
dataSource.name !== 'memory' && dataSource.name !== 'memory' &&
dataSource.name !== 'neo4j' && dataSource.name !== 'neo4j' &&
dataSource.name !== 'cradle' dataSource.name !== 'cradle'
) )
it('relations key is working', function(test) { it('relations key is working', function(test) {
test.ok(User.relations, 'Relations key should be defined'); test.ok(User.relations, 'Relations key should be defined');
test.ok(User.relations.posts, 'posts relation should exist on User'); test.ok(User.relations.posts, 'posts relation should exist on User');

View File

@ -124,7 +124,7 @@ describe('DataSource', function() {
/** /**
* new DataSource(dsName, connectorInstance) * new DataSource(dsName, connectorInstance)
*/ */
it('should accept resolved connector', function() { it('should accept dsName and resolved connector', function() {
var mockConnector = { var mockConnector = {
name: 'loopback-connector-mock', name: 'loopback-connector-mock',
initialize: function(ds, cb) { initialize: function(ds, cb) {

View File

@ -156,19 +156,19 @@ describe('datatypes', function() {
}); });
it('rejects array value converted to NaN for a required property', it('rejects array value converted to NaN for a required property',
function(done) { function(done) {
db = getSchema(); db = getSchema();
Model = db.define('RequiredNumber', { Model = db.define('RequiredNumber', {
num: {type: Number, required: true}, num: {type: Number, required: true},
}); });
db.automigrate(['Model'], function() { db.automigrate(['Model'], function() {
Model.create({num: [1, 2, 3]}, function(err, inst) { Model.create({num: [1, 2, 3]}, function(err, inst) {
should.exist(err); should.exist(err);
err.should.have.property('name').equal('ValidationError'); err.should.have.property('name').equal('ValidationError');
done(); done();
});
}); });
}); });
});
it('handles null data', (done) => { it('handles null data', (done) => {
db = getSchema(); db = getSchema();

View File

@ -667,6 +667,7 @@ describe('default scope', function() {
}); });
}); });
// eslint-disable-next-line mocha/no-identical-title
it('should find a scoped instance - thing', function(done) { it('should find a scoped instance - thing', function(done) {
Product.find({where: {name: 'Product'}}, function(err, products) { Product.find({where: {name: 'Product'}}, function(err, products) {
products.should.have.length(2); products.should.have.length(2);

View File

@ -162,20 +162,20 @@ describe('Memory connector with mocked discovery', function() {
function(done) { function(done) {
ds.connector.discoverSchemas = null; ds.connector.discoverSchemas = null;
ds.discoverSchemas('INVENTORY', {}) ds.discoverSchemas('INVENTORY', {})
.then(function(schemas) { .then(function(schemas) {
schemas.should.have.property('STRONGLOOP.INVENTORY'); schemas.should.have.property('STRONGLOOP.INVENTORY');
var s = schemas['STRONGLOOP.INVENTORY']; var s = schemas['STRONGLOOP.INVENTORY'];
s.name.should.be.eql('Inventory'); s.name.should.be.eql('Inventory');
Object.keys(s.properties).should.be.eql( Object.keys(s.properties).should.be.eql(
['productId', 'locationId', 'available', 'total'] ['productId', 'locationId', 'available', 'total']
); );
done(); done();
}) })
.catch(function(err) { .catch(function(err) {
done(err); done(err);
}); });
}); });
describe('discoverSchema', function() { describe('discoverSchema', function() {
@ -344,9 +344,9 @@ describe('discoverModelDefinitions', function() {
); );
done(); done();
}) })
.catch(function(err) { .catch(function(err) {
done(err); done(err);
}); });
}); });
}); });
@ -430,9 +430,9 @@ describe('discoverModelProperties', function() {
schemas.should.be.eql(modelProperties); schemas.should.be.eql(modelProperties);
done(); done();
}) })
.catch(function(err) { .catch(function(err) {
done(err); done(err);
}); });
}); });
}); });
@ -599,16 +599,16 @@ describe('discoverExportedForeignKeys', function() {
}); });
it('should discover foreign key definitions using `discoverExportedForeignKeys` - promise variant', it('should discover foreign key definitions using `discoverExportedForeignKeys` - promise variant',
function(done) { function(done) {
ds.discoverExportedForeignKeys('INVENTORY', {}) ds.discoverExportedForeignKeys('INVENTORY', {})
.then(function(modelForeignKeys) { .then(function(modelForeignKeys) {
modelForeignKeys.should.be.eql(exportedForeignKeys); modelForeignKeys.should.be.eql(exportedForeignKeys);
done(); done();
}) })
.catch(function(err) { .catch(function(err) {
done(err); done(err);
}); });
}); });
}); });
describe('Mock connector', function() { describe('Mock connector', function() {

View File

@ -19,7 +19,7 @@ describe('exclude properties ', function() {
var User = ds.define('User', {name: String, password: String}); var User = ds.define('User', {name: String, password: String});
var properties = User.definition.properties; var properties = User.definition.properties;
// User should have id, name & password properties // User should have id, name & password properties
assert(('id' in properties) && ('password' in properties) && ('name' in properties), assert(('id' in properties) && ('password' in properties) && ('name' in properties),
'User should have id, name & password properties'); 'User should have id, name & password properties');
// Create sub model Customer with vip as property. id property gets automatically created here as well. // Create sub model Customer with vip as property. id property gets automatically created here as well.
// Customer will inherit name, password and id from base User model. // Customer will inherit name, password and id from base User model.

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ describe('include_util', function() {
describe('#buildOneToOneIdentityMapWithOrigKeys', function() { describe('#buildOneToOneIdentityMapWithOrigKeys', function() {
it('should return an object with keys', function() { it('should return an object with keys', function() {
var objs = [ var objs = [
{id: 11, letter: 'A'}, {id: 11, letter: 'A'},
{id: 22, letter: 'B'}, {id: 22, letter: 'B'},
]; ];
var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id'); var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id');
result.get(11).should.be.ok; result.get(11).should.be.ok;
@ -36,19 +36,17 @@ describe('include_util', function() {
result.get(11)['letter'].should.equal('HA!'); result.get(11)['letter'].should.equal('HA!');
result.get(33)['letter'].should.equal('C'); result.get(33)['letter'].should.equal('C');
}); });
});
describe('#buildOneToOneIdentityMapWithOrigKeys', function() { it('should return an object with no additional keys', function() {
it('should return an object with keys', function() {
var objs = [ var objs = [
{id: 11, letter: 'A'}, {id: 11, letter: 'A'},
{id: 22, letter: 'B'}, {id: 22, letter: 'B'},
]; ];
var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id'); var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id');
result.get(11).should.be.ok; result.getKeys().should.eql([11, 22]); // no additional properties
result.get(22).should.be.ok;
result.getKeys().should.have.lengthOf(2); // no additional properties
}); });
}); });
describe('#buildOneToManyIdentityMap', function() { describe('#buildOneToManyIdentityMap', function() {
it('should return an object with keys', function() { it('should return an object with keys', function() {
var objs = [ var objs = [

View File

@ -15,7 +15,7 @@ function givenCacheItem(dataSourceFactory) {
}; };
function givenModel(dataSourceFactory, modelName, function givenModel(dataSourceFactory, modelName,
modelProperties, options) { modelProperties, options) {
const dataSource = dataSourceFactory(); const dataSource = dataSourceFactory();
const Model = dataSource.createModel(modelName, modelProperties); const Model = dataSource.createModel(modelName, modelProperties);
const p = 'deleteAll' in dataSource.connector ? const p = 'deleteAll' in dataSource.connector ?

View File

@ -69,9 +69,9 @@ module.exports = function(dataSourceFactory, connectorCapabilities) {
it('honours options.ttl', function() { it('honours options.ttl', function() {
return CacheItem.set('a-key', 'a-value', {ttl: TTL_PRECISION}) return CacheItem.set('a-key', 'a-value', {ttl: TTL_PRECISION})
.delay(2 * TTL_PRECISION) .delay(2 * TTL_PRECISION)
.then(function() { return CacheItem.get('a-key'); }) .then(function() { return CacheItem.get('a-key'); })
.then(function(value) { should.equal(value, null); }); .then(function(value) { should.equal(value, null); });
}); });
describe('get', function() { describe('get', function() {

View File

@ -24,25 +24,25 @@ module.exports = function(dataSourceFactory, connectorCapabilities) {
beforeEach(setupCacheItem); beforeEach(setupCacheItem);
it('gets TTL when key with unexpired TTL exists - Promise API', it('gets TTL when key with unexpired TTL exists - Promise API',
function() { function() {
return Promise.resolve( return Promise.resolve(
CacheItem.set('a-key', 'a-value', {ttl: INITIAL_TTL})) CacheItem.set('a-key', 'a-value', {ttl: INITIAL_TTL}))
.delay(SMALL_DELAY) .delay(SMALL_DELAY)
.then(function() { return CacheItem.ttl('a-key'); }) .then(function() { return CacheItem.ttl('a-key'); })
.then(function(ttl) { ttl.should.be.within(1, INITIAL_TTL); }); .then(function(ttl) { ttl.should.be.within(1, INITIAL_TTL); });
}); });
it('gets TTL when key with unexpired TTL exists - Callback API', it('gets TTL when key with unexpired TTL exists - Callback API',
function(done) { function(done) {
CacheItem.set('a-key', 'a-value', {ttl: INITIAL_TTL}, function(err) { CacheItem.set('a-key', 'a-value', {ttl: INITIAL_TTL}, function(err) {
if (err) return done(err);
CacheItem.ttl('a-key', function(err, ttl) {
if (err) return done(err); if (err) return done(err);
ttl.should.be.within(1, INITIAL_TTL); CacheItem.ttl('a-key', function(err, ttl) {
done(); if (err) return done(err);
ttl.should.be.within(1, INITIAL_TTL);
done();
});
}); });
}); });
});
it('succeeds when key without TTL exists', function() { it('succeeds when key without TTL exists', function() {
return CacheItem.set('a-key', 'a-value') return CacheItem.set('a-key', 'a-value')
@ -52,7 +52,7 @@ module.exports = function(dataSourceFactory, connectorCapabilities) {
it('fails when getting TTL for a key with expired TTL', function() { it('fails when getting TTL for a key with expired TTL', function() {
return Promise.resolve( return Promise.resolve(
CacheItem.set('expired-key', 'a-value', {ttl: TTL_PRECISION})) CacheItem.set('expired-key', 'a-value', {ttl: TTL_PRECISION}))
.delay(2 * TTL_PRECISION) .delay(2 * TTL_PRECISION)
.then(function() { .then(function() {
return CacheItem.ttl('expired-key'); return CacheItem.ttl('expired-key');

View File

@ -339,7 +339,7 @@ describe('DataSource define model', function() {
it('supports plain model definitions', function() { it('supports plain model definitions', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
// define models // define models
var Post = ds.define('Post', { var Post = ds.define('Post', {
title: {type: String, length: 255}, title: {type: String, length: 255},
content: {type: ModelBuilder.Text}, content: {type: ModelBuilder.Text},
@ -350,7 +350,7 @@ describe('DataSource define model', function() {
published: {type: Boolean, default: false, index: true}, published: {type: Boolean, default: false, index: true},
}); });
// simpler way to describe model // simpler way to describe model
var User = ds.define('User', { var User = ds.define('User', {
name: String, name: String,
bio: ModelBuilder.Text, bio: ModelBuilder.Text,
@ -362,7 +362,7 @@ describe('DataSource define model', function() {
var Group = ds.define('Group', {group: String}); var Group = ds.define('Group', {group: String});
User.mixin(Group); User.mixin(Group);
// define any custom method // define any custom method
User.prototype.getNameAndAge = function() { User.prototype.getNameAndAge = function() {
return this.name + ', ' + this.age; return this.name + ', ' + this.age;
}; };
@ -418,7 +418,7 @@ describe('DataSource define model', function() {
}); });
}); });
// should be able to attach a data source to an existing model // should be able to attach a data source to an existing model
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var Color = modelBuilder.define('Color', { var Color = modelBuilder.define('Color', {
@ -427,7 +427,7 @@ describe('DataSource define model', function() {
Color.should.not.have.property('create'); Color.should.not.have.property('create');
// attach // attach
ds.attach(Color); ds.attach(Color);
Color.should.have.property('create'); Color.should.have.property('create');
@ -971,7 +971,7 @@ describe('DataSource connector types', function() {
}); });
}); });
describe('DataSource constructor', function() { describe('DataSource._resolveConnector', function() {
// Mocked require // Mocked require
var loader = function(name) { var loader = function(name) {
if (name.indexOf('./connectors/') !== -1) { if (name.indexOf('./connectors/') !== -1) {

View File

@ -228,11 +228,11 @@ describe('manipulation', function() {
should.exist(p); should.exist(p);
should.not.exists(p.name); should.not.exists(p.name);
return Person.findById(p.id) return Person.findById(p.id)
.then(function(person) { .then(function(person) {
person.id.should.eql(p.id); person.id.should.eql(p.id);
should.not.exists(person.name); should.not.exists(person.name);
done(); done();
}); });
}).catch(done); }).catch(done);
}); });
@ -528,20 +528,20 @@ describe('manipulation', function() {
}); });
it('should have updated password hashed with updateAttribute', it('should have updated password hashed with updateAttribute',
function(done) { function(done) {
StubUser.create({password: 'foo'}, function(err, created) { StubUser.create({password: 'foo'}, function(err, created) {
if (err) return done(err);
created.updateAttribute('password', 'test', function(err, created) {
if (err) return done(err); if (err) return done(err);
created.password.should.equal('test-TEST'); created.updateAttribute('password', 'test', function(err, created) {
StubUser.findById(created.id, function(err, found) {
if (err) return done(err); if (err) return done(err);
found.password.should.equal('test-TEST'); created.password.should.equal('test-TEST');
done(); StubUser.findById(created.id, function(err, found) {
if (err) return done(err);
found.password.should.equal('test-TEST');
done();
});
}); });
}); });
}); });
});
it('should reject created StubUser with empty password', function(done) { it('should reject created StubUser with empty password', function(done) {
StubUser.create({email: 'b@example.com', password: ''}, function(err, createdUser) { StubUser.create({email: 'b@example.com', password: ''}, function(err, createdUser) {
@ -574,14 +574,14 @@ describe('manipulation', function() {
it('should update one attribute (promise variant)', function(done) { it('should update one attribute (promise variant)', function(done) {
person.updateAttribute('name', 'Teddy Graham') person.updateAttribute('name', 'Teddy Graham')
.then(function(p) { .then(function(p) {
return Person.all() return Person.all()
.then(function(ps) { .then(function(ps) {
ps.should.have.lengthOf(1); ps.should.have.lengthOf(1);
ps.pop().name.should.equal('Teddy Graham'); ps.pop().name.should.equal('Teddy Graham');
done(); done();
}); });
}).catch(done); }).catch(done);
}); });
it('should ignore undefined values on updateAttributes', function(done) { it('should ignore undefined values on updateAttributes', function(done) {
@ -732,10 +732,10 @@ describe('manipulation', function() {
it('should fail if an id value is to be changed on updateAttributes', it('should fail if an id value is to be changed on updateAttributes',
function(done) { function(done) {
person.updateAttributes({id: person.id + 1, name: 'John'}, person.updateAttributes({id: person.id + 1, name: 'John'},
function(err, p) { function(err, p) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('has an alias "patchAttributes"', function(done) { it('has an alias "patchAttributes"', function(done) {
@ -996,14 +996,14 @@ describe('manipulation', function() {
}); });
it('fails when id does not exist in db & validate is false when using updateAttributes', it('fails when id does not exist in db & validate is false when using updateAttributes',
function(done) { function(done) {
var unknownId = uid.fromConnector(db) || 123; var unknownId = uid.fromConnector(db) || 123;
var post = new Post({id: unknownId}); var post = new Post({id: unknownId});
post.updateAttributes({title: 'updated title', content: 'AAA'}, {validate: false}, (err) => { post.updateAttributes({title: 'updated title', content: 'AAA'}, {validate: false}, (err) => {
should(err).have.property('statusCode', 404); should(err).have.property('statusCode', 404);
done(); done();
});
}); });
});
it('works on create if the request does not include an id', function(done) { it('works on create if the request does not include an id', function(done) {
var post = {title: 'a', content: 'AAA'}; var post = {title: 'a', content: 'AAA'};
@ -1053,45 +1053,45 @@ describe('manipulation', function() {
it('works without options on create (promise variant)', function(done) { it('works without options on create (promise variant)', function(done) {
var post = {id: unknownId, title: 'a', content: 'AAA'}; var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceOrCreate(post) Post.replaceOrCreate(post)
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
return Post.findById(p.id)
.then(function(p) { .then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(post.id); p.id.should.eql(post.id);
p.id.should.not.have.property('_id'); p.should.not.have.property('_id');
p.title.should.equal(p.title); p.title.should.equal(post.title);
p.content.should.equal(p.content); p.content.should.equal(post.content);
done(); return Post.findById(p.id)
}); .then(function(p) {
}) p.id.should.eql(post.id);
.catch(done); p.id.should.not.have.property('_id');
p.title.should.equal(p.title);
p.content.should.equal(p.content);
done();
});
})
.catch(done);
}); });
it('works with options on create (promise variant)', function(done) { it('works with options on create (promise variant)', function(done) {
var post = {id: unknownId, title: 'a', content: 'AAA'}; var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceOrCreate(post, {validate: false}) Post.replaceOrCreate(post, {validate: false})
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
return Post.findById(p.id)
.then(function(p) { .then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(post.id); p.id.should.eql(post.id);
p.id.should.not.have.property('_id'); p.should.not.have.property('_id');
p.title.should.equal(p.title); p.title.should.equal(post.title);
p.content.should.equal(p.content); p.content.should.equal(post.content);
done(); return Post.findById(p.id)
}); .then(function(p) {
}) p.id.should.eql(post.id);
.catch(done); p.id.should.not.have.property('_id');
p.title.should.equal(p.title);
p.content.should.equal(p.content);
done();
});
})
.catch(done);
}); });
it('works without options on update (promise variant)', function(done) { it('works without options on update (promise variant)', function(done) {
@ -1103,26 +1103,26 @@ describe('manipulation', function() {
delete created.content; delete created.content;
created.title = 'b'; created.title = 'b';
return Post.replaceOrCreate(created) return Post.replaceOrCreate(created)
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(created.id);
p.should.not.have.property('_id');
p.title.should.equal('b');
p.should.have.property('content', undefined);
p.should.have.property('comments', undefined);
return Post.findById(created.id)
.then(function(p) { .then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(created.id);
p.should.not.have.property('_id'); p.should.not.have.property('_id');
p.title.should.equal('b'); p.title.should.equal('b');
should.not.exist(p.content); p.should.have.property('content', undefined);
should.not.exist(p.comments); p.should.have.property('comments', undefined);
done();
return Post.findById(created.id)
.then(function(p) {
p.should.not.have.property('_id');
p.title.should.equal('b');
should.not.exist(p.content);
should.not.exist(p.comments);
done();
});
}); });
});
}) })
.catch(done); .catch(done);
}); });
it('works with options on update (promise variant)', function(done) { it('works with options on update (promise variant)', function(done) {
@ -1134,26 +1134,26 @@ describe('manipulation', function() {
delete created.content; delete created.content;
created.title = 'b'; created.title = 'b';
return Post.replaceOrCreate(created, {validate: false}) return Post.replaceOrCreate(created, {validate: false})
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(created.id);
p.should.not.have.property('_id');
p.title.should.equal('b');
p.should.have.property('content', undefined);
p.should.have.property('comments', undefined);
return Post.findById(created.id)
.then(function(p) { .then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.eql(created.id);
p.should.not.have.property('_id'); p.should.not.have.property('_id');
p.title.should.equal('b'); p.title.should.equal('b');
should.not.exist(p.content); p.should.have.property('content', undefined);
should.not.exist(p.comments); p.should.have.property('comments', undefined);
done();
return Post.findById(created.id)
.then(function(p) {
p.should.not.have.property('_id');
p.title.should.equal('b');
should.not.exist(p.content);
should.not.exist(p.comments);
done();
});
}); });
});
}) })
.catch(done); .catch(done);
}); });
it('works without options on update (callback variant)', function(done) { it('works without options on update (callback variant)', function(done) {
@ -1279,6 +1279,7 @@ describe('manipulation', function() {
}); });
}); });
// eslint-disable-next-line mocha/no-identical-title
it('works on create if the request does not include an id', function(done) { it('works on create if the request does not include an id', function(done) {
var post = {title: 'a', content: 'AAA'}; var post = {title: 'a', content: 'AAA'};
Post.replaceOrCreate(post, function(err, p) { Post.replaceOrCreate(post, function(err, p) {
@ -1289,19 +1290,20 @@ describe('manipulation', function() {
}); });
}); });
// eslint-disable-next-line mocha/no-identical-title
it('works on update if the request includes an existing id in db', function(done) { it('works on update if the request includes an existing id in db', function(done) {
Post.create({title: 'a', content: 'AAA'}, Post.create({title: 'a', content: 'AAA'},
function(err, post) { function(err, post) {
if (err) return done(err);
post = post.toObject();
delete post.content;
post.title = 'b';
Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err); if (err) return done(err);
post = post.toObject(); p.id.should.eql(post.id);
delete post.content; done();
post.title = 'b';
Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err);
p.id.should.eql(post.id);
done();
});
}); });
});
}); });
}); });
@ -1333,20 +1335,20 @@ describe('manipulation', function() {
}); });
it('should have updated password hashed with replaceAttributes', it('should have updated password hashed with replaceAttributes',
function(done) { function(done) {
StubUser.create({password: 'foo'}, function(err, created) { StubUser.create({password: 'foo'}, function(err, created) {
if (err) return done(err);
created.replaceAttributes({password: 'test'}, function(err, created) {
if (err) return done(err); if (err) return done(err);
created.password.should.equal('test-TEST'); created.replaceAttributes({password: 'test'}, function(err, created) {
StubUser.findById(created.id, function(err, found) {
if (err) return done(err); if (err) return done(err);
found.password.should.equal('test-TEST'); created.password.should.equal('test-TEST');
done(); StubUser.findById(created.id, function(err, found) {
if (err) return done(err);
found.password.should.equal('test-TEST');
done();
});
}); });
}); });
}); });
});
it('should reject updated empty password with replaceAttributes', function(done) { it('should reject updated empty password with replaceAttributes', function(done) {
StubUser.create({password: 'abc123'}, function(err, createdUser) { StubUser.create({password: 'abc123'}, function(err, createdUser) {
@ -1427,42 +1429,42 @@ describe('manipulation', function() {
it('works without options(promise variant)', function(done) { it('works without options(promise variant)', function(done) {
Post.findById(postInstance.id) Post.findById(postInstance.id)
.then(function(p) {
p.replaceAttributes({title: 'b'})
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.title.should.equal('b');
p.should.have.property('content', undefined);
return Post.findById(postInstance.id)
.then(function(p) { .then(function(p) {
p.title.should.equal('b'); p.replaceAttributes({title: 'b'})
should.not.exist(p.content); .then(function(p) {
done(); should.exist(p);
}); p.should.be.instanceOf(Post);
}); p.title.should.equal('b');
}) p.should.have.property('content', undefined);
.catch(done); return Post.findById(postInstance.id)
.then(function(p) {
p.title.should.equal('b');
should.not.exist(p.content);
done();
});
});
})
.catch(done);
}); });
it('works with options(promise variant)', function(done) { it('works with options(promise variant)', function(done) {
Post.findById(postInstance.id) Post.findById(postInstance.id)
.then(function(p) {
p.replaceAttributes({title: 'b'}, {validate: false})
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.title.should.equal('b');
p.should.have.property('content', undefined);
return Post.findById(postInstance.id)
.then(function(p) { .then(function(p) {
p.title.should.equal('b'); p.replaceAttributes({title: 'b'}, {validate: false})
should.not.exist(p.content); .then(function(p) {
done(); should.exist(p);
}); p.should.be.instanceOf(Post);
}); p.title.should.equal('b');
}) p.should.have.property('content', undefined);
.catch(done); return Post.findById(postInstance.id)
.then(function(p) {
p.title.should.equal('b');
should.not.exist(p.content);
done();
});
});
})
.catch(done);
}); });
it('should fail when changing id', function(done) { it('should fail when changing id', function(done) {
@ -1584,18 +1586,18 @@ describe('manipulation', function() {
Person.findOrCreate( Person.findOrCreate(
{where: {name: 'Jed'}}, {where: {name: 'Jed'}},
{name: 'Jed', gender: 'male'}) {name: 'Jed', gender: 'male'})
.then(function(res) { .then(function(res) {
res.should.be.instanceOf(Array); res.should.be.instanceOf(Array);
res.should.have.lengthOf(2); res.should.have.lengthOf(2);
var p = res[0]; var p = res[0];
var created = res[1]; var created = res[1];
p.should.be.instanceOf(Person); p.should.be.instanceOf(Person);
p.name.should.equal('Jed'); p.name.should.equal('Jed');
p.gender.should.equal('male'); p.gender.should.equal('male');
created.should.equal(false); created.should.equal(false);
done(); done();
}) })
.catch(done); .catch(done);
}); });
}); });
@ -1690,47 +1692,47 @@ describe('manipulation', function() {
}); });
it('should only delete instances that satisfy the where condition', it('should only delete instances that satisfy the where condition',
function(done) { function(done) {
Person.deleteAll({name: 'John'}, function(err, info) { Person.deleteAll({name: 'John'}, function(err, info) {
if (err) return done(err);
info.should.have.property('count', 1);
Person.find({where: {name: 'John'}}, function(err, data) {
if (err) return done(err); if (err) return done(err);
info.should.have.property('count', 1); data.should.have.length(0);
Person.find({where: {name: 'John'}}, function(err, data) { Person.find({where: {name: 'Jane'}}, function(err, data) {
if (err) return done(err); if (err) return done(err);
data.should.have.length(0); data.should.have.length(1);
Person.find({where: {name: 'Jane'}}, function(err, data) { done();
if (err) return done(err);
data.should.have.length(1);
done();
});
}); });
}); });
}); });
});
it('should report zero deleted instances when no matches are found', it('should report zero deleted instances when no matches are found',
function(done) { function(done) {
Person.deleteAll({name: 'does-not-match'}, function(err, info) { Person.deleteAll({name: 'does-not-match'}, function(err, info) {
if (err) return done(err);
info.should.have.property('count', 0);
Person.count(function(err, count) {
if (err) return done(err); if (err) return done(err);
info.should.have.property('count', 0); count.should.equal(2);
Person.count(function(err, count) { done();
if (err) return done(err);
count.should.equal(2);
done();
});
}); });
}); });
});
it('should delete all instances when the where condition is not provided', it('should delete all instances when the where condition is not provided',
function(done) { function(done) {
Person.deleteAll(function(err, info) { Person.deleteAll(function(err, info) {
if (err) return done(err);
info.should.have.property('count', 2);
Person.count(function(err, count) {
if (err) return done(err); if (err) return done(err);
info.should.have.property('count', 2); count.should.equal(0);
Person.count(function(err, count) { done();
if (err) return done(err);
count.should.equal(0);
done();
});
}); });
}); });
});
}); });
bdd.describeIf(connectorCapabilities.reportDeletedCount === false && bdd.describeIf(connectorCapabilities.reportDeletedCount === false &&
@ -1757,55 +1759,59 @@ describe('manipulation', function() {
}); });
}); });
// eslint-disable-next-line mocha/no-identical-title
it('should be defined as function', function() { it('should be defined as function', function() {
Person.deleteAll.should.be.a.Function; Person.deleteAll.should.be.a.Function;
Person.destroyAll.should.be.a.Function; Person.destroyAll.should.be.a.Function;
}); });
// eslint-disable-next-line mocha/no-identical-title
it('should only delete instances that satisfy the where condition', it('should only delete instances that satisfy the where condition',
function(done) { function(done) {
Person.deleteAll({id: idJohn}, function(err, info) { Person.deleteAll({id: idJohn}, function(err, info) {
if (err) return done(err);
should.not.exist(info.count);
Person.find({where: {name: 'John'}}, function(err, data) {
if (err) return done(err); if (err) return done(err);
should.not.exist(info.count); should.not.exist(data.count);
Person.find({where: {name: 'John'}}, function(err, data) { data.should.have.length(0);
Person.find({where: {name: 'Jane'}}, function(err, data) {
if (err) return done(err); if (err) return done(err);
should.not.exist(data.count); data.should.have.length(1);
data.should.have.length(0); done();
Person.find({where: {name: 'Jane'}}, function(err, data) {
if (err) return done(err);
data.should.have.length(1);
done();
});
}); });
}); });
}); });
});
// eslint-disable-next-line mocha/no-identical-title
it('should report zero deleted instances when no matches are found', it('should report zero deleted instances when no matches are found',
function(done) { function(done) {
var unknownId = uid.fromConnector(db) || 1234567890; var unknownId = uid.fromConnector(db) || 1234567890;
Person.deleteAll({id: unknownId}, function(err, info) { Person.deleteAll({id: unknownId}, function(err, info) {
if (err) return done(err);
should.not.exist(info.count);
Person.count(function(err, count) {
if (err) return done(err); if (err) return done(err);
should.not.exist(info.count); count.should.equal(2);
Person.count(function(err, count) { done();
if (err) return done(err);
count.should.equal(2);
done();
});
}); });
}); });
});
// eslint-disable-next-line mocha/no-identical-title
it('should delete all instances when the where condition is not provided', it('should delete all instances when the where condition is not provided',
function(done) { function(done) {
Person.deleteAll(function(err, info) { Person.deleteAll(function(err, info) {
if (err) return done(err);
should.not.exist(info.count);
Person.count(function(err, count) {
if (err) return done(err); if (err) return done(err);
should.not.exist(info.count); count.should.equal(0);
Person.count(function(err, count) { done();
if (err) return done(err);
count.should.equal(0);
done();
});
}); });
}); });
});
}); });
describe('deleteById', function() { describe('deleteById', function() {
@ -1903,22 +1909,22 @@ describe('manipulation', function() {
bdd.itIf(connectorCapabilities.supportStrictDelete !== false, 'should allow delete(id) - ' + bdd.itIf(connectorCapabilities.supportStrictDelete !== false, 'should allow delete(id) - ' +
'fail with error', function(done) { 'fail with error', function(done) {
Person.settings.strictDelete = true; Person.settings.strictDelete = true;
Person.findOne(function(err, u) { Person.findOne(function(err, u) {
if (err) return done(err);
u.delete(function(err, info) {
if (err) return done(err); if (err) return done(err);
u.delete(function(err, info) { info.should.have.property('count', 1);
if (err) return done(err); u.delete(function(err) {
info.should.have.property('count', 1); should.exist(err);
u.delete(function(err) { err.message.should.equal('No instance with id ' + u.id + ' found for Person');
should.exist(err); err.should.have.property('code', 'NOT_FOUND');
err.message.should.equal('No instance with id ' + u.id + ' found for Person'); err.should.have.property('statusCode', 404);
err.should.have.property('code', 'NOT_FOUND'); done();
err.should.have.property('statusCode', 404);
done();
});
}); });
}); });
}); });
});
}); });
describe('initialize', function() { describe('initialize', function() {
@ -1933,7 +1939,7 @@ describe('manipulation', function() {
person.isNewRecord().should.be.true; person.isNewRecord().should.be.true;
}); });
describe('Date $now function', function() { describe('Date $now function (type: Date)', function() {
var CustomModel; var CustomModel;
before(function(done) { before(function(done) {
@ -1957,7 +1963,7 @@ describe('manipulation', function() {
}); });
}); });
describe('Date $now function', function() { describe('Date $now function (type: String)', function() {
var CustomModel; var CustomModel;
before(function(done) { before(function(done) {
@ -2202,46 +2208,46 @@ describe('manipulation', function() {
}); });
it('should not update instances that do not satisfy the where condition', it('should not update instances that do not satisfy the where condition',
function(done) { function(done) {
idHarry = uid.fromConnector(db) || undefined; idHarry = uid.fromConnector(db) || undefined;
var filter = connectorCapabilities.updateWithOtherThanId === false ? var filter = connectorCapabilities.updateWithOtherThanId === false ?
{id: idHarry} : {name: 'Harry Hoe'}; {id: idHarry} : {name: 'Harry Hoe'};
Person.update(filter, {name: 'Marta Moe'}, function(err, Person.update(filter, {name: 'Marta Moe'}, function(err,
info) { info) {
if (err) return done(err);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 0);
} else {
should.not.exist(info.count);
}
Person.find({where: {name: 'Harry Hoe'}}, function(err, people) {
if (err) return done(err); if (err) return done(err);
if (connectorCapabilities.reportDeletedCount !== false) { people.should.be.empty;
info.should.have.property('count', 0); done();
} else {
should.not.exist(info.count);
}
Person.find({where: {name: 'Harry Hoe'}}, function(err, people) {
if (err) return done(err);
people.should.be.empty;
done();
});
}); });
}); });
});
it('should only update instances that satisfy the where condition', it('should only update instances that satisfy the where condition',
function(done) { function(done) {
var filter = connectorCapabilities.deleteWithOtherThanId === false ? var filter = connectorCapabilities.deleteWithOtherThanId === false ?
{id: idBrett} : {name: 'Brett Boe'}; {id: idBrett} : {name: 'Brett Boe'};
Person.update(filter, {name: 'Harry Hoe'}, function(err, Person.update(filter, {name: 'Harry Hoe'}, function(err,
info) { info) {
if (err) return done(err);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 1);
} else {
should.not.exist(info.count);
}
Person.find({where: {age: 19}}, function(err, people) {
if (err) return done(err); if (err) return done(err);
if (connectorCapabilities.reportDeletedCount !== false) { people.should.have.length(1);
info.should.have.property('count', 1); people[0].name.should.equal('Harry Hoe');
} else { done();
should.not.exist(info.count);
}
Person.find({where: {age: 19}}, function(err, people) {
if (err) return done(err);
people.should.have.length(1);
people[0].name.should.equal('Harry Hoe');
done();
});
}); });
}); });
});
it('should reject updated empty password with updateAll', function(done) { it('should reject updated empty password with updateAll', function(done) {
StubUser.create({password: 'abc123'}, function(err, createdUser) { StubUser.create({password: 'abc123'}, function(err, createdUser) {
@ -2277,16 +2283,16 @@ describe('manipulation', function() {
bdd.itIf(connectorCapabilities.ignoreUndefinedConditionValue !== false, 'should ignore where ' + bdd.itIf(connectorCapabilities.ignoreUndefinedConditionValue !== false, 'should ignore where ' +
'conditions with undefined values', function(done) { 'conditions with undefined values', function(done) {
Person.update(filterBrett, {name: undefined, gender: 'male'}, Person.update(filterBrett, {name: undefined, gender: 'male'},
function(err, info) { function(err, info) {
if (err) return done(err);
info.should.have.property('count', 1);
Person.find({where: filterBrett}, function(err, people) {
if (err) return done(err); if (err) return done(err);
people.should.have.length(1); info.should.have.property('count', 1);
people[0].name.should.equal('Brett Boe'); Person.find({where: filterBrett}, function(err, people) {
done(); if (err) return done(err);
people.should.have.length(1);
people[0].name.should.equal('Brett Boe');
done();
});
}); });
});
}); });
it('should not coerce invalid values provided in where conditions', function(done) { it('should not coerce invalid values provided in where conditions', function(done) {
@ -2355,16 +2361,16 @@ describe('manipulation', function() {
Person.upsertWithWhere({id: 10}, Person.upsertWithWhere({id: 10},
{name: 'updated name'}, {name: 'updated name'},
function(err, updated) { function(err, updated) {
if (err) return done(err); if (err) return done(err);
var result = updated.toObject(); var result = updated.toObject();
result.should.have.properties({ result.should.have.properties({
id: instance.id, id: instance.id,
name: 'updated name', name: 'updated name',
});
should.equal(result.city, null);
done();
}); });
should.equal(result.city, null);
done();
});
}); });
}); });

View File

@ -320,19 +320,19 @@ describe('Memory connector', function() {
it('should successfully extract 1 user (Lennon) from the db', function(done) { it('should successfully extract 1 user (Lennon) from the db', function(done) {
User.find({where: {birthday: {between: [new Date(1970, 0), new Date(1990, 0)]}}}, User.find({where: {birthday: {between: [new Date(1970, 0), new Date(1990, 0)]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(1); should(users.length).be.equal(1);
should(users[0].name).be.equal('John Lennon'); should(users[0].name).be.equal('John Lennon');
done(); done();
}); });
}); });
it('should successfully extract 2 users from the db', function(done) { it('should successfully extract 2 users from the db', function(done) {
User.find({where: {birthday: {between: [new Date(1940, 0), new Date(1990, 0)]}}}, User.find({where: {birthday: {between: [new Date(1940, 0), new Date(1990, 0)]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(2); should(users.length).be.equal(2);
done(); done();
}); });
}); });
it('should successfully extract 2 users using implied and', function(done) { it('should successfully extract 2 users using implied and', function(done) {
@ -358,18 +358,18 @@ describe('Memory connector', function() {
it('should successfully extract 2 users using date range', function(done) { it('should successfully extract 2 users using date range', function(done) {
User.find({where: {birthday: {between: User.find({where: {birthday: {between:
[new Date(1940, 0).toISOString(), new Date(1990, 0).toISOString()]}}}, [new Date(1940, 0).toISOString(), new Date(1990, 0).toISOString()]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(2); should(users.length).be.equal(2);
done(); done();
}); });
}); });
it('should successfully extract 0 user from the db', function(done) { it('should successfully extract 0 user from the db', function(done) {
User.find({where: {birthday: {between: [new Date(1990, 0), Date.now()]}}}, User.find({where: {birthday: {between: [new Date(1990, 0), Date.now()]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(0); should(users.length).be.equal(0);
done(); done();
}); });
}); });
it('should successfully extract 2 users matching over array values', function(done) { it('should successfully extract 2 users matching over array values', function(done) {
@ -503,14 +503,14 @@ describe('Memory connector', function() {
}); });
it('should work when a regex is provided without the regexp operator', it('should work when a regex is provided without the regexp operator',
function(done) { function(done) {
User.find({where: {name: /John.*/i}}, function(err, users) { User.find({where: {name: /John.*/i}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.equal(1); users.length.should.equal(1);
users[0].name.should.equal('John Lennon'); users[0].name.should.equal('John Lennon');
done(); done();
});
}); });
});
it('should support the regexp operator with regex strings', function(done) { it('should support the regexp operator with regex strings', function(done) {
User.find({where: {name: {regexp: '^J'}}}, function(err, users) { User.find({where: {name: {regexp: '^J'}}}, function(err, users) {
@ -532,7 +532,7 @@ describe('Memory connector', function() {
it('should support the regexp operator with regex objects', function(done) { it('should support the regexp operator with regex objects', function(done) {
User.find({where: {name: {regexp: new RegExp(/^J/)}}}, function(err, User.find({where: {name: {regexp: new RegExp(/^J/)}}}, function(err,
users) { users) {
should.not.exist(err); should.not.exist(err);
users.length.should.equal(1); users.length.should.equal(1);
users[0].name.should.equal('John Lennon'); users[0].name.should.equal('John Lennon');
@ -568,8 +568,8 @@ describe('Memory connector', function() {
state: 'CA', state: 'CA',
zipCode: '95131', zipCode: '95131',
tags: [ tags: [
{tag: 'business'}, {tag: 'business'},
{tag: 'rent'}, {tag: 'rent'},
], ],
}, },
friends: [ friends: [
@ -962,14 +962,6 @@ describe('Memory connector with options', function() {
}); });
}); });
it('should receive options from the find method', function(done) {
var opts = {transaction: 'tx2'};
Post.find({}, opts, function(err, p) {
savedOptions.find.should.be.eql(opts);
done(err);
});
});
it('should treat first object arg as filter for find', function(done) { it('should treat first object arg as filter for find', function(done) {
var filter = {title: 't1'}; var filter = {title: 't1'};
Post.find(filter, function(err, p) { Post.find(filter, function(err, p) {

View File

@ -76,19 +76,19 @@ describe('Model class inheritance', function() {
// saving original getMergePolicy method // saving original getMergePolicy method
let originalGetMergePolicy = base.getMergePolicy; let originalGetMergePolicy = base.getMergePolicy;
// the injected getMergePolicy method captures the provided configureModelMerge option // the injected getMergePolicy method captures the provided configureModelMerge option
base.getMergePolicy = function(options) { base.getMergePolicy = function(options) {
mergePolicy = options && options.configureModelMerge; mergePolicy = options && options.configureModelMerge;
return originalGetMergePolicy(options); return originalGetMergePolicy(options);
}; };
// calling extend() on base model calls base.getMergePolicy() internally // calling extend() on base model calls base.getMergePolicy() internally
// child model settings are passed as 3rd parameter // child model settings are passed as 3rd parameter
const child = base.extend('child', {}, {configureModelMerge: newMergePolicy}); const child = base.extend('child', {}, {configureModelMerge: newMergePolicy});
should.deepEqual(mergePolicy, newMergePolicy); should.deepEqual(mergePolicy, newMergePolicy);
// restoring original getMergePolicy method // restoring original getMergePolicy method
base.getMergePolicy = originalGetMergePolicy; base.getMergePolicy = originalGetMergePolicy;
}); });
@ -109,7 +109,7 @@ describe('Model class inheritance', function() {
it('is inherited by child model', function() { it('is inherited by child model', function() {
const child = base.extend('child', {}, {configureModelMerge: true}); const child = base.extend('child', {}, {configureModelMerge: true});
// get mergePolicy from child // get mergePolicy from child
const mergePolicy = child.getMergePolicy({configureModelMerge: true}); const mergePolicy = child.getMergePolicy({configureModelMerge: true});
should.deepEqual(mergePolicy, recommendedMergePolicy); should.deepEqual(mergePolicy, recommendedMergePolicy);
}); });
@ -128,8 +128,8 @@ describe('Model class inheritance', function() {
}); });
const baseChild = modelBuilder.define('baseChild'); const baseChild = modelBuilder.define('baseChild');
baseChild.attachTo(memory); baseChild.attachTo(memory);
// the name of this must begin with a letter < b // the name of this must begin with a letter < b
// for this test to fail // for this test to fail
const anotherChild = baseChild.extend('anotherChild'); const anotherChild = baseChild.extend('anotherChild');
assert(anotherChild.prototype instanceof baseChild); assert(anotherChild.prototype instanceof baseChild);
@ -220,23 +220,23 @@ describe('Model class inheritance', function() {
}); });
var Customer = User.extend('Customer', var Customer = User.extend('Customer',
{customerId: {type: String, id: true}}, { {customerId: {type: String, id: true}}, {
defaultPermission: 'DENY', defaultPermission: 'DENY',
acls: [ acls: [
{ {
principalType: 'ROLE', principalType: 'ROLE',
principalId: '$unauthenticated', principalId: '$unauthenticated',
permission: 'DENY', permission: 'DENY',
},
],
relations: {
orders: {
type: 'hasMany',
model: 'Order',
},
}, },
} ],
); relations: {
orders: {
type: 'hasMany',
model: 'Order',
},
},
}
);
assert.deepEqual(User.settings, { assert.deepEqual(User.settings, {
// forceId is set to 'auto' in memory if idProp.generated && forceId !== false // forceId is set to 'auto' in memory if idProp.generated && forceId !== false
@ -291,8 +291,8 @@ describe('Model class inheritance', function() {
}); });
it('defines rank of ACLs according to model\'s inheritance rank', function() { it('defines rank of ACLs according to model\'s inheritance rank', function() {
// a simple test is enough as we already fully tested option `{rank: true}` // a simple test is enough as we already fully tested option `{rank: true}`
// in tests with flag `configureModelMerge` // in tests with flag `configureModelMerge`
const modelBuilder = memory.modelBuilder; const modelBuilder = memory.modelBuilder;
const base = modelBuilder.define('base', {}, {acls: [ const base = modelBuilder.define('base', {}, {acls: [
{ {
@ -336,7 +336,7 @@ describe('Model class inheritance', function() {
}); });
it('replaces baseClass relations with matching subClass relations', function() { it('replaces baseClass relations with matching subClass relations', function() {
// merge policy of settings.relations is {patch: true} // merge policy of settings.relations is {patch: true}
const modelBuilder = memory.modelBuilder; const modelBuilder = memory.modelBuilder;
const base = modelBuilder.define('base', {}, { const base = modelBuilder.define('base', {}, {
relations: { relations: {
@ -462,7 +462,7 @@ describe('Model class inheritance', function() {
it('`{replace: true}` replaces base model array with sub model matching ' + it('`{replace: true}` replaces base model array with sub model matching ' +
'array', function() { 'array', function() {
// merge policy of settings.description is {replace: true} // merge policy of settings.description is {replace: true}
const modelBuilder = memory.modelBuilder; const modelBuilder = memory.modelBuilder;
const base = modelBuilder.define('base', {}, { const base = modelBuilder.define('base', {}, {
description: ['base', 'model', 'description'], description: ['base', 'model', 'description'],
@ -515,7 +515,7 @@ describe('Model class inheritance', function() {
it('`{replace: false}` adds distinct members of matching arrays from ' + it('`{replace: false}` adds distinct members of matching arrays from ' +
'base model and sub model', function() { 'base model and sub model', function() {
// merge policy of settings.hidden is {replace: false} // merge policy of settings.hidden is {replace: false}
const modelBuilder = memory.modelBuilder; const modelBuilder = memory.modelBuilder;
const base = modelBuilder.define('base', {}, { const base = modelBuilder.define('base', {}, {
hidden: ['firstProperty', 'secondProperty'], hidden: ['firstProperty', 'secondProperty'],
@ -534,7 +534,7 @@ describe('Model class inheritance', function() {
it('`{patch: true}` adds distinct inner properties of matching objects ' + it('`{patch: true}` adds distinct inner properties of matching objects ' +
'from base model and sub model', function() { 'from base model and sub model', function() {
// merge policy of settings.relations is {patch: true} // merge policy of settings.relations is {patch: true}
const modelBuilder = memory.modelBuilder; const modelBuilder = memory.modelBuilder;
const base = modelBuilder.define('base', {}, { const base = modelBuilder.define('base', {}, {
relations: { relations: {
@ -576,7 +576,7 @@ describe('Model class inheritance', function() {
it('`{patch: true}` replaces baseClass inner properties with matching ' + it('`{patch: true}` replaces baseClass inner properties with matching ' +
'subClass inner properties', function() { 'subClass inner properties', function() {
// merge policy of settings.relations is {patch: true} // merge policy of settings.relations is {patch: true}
const modelBuilder = memory.modelBuilder; const modelBuilder = memory.modelBuilder;
const base = modelBuilder.define('base', {}, { const base = modelBuilder.define('base', {}, {
relations: { relations: {

View File

@ -22,9 +22,9 @@ describe('optional-validation', function() {
before(function(done) { before(function(done) {
db = getSchema(); db = getSchema();
ModelWithForceId = db.createModel( ModelWithForceId = db.createModel(
'ModelWithForceId', 'ModelWithForceId',
{name: String}, {name: String},
{forceId: true}); {forceId: true});
User = db.define('User', { User = db.define('User', {
seq: {type: Number, index: true}, seq: {type: Number, index: true},
name: {type: String, index: true, sort: true}, name: {type: String, index: true, sort: true},
@ -115,26 +115,26 @@ describe('optional-validation', function() {
describe('forceId', function() { describe('forceId', function() {
context('replaceAttributes', function() { context('replaceAttributes', function() {
it('should not fail if you do not pass the Primary key in data object', it('should not fail if you do not pass the Primary key in data object',
function(done) { function(done) {
ModelWithForceId.create({name: 'foo'}, function(err, created) { ModelWithForceId.create({name: 'foo'}, function(err, created) {
if (err) return done(err); if (err) return done(err);
created.replaceAttributes({name: 'bar'}, function(err, data) { created.replaceAttributes({name: 'bar'}, function(err, data) {
done(err); done(err);
});
}); });
}); });
});
it('should fail if you pass the Primary key in data object', it('should fail if you pass the Primary key in data object',
function(done) { function(done) {
ModelWithForceId.create({name: 'foo'}, function(err, created) { ModelWithForceId.create({name: 'foo'}, function(err, created) {
if (err) return done(err); if (err) return done(err);
created.replaceAttributes({name: 'bar', id: 999}, created.replaceAttributes({name: 'bar', id: 999},
function(err, data) { function(err, data) {
should.exist(err); should.exist(err);
done(); done();
});
}); });
}); });
});
}); });
}); });
@ -167,28 +167,28 @@ describe('optional-validation', function() {
describe('method findOrCreate', function() { describe('method findOrCreate', function() {
it('should throw on findOrCreate with validate:true with invalid data', it('should throw on findOrCreate with validate:true with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true}, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on findOrCreate with validate:false with invalid data', it('should NOT throw on findOrCreate with validate:false with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false}, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
expectCreateSuccess(INVALID_DATA, done)); expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on findOrCreate with validate:true with valid data', it('should NOT throw on findOrCreate with validate:true with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true}, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should NOT throw on findOrCreate with validate:false with valid data', it('should NOT throw on findOrCreate with validate:false with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false}, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should throw on findOrCreate with invalid data', function(done) { it('should throw on findOrCreate with invalid data', function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done)); User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done));
@ -201,28 +201,28 @@ describe('optional-validation', function() {
describe('method updateOrCreate on existing data', function() { describe('method updateOrCreate on existing data', function() {
it('should throw on updateOrCreate(id) with validate:true with invalid data', it('should throw on updateOrCreate(id) with validate:true with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, {validate: true}, callUpdateOrCreateWithExistingUserId(null, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data', it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, {validate: false}, callUpdateOrCreateWithExistingUserId(null, {validate: false},
expectChangeSuccess(INVALID_DATA, done)); expectChangeSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:true with valid data', it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true}, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with valid data', it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false}, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
// backwards compatible with validateUpsert // backwards compatible with validateUpsert
it('should NOT throw on updateOrCreate(id) with invalid data', function(done) { it('should NOT throw on updateOrCreate(id) with invalid data', function(done) {
@ -310,17 +310,17 @@ describe('optional-validation', function() {
}); });
it('returns an error when trying to update the id property when forceId is set to true', it('returns an error when trying to update the id property when forceId is set to true',
function(done) { function(done) {
ModelWithForceId.create({name: 'foo'}, function(err, model) { ModelWithForceId.create({name: 'foo'}, function(err, model) {
if (err) return done(err); if (err) return done(err);
model.updateAttributes({id: 123}, function(err) { model.updateAttributes({id: 123}, function(err) {
err.should.be.instanceOf(Error); err.should.be.instanceOf(Error);
err.message.should.eql('id cannot be updated from ' + model.id + err.message.should.eql('id cannot be updated from ' + model.id +
' to 123 when forceId is set to true'); ' to 123 when forceId is set to true');
done(); done();
});
}); });
}); });
});
}); });
}); });
@ -358,32 +358,32 @@ describe('optional-validation', function() {
describe('method findOrCreate', function() { describe('method findOrCreate', function() {
it('should throw on findOrCreate with validate:true with invalid data', it('should throw on findOrCreate with validate:true with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true}, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on findOrCreate with validate:false with invalid data', it('should NOT throw on findOrCreate with validate:false with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false}, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
expectCreateSuccess(INVALID_DATA, done)); expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on findOrCreate with validate:true with valid data', it('should NOT throw on findOrCreate with validate:true with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true}, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should NOT throw on findOrCreate with validate:false with valid data', it('should NOT throw on findOrCreate with validate:false with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false}, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should NOT throw on findOrCreate with invalid data', function(done) { it('should NOT throw on findOrCreate with invalid data', function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, User.findOrCreate(getNewWhere(), INVALID_DATA,
expectCreateSuccess(INVALID_DATA, done)); expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on findOrCreate with valid data', function(done) { it('should NOT throw on findOrCreate with valid data', function(done) {
@ -393,28 +393,28 @@ describe('optional-validation', function() {
describe('method updateOrCreate on existing data', function() { describe('method updateOrCreate on existing data', function() {
it('should throw on updateOrCreate(id) with validate:true with invalid data', it('should throw on updateOrCreate(id) with validate:true with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, {validate: true}, callUpdateOrCreateWithExistingUserId(null, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data', it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, {validate: false}, callUpdateOrCreateWithExistingUserId(null, {validate: false},
expectChangeSuccess(INVALID_DATA, done)); expectChangeSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:true with valid data', it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true}, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with valid data', it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false}, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should NOT throw on updateOrCreate(id) with invalid data', function(done) { it('should NOT throw on updateOrCreate(id) with invalid data', function(done) {
callUpdateOrCreateWithExistingUserId(null, expectChangeSuccess(INVALID_DATA, done)); callUpdateOrCreateWithExistingUserId(null, expectChangeSuccess(INVALID_DATA, done));
@ -498,28 +498,28 @@ describe('optional-validation', function() {
describe('method findOrCreate', function() { describe('method findOrCreate', function() {
it('should throw on findOrCreate with validate:true with invalid data', it('should throw on findOrCreate with validate:true with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true}, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on findOrCreate with validate:false with invalid data', it('should NOT throw on findOrCreate with validate:false with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false}, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
expectCreateSuccess(INVALID_DATA, done)); expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on findOrCreate with validate:true with valid data', it('should NOT throw on findOrCreate with validate:true with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true}, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should NOT throw on findOrCreate with validate:false with valid data', it('should NOT throw on findOrCreate with validate:false with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false}, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should throw on findOrCreate with invalid data', function(done) { it('should throw on findOrCreate with invalid data', function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done)); User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done));
@ -532,28 +532,28 @@ describe('optional-validation', function() {
describe('method updateOrCreate on existing data', function() { describe('method updateOrCreate on existing data', function() {
it('should throw on updateOrCreate(id) with validate:true with invalid data', it('should throw on updateOrCreate(id) with validate:true with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, {validate: true}, callUpdateOrCreateWithExistingUserId(null, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data', it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, {validate: false}, callUpdateOrCreateWithExistingUserId(null, {validate: false},
expectChangeSuccess(INVALID_DATA, done)); expectChangeSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:true with valid data', it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true}, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with valid data', it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false}, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should throw on updateOrCreate(id) with invalid data', function(done) { it('should throw on updateOrCreate(id) with invalid data', function(done) {
callUpdateOrCreateWithExistingUserId(null, expectValidationError(done)); callUpdateOrCreateWithExistingUserId(null, expectValidationError(done));

View File

@ -140,26 +140,26 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
it('triggers the loaded hook multiple times when multiple instances exist when near filter is used', it('triggers the loaded hook multiple times when multiple instances exist when near filter is used',
function(done) { function(done) {
var hookMonitorGeoModel; var hookMonitorGeoModel;
hookMonitorGeoModel = new HookMonitor({includeModelName: false}); hookMonitorGeoModel = new HookMonitor({includeModelName: false});
function monitorHookExecutionGeoModel(hookNames) { function monitorHookExecutionGeoModel(hookNames) {
hookMonitorGeoModel.install(GeoModel, hookNames); hookMonitorGeoModel.install(GeoModel, hookNames);
} }
monitorHookExecutionGeoModel(); monitorHookExecutionGeoModel();
var query = { var query = {
where: {location: {near: '10,5'}}, where: {location: {near: '10,5'}},
}; };
GeoModel.find(query, function(err, list) { GeoModel.find(query, function(err, list) {
if (err) return done(err); if (err) return done(err);
hookMonitorGeoModel.names.should.eql(['access', 'loaded', 'loaded']); hookMonitorGeoModel.names.should.eql(['access', 'loaded', 'loaded']);
done(); done();
});
}); });
});
it('applies updates from `loaded` hook when near filter is used', function(done) { it('applies updates from `loaded` hook when near filter is used', function(done) {
GeoModel.observe('loaded', function(ctx, next) { GeoModel.observe('loaded', function(ctx, next) {
@ -179,23 +179,23 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
it('applies updates to one specific instance from `loaded` hook when near filter is used', it('applies updates to one specific instance from `loaded` hook when near filter is used',
function(done) { function(done) {
GeoModel.observe('loaded', function(ctx, next) { GeoModel.observe('loaded', function(ctx, next) {
if (ctx.data.name === 'Rome') if (ctx.data.name === 'Rome')
ctx.data.name = 'Berlin'; ctx.data.name = 'Berlin';
next(); next();
}); });
var query = { var query = {
where: {location: {near: '10,5'}}, where: {location: {near: '10,5'}},
}; };
GeoModel.find(query, function(err, list) { GeoModel.find(query, function(err, list) {
if (err) return done(err); if (err) return done(err);
list.map(get('name')).should.containEql('Berlin', 'Tokyo'); list.map(get('name')).should.containEql('Berlin', 'Tokyo');
done(); done();
});
}); });
});
it('applies updates from `loaded` hook when near filter is not used', function(done) { it('applies updates from `loaded` hook when near filter is not used', function(done) {
TestModel.observe('loaded', function(ctx, next) { TestModel.observe('loaded', function(ctx, next) {
@ -211,33 +211,33 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
it('applies updates to one specific instance from `loaded` hook when near filter is not used', it('applies updates to one specific instance from `loaded` hook when near filter is not used',
function(done) { function(done) {
TestModel.observe('loaded', function(ctx, next) { TestModel.observe('loaded', function(ctx, next) {
if (ctx.data.name === 'first') if (ctx.data.name === 'first')
ctx.data.name = 'Paris'; ctx.data.name = 'Paris';
next(); next();
}); });
TestModel.find(function(err, list) { TestModel.find(function(err, list) {
if (err) return done(err);
list.map(get('name')).should.eql(['Paris', 'second']);
done();
});
});
it('should not trigger hooks for geo queries, if notify is false',
function(done) {
monitorHookExecution();
TestModel.find(
{where: {geo: {near: '10,20'}}},
{notify: false},
function(err, list) {
if (err) return done(err); if (err) return done(err);
hookMonitor.names.should.be.empty(); list.map(get('name')).should.eql(['Paris', 'second']);
done(); done();
}); });
}); });
it('should not trigger hooks for geo queries, if notify is false',
function(done) {
monitorHookExecution();
TestModel.find(
{where: {geo: {near: '10,20'}}},
{notify: false},
function(err, list) {
if (err) return done(err);
hookMonitor.names.should.be.empty();
done();
});
});
it('should apply updates from `access` hook', function(done) { it('should apply updates from `access` hook', function(done) {
TestModel.observe('access', function(ctx, next) { TestModel.observe('access', function(ctx, next) {
@ -805,12 +805,12 @@ module.exports = function(dataSource, should, connectorCapabilities) {
record.id.should.eql(existingInstance.id); record.id.should.eql(existingInstance.id);
// `findOrCreate` creates a new instance of the object everytime. // `findOrCreate` creates a new instance of the object everytime.
// So, `data.id` as well as `currentInstance.id` always matches // So, `data.id` as well as `currentInstance.id` always matches
// the newly generated UID. // the newly generated UID.
// Hence, the test below asserts both `data.id` and // Hence, the test below asserts both `data.id` and
// `currentInstance.id` to match getLastGeneratedUid(). // `currentInstance.id` to match getLastGeneratedUid().
// On same lines, it also asserts `isNewInstance` to be true. // On same lines, it also asserts `isNewInstance` to be true.
ctxRecorder.records.should.eql(aCtxForModel(TestModel, { ctxRecorder.records.should.eql(aCtxForModel(TestModel, {
data: { data: {
id: getLastGeneratedUid(), id: getLastGeneratedUid(),
@ -952,9 +952,9 @@ module.exports = function(dataSource, should, connectorCapabilities) {
record.id.should.eql(existingInstance.id); record.id.should.eql(existingInstance.id);
// After the call to `connector.findOrCreate`, since the record // After the call to `connector.findOrCreate`, since the record
// already exists, `data.id` matches `existingInstance.id` // already exists, `data.id` matches `existingInstance.id`
// as against the behaviour noted for `persist` hook // as against the behaviour noted for `persist` hook
ctxRecorder.records.should.eql(aCtxForModel(TestModel, { ctxRecorder.records.should.eql(aCtxForModel(TestModel, {
data: { data: {
id: existingInstance.id, id: existingInstance.id,
@ -2258,7 +2258,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
if (!dataSource.connector.replaceById) { if (!dataSource.connector.replaceById) {
describe.skip('replaceById - not implemented', function() {}); describe.skip('replaceOrCreate - not implemented', function() {});
} else { } else {
describe('PersistedModel.replaceOrCreate', function() { describe('PersistedModel.replaceOrCreate', function() {
it('triggers hooks in the correct order on create', function(done) { it('triggers hooks in the correct order on create', function(done) {
@ -2400,19 +2400,19 @@ module.exports = function(dataSource, should, connectorCapabilities) {
it('triggers `before save` hookon create', function(done) { it('triggers `before save` hookon create', function(done) {
TestModel.observe('before save', ctxRecorder.recordAndNext()); TestModel.observe('before save', ctxRecorder.recordAndNext());
TestModel.replaceOrCreate({id: existingInstance.id, name: 'new name'}, TestModel.replaceOrCreate({id: existingInstance.id, name: 'new name'},
function(err, instance) { function(err, instance) {
if (err) if (err)
return done(err); return done(err);
var expectedContext = aCtxForModel(TestModel, { var expectedContext = aCtxForModel(TestModel, {
instance: instance, instance: instance,
});
if (!dataSource.connector.replaceOrCreate) {
expectedContext.isNewInstance = false;
}
done();
}); });
if (!dataSource.connector.replaceOrCreate) {
expectedContext.isNewInstance = false;
}
done();
});
}); });
it('triggers `before save` hook on replace', function(done) { it('triggers `before save` hook on replace', function(done) {
@ -2573,7 +2573,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
expected.isNewInstance = expected.isNewInstance =
isNewInstanceFlag ? isNewInstanceFlag ?
true : undefined; true : undefined;
ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected)); ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected));
done(); done();
@ -2597,7 +2597,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
expected.isNewInstance = expected.isNewInstance =
isNewInstanceFlag ? isNewInstanceFlag ?
false : undefined; false : undefined;
ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected)); ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected));
done(); done();
@ -2632,7 +2632,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
expected.isNewInstance = expected.isNewInstance =
isNewInstanceFlag ? isNewInstanceFlag ?
false : undefined; false : undefined;
ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected)); ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected));
done(); done();
@ -2656,7 +2656,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}; };
expected.isNewInstance = expected.isNewInstance =
isNewInstanceFlag ? isNewInstanceFlag ?
true : undefined; true : undefined;
ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected)); ctxRecorder.records.should.eql(aCtxForModel(TestModel, expected));
done(); done();
@ -3162,14 +3162,14 @@ module.exports = function(dataSource, should, connectorCapabilities) {
TestModel.observe('access', ctxRecorder.recordAndNext()); TestModel.observe('access', ctxRecorder.recordAndNext());
TestModel.upsertWithWhere({id: existingInstance.id}, TestModel.upsertWithWhere({id: existingInstance.id},
{name: 'new name', extra: 'new extra'}, {name: 'new name', extra: 'new extra'},
function(err, instance) { function(err, instance) {
if (err) return done(err); if (err) return done(err);
ctxRecorder.records.should.eql(aCtxForModel(TestModel, {query: { ctxRecorder.records.should.eql(aCtxForModel(TestModel, {query: {
where: {id: existingInstance.id}, where: {id: existingInstance.id},
}})); }}));
done(); done();
}); });
}); });
it('triggers hooks only once', function(done) { it('triggers hooks only once', function(done) {
@ -3236,27 +3236,27 @@ module.exports = function(dataSource, should, connectorCapabilities) {
TestModel.observe('before save', ctxRecorder.recordAndNext()); TestModel.observe('before save', ctxRecorder.recordAndNext());
TestModel.upsertWithWhere({id: existingInstance.id}, TestModel.upsertWithWhere({id: existingInstance.id},
{id: existingInstance.id, name: 'updated name'}, {id: existingInstance.id, name: 'updated name'},
function(err, instance) { function(err, instance) {
if (err) return done(err); if (err) return done(err);
var expectedContext = aCtxForModel(TestModel, { var expectedContext = aCtxForModel(TestModel, {
where: {id: existingInstance.id}, where: {id: existingInstance.id},
data: { data: {
id: existingInstance.id, id: existingInstance.id,
name: 'updated name', name: 'updated name',
}, },
}); });
if (!dataSource.connector.upsertWithWhere) { if (!dataSource.connector.upsertWithWhere) {
// the difference between `existingInstance` and the following // the difference between `existingInstance` and the following
// plain-data object is `currentInstance` the missing fields are // plain-data object is `currentInstance` the missing fields are
// null in `currentInstance`, wehere as in `existingInstance` they // null in `currentInstance`, wehere as in `existingInstance` they
// are undefined; please see other tests for example see: // are undefined; please see other tests for example see:
// test for "PersistedModel.create triggers `persist` hook" // test for "PersistedModel.create triggers `persist` hook"
expectedContext.currentInstance = {id: existingInstance.id, name: 'first', extra: null}; expectedContext.currentInstance = {id: existingInstance.id, name: 'first', extra: null};
} }
ctxRecorder.records.should.eql(expectedContext); ctxRecorder.records.should.eql(expectedContext);
done(); done();
}); });
}); });
it('triggers `before save` hook on create', function(done) { it('triggers `before save` hook on create', function(done) {
@ -3287,12 +3287,12 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
TestModel.upsertWithWhere({id: existingInstance.id}, TestModel.upsertWithWhere({id: existingInstance.id},
{name: 'updated name'}, {name: 'updated name'},
function(err, instance) { function(err, instance) {
if (err) return done(err); if (err) return done(err);
instance.name.should.equal('hooked'); instance.name.should.equal('hooked');
done(); done();
}); });
}); });
it('applies updates from `before save` hook on create', function(done) { it('applies updates from `before save` hook on create', function(done) {
@ -3429,11 +3429,11 @@ module.exports = function(dataSource, should, connectorCapabilities) {
it('emits error when `loaded` hook fails', function(done) { it('emits error when `loaded` hook fails', function(done) {
TestModel.observe('loaded', nextWithError(expectedError)); TestModel.observe('loaded', nextWithError(expectedError));
TestModel.upsertWithWhere({id: 'new-id'}, TestModel.upsertWithWhere({id: 'new-id'},
{id: 'new-id', name: 'a name'}, {id: 'new-id', name: 'a name'},
function(err, instance) { function(err, instance) {
[err].should.eql([expectedError]); [err].should.eql([expectedError]);
done(); done();
}); });
}); });
it('triggers `after save` hook on update', function(done) { it('triggers `after save` hook on update', function(done) {

File diff suppressed because it is too large Load Diff

View File

@ -127,7 +127,7 @@ describe('util.parseSettings', function() {
should.equal(settings.url, 'mysql://127.0.0.1:3306/mydb?x[a]=1&x[b]=2&engine=InnoDB'); should.equal(settings.url, 'mysql://127.0.0.1:3306/mydb?x[a]=1&x[b]=2&engine=InnoDB');
}); });
it('Parse a url without auth into a settings object', function() { it('Parse a Memory url without auth into a settings object', function() {
var url = 'memory://?x=1'; var url = 'memory://?x=1';
var settings = utils.parseSettings(url); var settings = utils.parseSettings(url);
should.equal(settings.hostname, ''); should.equal(settings.hostname, '');
@ -145,7 +145,7 @@ describe('util.deepMerge', function() {
var extras = {base: 'User', var extras = {base: 'User',
relations: {accessTokens: {model: 'accessToken', type: 'hasMany', relations: {accessTokens: {model: 'accessToken', type: 'hasMany',
foreignKey: 'userId'}, foreignKey: 'userId'},
account: {model: 'account', type: 'belongsTo'}}, account: {model: 'account', type: 'belongsTo'}},
acls: [ acls: [
{accessType: '*', {accessType: '*',
permission: 'DENY', permission: 'DENY',
@ -206,7 +206,7 @@ describe('util.deepMerge', function() {
base: 'User', base: 'User',
relations: {accessTokens: {model: 'accessToken', type: 'hasMany', relations: {accessTokens: {model: 'accessToken', type: 'hasMany',
foreignKey: 'userId'}, foreignKey: 'userId'},
account: {model: 'account', type: 'belongsTo'}}}; account: {model: 'account', type: 'belongsTo'}}};
should.deepEqual(merged, expected, 'Merged objects should match the expectation'); should.deepEqual(merged, expected, 'Merged objects should match the expectation');
}); });
@ -495,19 +495,19 @@ describe('util.toRegExp', function() {
context('with a regex string', function() { context('with a regex string', function() {
it('should return a RegExp object when no regex flags are provided', it('should return a RegExp object when no regex flags are provided',
function() { function() {
utils.toRegExp('^regex$').should.be.an.instanceOf(RegExp); utils.toRegExp('^regex$').should.be.an.instanceOf(RegExp);
}); });
it('should throw an error when invalid regex flags are provided', it('should throw an error when invalid regex flags are provided',
function() { function() {
utils.toRegExp('^regex$/abc').should.be.an.Error; utils.toRegExp('^regex$/abc').should.be.an.Error;
}); });
it('should return a RegExp object when valid flags are provided', it('should return a RegExp object when valid flags are provided',
function() { function() {
utils.toRegExp('regex/igm').should.be.an.instanceOf(RegExp); utils.toRegExp('regex/igm').should.be.an.instanceOf(RegExp);
}); });
}); });
context('with a regex literal', function() { context('with a regex literal', function() {