2013-04-06 10:57:12 +00:00
|
|
|
// This test written in mocha+should.js
|
|
|
|
var should = require('./init.js');
|
|
|
|
|
|
|
|
var db, Person;
|
2013-11-25 16:20:05 +00:00
|
|
|
var ValidationError = require('..').ValidationError;
|
2013-03-26 19:33:11 +00:00
|
|
|
|
2015-02-20 10:18:47 +00:00
|
|
|
var UUID_REGEXP = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
describe('manipulation', function () {
|
|
|
|
|
|
|
|
before(function (done) {
|
|
|
|
db = getSchema();
|
|
|
|
|
|
|
|
Person = db.define('Person', {
|
|
|
|
name: String,
|
|
|
|
gender: String,
|
|
|
|
married: Boolean,
|
|
|
|
age: {type: Number, index: true},
|
|
|
|
dob: Date,
|
2015-02-20 17:33:54 +00:00
|
|
|
createdAt: {type: Date, default: Date}
|
2014-09-05 14:35:01 +00:00
|
|
|
}, { forceId: true });
|
2013-03-26 19:33:11 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
db.automigrate(done);
|
2013-03-26 19:33:11 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
|
2015-01-30 10:01:48 +00:00
|
|
|
// A simplified implementation of LoopBack's User model
|
|
|
|
// to reproduce problems related to properties with dynamic setters
|
|
|
|
// For the purpose of the tests, we use a counter instead of a hash fn.
|
2015-02-21 00:10:25 +00:00
|
|
|
var StubUser;
|
2015-01-30 10:01:48 +00:00
|
|
|
before(function setupStubUserModel(done) {
|
|
|
|
StubUser = db.createModel('StubUser', { password: String }, { forceId: true });
|
|
|
|
StubUser.setter.password = function(plain) {
|
2015-02-21 00:10:25 +00:00
|
|
|
this.$password = plain + '-' + plain.toUpperCase();
|
2015-01-30 10:01:48 +00:00
|
|
|
};
|
|
|
|
db.automigrate('StubUser', done);
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(function resetStubPasswordCounter() {
|
|
|
|
stubPasswordCounter = 0;
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
describe('create', function () {
|
2013-03-26 19:33:11 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
before(function (done) {
|
|
|
|
Person.destroyAll(done);
|
|
|
|
});
|
2013-03-30 17:06:09 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should create instance', function (done) {
|
|
|
|
Person.create({name: 'Anatoliy'}, function (err, p) {
|
|
|
|
p.name.should.equal('Anatoliy');
|
|
|
|
should.not.exist(err);
|
|
|
|
should.exist(p);
|
|
|
|
Person.findById(p.id, function (err, person) {
|
2015-02-04 18:20:56 +00:00
|
|
|
person.id.should.eql(p.id);
|
2014-01-24 17:09:53 +00:00
|
|
|
person.name.should.equal('Anatoliy');
|
|
|
|
done();
|
2013-03-26 19:33:11 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
|
|
|
});
|
2015-01-30 10:01:48 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should create instance (promise variant)', function (done) {
|
|
|
|
Person.create({name: 'Anatoliy'})
|
|
|
|
.then (function (p) {
|
|
|
|
p.name.should.equal('Anatoliy');
|
|
|
|
should.exist(p);
|
|
|
|
return Person.findById(p.id)
|
|
|
|
.then (function (person) {
|
|
|
|
person.id.should.eql(p.id);
|
|
|
|
person.name.should.equal('Anatoliy');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-09-05 15:09:23 +00:00
|
|
|
it('should instantiate an object', function (done) {
|
|
|
|
var p = new Person({name: 'Anatoliy'});
|
|
|
|
p.name.should.equal('Anatoliy');
|
|
|
|
p.isNewRecord().should.be.true;
|
|
|
|
p.save(function(err, inst) {
|
|
|
|
should.not.exist(err);
|
|
|
|
inst.isNewRecord().should.be.false;
|
|
|
|
inst.should.equal(p);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should instantiate an object (promise variant)', function (done) {
|
|
|
|
var p = new Person({name: 'Anatoliy'});
|
|
|
|
p.name.should.equal('Anatoliy');
|
|
|
|
p.isNewRecord().should.be.true;
|
|
|
|
p.save()
|
|
|
|
.then (function(inst) {
|
|
|
|
inst.isNewRecord().should.be.false;
|
|
|
|
inst.should.equal(p);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should return instance of object', function (done) {
|
|
|
|
var person = Person.create(function (err, p) {
|
|
|
|
p.id.should.eql(person.id);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
should.exist(person);
|
|
|
|
person.should.be.an.instanceOf(Person);
|
|
|
|
should.not.exist(person.id);
|
|
|
|
});
|
2015-01-30 10:01:48 +00:00
|
|
|
|
2014-09-05 15:09:23 +00:00
|
|
|
it('should not allow user-defined value for the id of object - create', function (done) {
|
|
|
|
Person.create({id: 123456}, function (err, p) {
|
2014-09-05 14:35:01 +00:00
|
|
|
err.should.be.instanceof(ValidationError);
|
|
|
|
err.statusCode.should.equal(422);
|
2015-01-12 13:52:54 +00:00
|
|
|
err.details.messages.id.should.eql(['can\'t be set']);
|
2014-09-05 14:35:01 +00:00
|
|
|
p.should.be.instanceof(Person);
|
|
|
|
p.id.should.equal(123456);
|
2014-09-05 15:09:23 +00:00
|
|
|
p.isNewRecord().should.be.true;
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2015-01-30 10:01:48 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should not allow user-defined value for the id of object - create (promise variant)', function (done) {
|
|
|
|
Person.create({id: 123456})
|
|
|
|
.then (function (p) {
|
|
|
|
done(new Error('Person.create should have failed.'));
|
|
|
|
}, function (err) {
|
|
|
|
err.should.be.instanceof(ValidationError);
|
|
|
|
err.statusCode.should.equal(422);
|
|
|
|
err.details.messages.id.should.eql(['can\'t be set']);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-09-05 15:09:23 +00:00
|
|
|
it('should not allow user-defined value for the id of object - save', function (done) {
|
|
|
|
var p = new Person({id: 123456});
|
|
|
|
p.isNewRecord().should.be.true;
|
|
|
|
p.save(function(err, inst) {
|
|
|
|
err.should.be.instanceof(ValidationError);
|
|
|
|
err.statusCode.should.equal(422);
|
2015-01-12 13:52:54 +00:00
|
|
|
err.details.messages.id.should.eql(['can\'t be set']);
|
2014-09-05 15:09:23 +00:00
|
|
|
inst.id.should.equal(123456);
|
|
|
|
inst.isNewRecord().should.be.true;
|
2014-09-05 14:35:01 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should not allow user-defined value for the id of object - save (promise variant)', function (done) {
|
|
|
|
var p = new Person({id: 123456});
|
|
|
|
p.isNewRecord().should.be.true;
|
|
|
|
p.save()
|
|
|
|
.then (function(inst) {
|
|
|
|
done(new Error('save should have failed.'));
|
|
|
|
}, function (err) {
|
|
|
|
err.should.be.instanceof(ValidationError);
|
|
|
|
err.statusCode.should.equal(422);
|
|
|
|
err.details.messages.id.should.eql(['can\'t be set']);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should work when called without callback', function (done) {
|
|
|
|
Person.afterCreate = function (next) {
|
|
|
|
this.should.be.an.instanceOf(Person);
|
|
|
|
this.name.should.equal('Nickolay');
|
|
|
|
should.exist(this.id);
|
|
|
|
Person.afterCreate = null;
|
|
|
|
next();
|
|
|
|
setTimeout(done, 10);
|
|
|
|
};
|
|
|
|
Person.create({name: 'Nickolay'});
|
|
|
|
});
|
2013-03-31 09:40:37 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should create instance with blank data', function (done) {
|
|
|
|
Person.create(function (err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
should.exist(p);
|
|
|
|
should.not.exists(p.name);
|
|
|
|
Person.findById(p.id, function (err, person) {
|
2015-02-04 18:20:56 +00:00
|
|
|
person.id.should.eql(p.id);
|
2014-01-24 17:09:53 +00:00
|
|
|
should.not.exists(person.name);
|
|
|
|
done();
|
2013-03-31 09:40:37 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
});
|
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should create instance with blank data (promise variant)', function (done) {
|
|
|
|
Person.create()
|
|
|
|
.then (function (p) {
|
|
|
|
should.exist(p);
|
|
|
|
should.not.exists(p.name);
|
|
|
|
return Person.findById(p.id)
|
|
|
|
.then (function (person) {
|
|
|
|
person.id.should.eql(p.id);
|
|
|
|
should.not.exists(person.name);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
}).catch(done);
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should work when called with no data and callback', function (done) {
|
|
|
|
Person.afterCreate = function (next) {
|
|
|
|
this.should.be.an.instanceOf(Person);
|
|
|
|
should.not.exist(this.name);
|
|
|
|
should.exist(this.id);
|
|
|
|
Person.afterCreate = null;
|
|
|
|
next();
|
|
|
|
setTimeout(done, 30);
|
|
|
|
};
|
|
|
|
Person.create();
|
|
|
|
});
|
2013-03-28 11:27:27 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should create batch of objects', function (done) {
|
|
|
|
var batch = [
|
|
|
|
{name: 'Shaltay'},
|
|
|
|
{name: 'Boltay'},
|
|
|
|
{}
|
|
|
|
];
|
|
|
|
Person.create(batch,function (e, ps) {
|
|
|
|
should.not.exist(e);
|
|
|
|
should.exist(ps);
|
|
|
|
ps.should.be.instanceOf(Array);
|
|
|
|
ps.should.have.lengthOf(batch.length);
|
|
|
|
|
|
|
|
Person.validatesPresenceOf('name');
|
|
|
|
Person.create(batch,function (errors, persons) {
|
2014-08-26 15:51:01 +00:00
|
|
|
delete Person.validations;
|
2014-01-24 17:09:53 +00:00
|
|
|
should.exist(errors);
|
|
|
|
errors.should.have.lengthOf(batch.length);
|
|
|
|
should.not.exist(errors[0]);
|
|
|
|
should.not.exist(errors[1]);
|
|
|
|
should.exist(errors[2]);
|
|
|
|
|
|
|
|
should.exist(persons);
|
|
|
|
persons.should.have.lengthOf(batch.length);
|
|
|
|
persons[0].errors.should.be.false;
|
|
|
|
done();
|
|
|
|
}).should.be.instanceOf(Array);
|
|
|
|
}).should.have.lengthOf(3);
|
|
|
|
});
|
2015-01-29 19:52:39 +00:00
|
|
|
|
|
|
|
it('should create batch of objects with beforeCreate', function(done) {
|
|
|
|
Person.beforeCreate = function(next, data) {
|
|
|
|
if (data && data.name === 'A') {
|
|
|
|
return next(null, {id: 'a', name: 'A'});
|
|
|
|
} else {
|
|
|
|
return next();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
var batch = [
|
|
|
|
{name: 'A'},
|
|
|
|
{name: 'B'},
|
|
|
|
undefined
|
|
|
|
];
|
|
|
|
Person.create(batch, function(e, ps) {
|
|
|
|
should.not.exist(e);
|
|
|
|
should.exist(ps);
|
|
|
|
ps.should.be.instanceOf(Array);
|
|
|
|
ps.should.have.lengthOf(batch.length);
|
|
|
|
ps[0].should.be.eql({id: 'a', name: 'A'});
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2015-02-04 08:08:28 +00:00
|
|
|
|
|
|
|
it('should preserve properties with "undefined" value', function(done) {
|
|
|
|
Person.create(
|
|
|
|
{ name: 'a-name', gender: undefined },
|
|
|
|
function(err, created) {
|
|
|
|
if (err) return done(err);
|
|
|
|
created.toObject().should.have.properties({
|
|
|
|
id: created.id,
|
|
|
|
name: 'a-name',
|
|
|
|
gender: undefined
|
|
|
|
});
|
|
|
|
|
|
|
|
Person.findById(created.id, function(err, found) {
|
|
|
|
if (err) return done(err);
|
2015-02-20 17:55:09 +00:00
|
|
|
var result = found.toObject();
|
|
|
|
result.should.have.properties({
|
2015-02-04 08:08:28 +00:00
|
|
|
id: created.id,
|
2015-02-20 17:55:09 +00:00
|
|
|
name: 'a-name'
|
2015-02-04 08:08:28 +00:00
|
|
|
});
|
2015-02-20 17:55:09 +00:00
|
|
|
// The gender can be null from a RDB
|
|
|
|
should.equal(result.gender, null);
|
2015-02-04 08:08:28 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
|
2015-03-16 10:26:57 +00:00
|
|
|
it('should refuse to create object with duplicate id', function(done) {
|
|
|
|
// NOTE(bajtos) We cannot reuse Person model here,
|
|
|
|
// `settings.forceId` aborts the CREATE request at the validation step.
|
|
|
|
var Product = db.define('Product', { name: String });
|
|
|
|
db.automigrate(function(err) {
|
|
|
|
if (err) return done(err);
|
|
|
|
|
|
|
|
Product.create({ name: 'a-name' }, function(err, p) {
|
|
|
|
if (err) return done(err);
|
|
|
|
Product.create({ id: p.id, name: 'duplicate' }, function(err) {
|
|
|
|
if (!err) {
|
|
|
|
return done(new Error('Create should have rejected duplicate id.'));
|
|
|
|
}
|
|
|
|
err.message.should.match(/duplicate/i);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
2013-03-28 11:27:27 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
describe('save', function () {
|
|
|
|
|
|
|
|
it('should save new object', function (done) {
|
|
|
|
var p = new Person;
|
|
|
|
p.save(function (err) {
|
|
|
|
should.not.exist(err);
|
|
|
|
should.exist(p.id);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2013-03-28 11:27:27 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should save new object (promise variant)', function (done) {
|
|
|
|
var p = new Person;
|
|
|
|
p.save()
|
|
|
|
.then(function () {
|
|
|
|
should.exist(p.id);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should save existing object', function (done) {
|
|
|
|
Person.findOne(function (err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
p.name = 'Hans';
|
|
|
|
p.save(function (err) {
|
|
|
|
should.not.exist(err);
|
|
|
|
Person.findOne(function (err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
p.name.should.equal('Hans');
|
|
|
|
done();
|
|
|
|
});
|
2013-03-28 11:27:27 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
|
|
|
});
|
2013-03-28 11:27:27 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should save existing object (promise variant)', function (done) {
|
|
|
|
Person.findOne()
|
|
|
|
.then(function (p) {
|
|
|
|
p.name = 'Fritz';
|
|
|
|
return p.save()
|
|
|
|
.then(function () {
|
|
|
|
return Person.findOne()
|
|
|
|
.then(function (p) {
|
|
|
|
p.name.should.equal('Fritz');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should save invalid object (skipping validation)', function (done) {
|
|
|
|
Person.findOne(function (err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
p.isValid = function (done) {
|
|
|
|
process.nextTick(done);
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
p.name = 'Nana';
|
|
|
|
p.save(function (err) {
|
|
|
|
should.exist(err);
|
|
|
|
p.save({validate: false}, function (err) {
|
|
|
|
should.not.exist(err);
|
|
|
|
done();
|
|
|
|
});
|
2013-03-28 11:27:27 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
|
|
|
});
|
2013-03-30 17:07:16 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should save invalid object (skipping validation - promise variant)', function (done) {
|
|
|
|
Person.findOne()
|
|
|
|
.then(function (p) {
|
|
|
|
p.isValid = function (done) {
|
|
|
|
process.nextTick(done);
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
p.name = 'Nana';
|
|
|
|
return p.save()
|
|
|
|
.then(function (d) {
|
|
|
|
done(new Error('save should have failed.'));
|
|
|
|
}, function (err) {
|
|
|
|
should.exist(err);
|
|
|
|
p.save({validate: false})
|
|
|
|
.then(function (d) {
|
|
|
|
should.exist(d);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should save throw error on validation', function () {
|
|
|
|
Person.findOne(function (err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
p.isValid = function (cb) {
|
|
|
|
cb(false);
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
(function () {
|
|
|
|
p.save({
|
|
|
|
'throws': true
|
|
|
|
});
|
|
|
|
}).should.throw(ValidationError);
|
|
|
|
});
|
2013-03-30 17:07:16 +00:00
|
|
|
});
|
|
|
|
|
2015-01-30 10:01:48 +00:00
|
|
|
it('should preserve properties with dynamic setters', function(done) {
|
|
|
|
// This test reproduces a problem discovered by LoopBack unit-test
|
|
|
|
// "User.hasPassword() should match a password after it is changed"
|
|
|
|
StubUser.create({ password: 'foo' }, function(err, created) {
|
|
|
|
if (err) return done(err);
|
|
|
|
created.password = 'bar';
|
|
|
|
created.save(function(err, saved) {
|
|
|
|
if (err) return done(err);
|
2015-02-21 00:10:25 +00:00
|
|
|
saved.password.should.equal('bar-BAR');
|
2015-01-30 10:01:48 +00:00
|
|
|
StubUser.findById(created.id, function(err, found) {
|
|
|
|
if (err) return done(err);
|
2015-02-21 00:10:25 +00:00
|
|
|
found.password.should.equal('bar-BAR');
|
2015-01-30 10:01:48 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
2013-03-30 17:07:16 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
describe('updateAttributes', function () {
|
|
|
|
var person;
|
2013-03-30 17:07:16 +00:00
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
before(function (done) {
|
|
|
|
Person.destroyAll(function () {
|
2015-03-16 16:25:38 +00:00
|
|
|
Person.create({name: 'Mary', age: 15}, function(err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
person = p;
|
|
|
|
done();
|
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should update one attribute', function (done) {
|
|
|
|
person.updateAttribute('name', 'Paul Graham', function (err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
Person.all(function (e, ps) {
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
should.not.exist(e);
|
2014-01-24 17:09:53 +00:00
|
|
|
ps.should.have.lengthOf(1);
|
|
|
|
ps.pop().name.should.equal('Paul Graham');
|
|
|
|
done();
|
2013-03-27 00:51:00 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
|
|
|
});
|
2015-01-30 07:26:11 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should update one attribute (promise variant)', function (done) {
|
|
|
|
person.updateAttribute('name', 'Teddy Graham')
|
|
|
|
.then(function (p) {
|
|
|
|
return Person.all()
|
|
|
|
.then(function (ps) {
|
|
|
|
ps.should.have.lengthOf(1);
|
|
|
|
ps.pop().name.should.equal('Teddy Graham');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
}).catch(done);
|
|
|
|
});
|
|
|
|
|
2015-01-30 07:26:11 +00:00
|
|
|
it('should ignore undefined values on updateAttributes', function(done) {
|
|
|
|
person.updateAttributes({'name': 'John', age: undefined},
|
|
|
|
function(err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
Person.findById(p.id, function(e, p) {
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
should.not.exist(e);
|
2015-01-30 07:26:11 +00:00
|
|
|
p.name.should.equal('John');
|
|
|
|
p.age.should.equal(15);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-03-16 16:25:38 +00:00
|
|
|
it('should allow same id value on updateAttributes', function(done) {
|
|
|
|
person.updateAttributes({id: person.id, name: 'John'},
|
|
|
|
function(err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
Person.findById(p.id, function(e, p) {
|
|
|
|
should.not.exist(e);
|
|
|
|
p.name.should.equal('John');
|
|
|
|
p.age.should.equal(15);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should fail if an id value is to be changed on updateAttributes',
|
|
|
|
function(done) {
|
|
|
|
person.updateAttributes({id: person.id + 1, name: 'John'},
|
|
|
|
function(err, p) {
|
|
|
|
should.exist(err);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-30 07:26:11 +00:00
|
|
|
it('should allows model instance on updateAttributes', function(done) {
|
|
|
|
person.updateAttributes(new Person({'name': 'John', age: undefined}),
|
|
|
|
function(err, p) {
|
|
|
|
should.not.exist(err);
|
|
|
|
Person.findById(p.id, function(e, p) {
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
should.not.exist(e);
|
2015-01-30 07:26:11 +00:00
|
|
|
p.name.should.equal('John');
|
|
|
|
p.age.should.equal(15);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should allows model instance on updateAttributes (promise variant)', function(done) {
|
|
|
|
person.updateAttributes(new Person({'name': 'Jane', age: undefined}))
|
|
|
|
.then(function(p) {
|
|
|
|
return Person.findById(p.id)
|
|
|
|
.then(function(p) {
|
|
|
|
p.name.should.equal('Jane');
|
|
|
|
p.age.should.equal(15);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
|
|
|
|
2015-01-30 10:01:48 +00:00
|
|
|
describe('updateOrCreate', function() {
|
|
|
|
it('should preserve properties with dynamic setters on create', function(done) {
|
2015-02-21 00:10:25 +00:00
|
|
|
StubUser.updateOrCreate({ password: 'foo' }, function(err, created) {
|
2015-01-30 10:01:48 +00:00
|
|
|
if (err) return done(err);
|
2015-02-21 00:10:25 +00:00
|
|
|
created.password.should.equal('foo-FOO');
|
2015-01-30 10:01:48 +00:00
|
|
|
StubUser.findById(created.id, function(err, found) {
|
|
|
|
if (err) return done(err);
|
2015-02-21 00:10:25 +00:00
|
|
|
found.password.should.equal('foo-FOO');
|
2015-01-30 10:01:48 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should preserve properties with dynamic setters on update', function(done) {
|
|
|
|
StubUser.create({ password: 'foo' }, function(err, created) {
|
|
|
|
if (err) return done(err);
|
|
|
|
var data = { id: created.id, password: 'bar' };
|
|
|
|
StubUser.updateOrCreate(data, function(err, updated) {
|
|
|
|
if (err) return done(err);
|
2015-02-21 00:10:25 +00:00
|
|
|
updated.password.should.equal('bar-BAR');
|
2015-01-30 10:01:48 +00:00
|
|
|
StubUser.findById(created.id, function(err, found) {
|
|
|
|
if (err) return done(err);
|
2015-02-21 00:10:25 +00:00
|
|
|
found.password.should.equal('bar-BAR');
|
2015-01-30 10:01:48 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2015-02-04 08:08:28 +00:00
|
|
|
|
|
|
|
it('should preserve properties with "undefined" value', function(done) {
|
|
|
|
Person.create(
|
|
|
|
{ name: 'a-name', gender: undefined },
|
|
|
|
function(err, instance) {
|
|
|
|
if (err) return done(err);
|
|
|
|
instance.toObject().should.have.properties({
|
|
|
|
id: instance.id,
|
|
|
|
name: 'a-name',
|
|
|
|
gender: undefined
|
|
|
|
});
|
|
|
|
|
|
|
|
Person.updateOrCreate(
|
|
|
|
{ id: instance.id, name: 'updated name' },
|
|
|
|
function(err, updated) {
|
|
|
|
if (err) return done(err);
|
2015-02-21 00:10:25 +00:00
|
|
|
var result = updated.toObject();
|
|
|
|
result.should.have.properties({
|
2015-02-04 08:08:28 +00:00
|
|
|
id: instance.id,
|
2015-02-21 00:10:25 +00:00
|
|
|
name: 'updated name'
|
2015-02-04 08:08:28 +00:00
|
|
|
});
|
2015-02-21 00:10:25 +00:00
|
|
|
should.equal(result.gender, null);
|
2015-02-04 08:08:28 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2015-03-16 11:36:54 +00:00
|
|
|
|
|
|
|
it('should allow save() of the created instance', function(done) {
|
|
|
|
Person.updateOrCreate(
|
|
|
|
{ id: 'new-id', name: 'a-name' },
|
|
|
|
function(err, inst) {
|
|
|
|
if (err) return done(err);
|
|
|
|
inst.save(done);
|
|
|
|
});
|
|
|
|
});
|
2015-01-30 10:01:48 +00:00
|
|
|
});
|
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
describe('findOrCreate', function() {
|
|
|
|
it('should create a record with if new', function(done) {
|
|
|
|
Person.findOrCreate({ name: 'Zed', gender: 'male' },
|
|
|
|
function(err, p, created) {
|
|
|
|
if (err) return done(err);
|
|
|
|
should.exist(p);
|
|
|
|
p.should.be.instanceOf(Person);
|
|
|
|
p.name.should.equal('Zed');
|
|
|
|
p.gender.should.equal('male');
|
|
|
|
created.should.equal(true);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should find a record if exists', function(done) {
|
|
|
|
Person.findOrCreate(
|
|
|
|
{where: {name: 'Zed'}},
|
|
|
|
{name: 'Zed', gender: 'male'},
|
|
|
|
function(err, p, created) {
|
|
|
|
if (err) return done(err);
|
|
|
|
should.exist(p);
|
|
|
|
p.should.be.instanceOf(Person);
|
|
|
|
p.name.should.equal('Zed');
|
|
|
|
p.gender.should.equal('male');
|
|
|
|
created.should.equal(false);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should create a record with if new (promise variant)', function(done) {
|
|
|
|
Person.findOrCreate({ name: 'Jed', gender: 'male' })
|
|
|
|
.then(function(res) {
|
|
|
|
should.exist(res);
|
|
|
|
res.should.be.instanceOf(Array);
|
|
|
|
res.should.have.lengthOf(2);
|
|
|
|
var p = res[0];
|
|
|
|
var created = res[1];
|
|
|
|
p.should.be.instanceOf(Person);
|
|
|
|
p.name.should.equal('Jed');
|
|
|
|
p.gender.should.equal('male');
|
|
|
|
created.should.equal(true);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should find a record if exists (promise variant)', function(done) {
|
|
|
|
Person.findOrCreate(
|
|
|
|
{where: {name: 'Jed'}},
|
|
|
|
{name: 'Jed', gender: 'male'})
|
|
|
|
.then(function(res) {
|
|
|
|
res.should.be.instanceOf(Array);
|
|
|
|
res.should.have.lengthOf(2);
|
|
|
|
var p = res[0];
|
|
|
|
var created = res[1];
|
|
|
|
p.should.be.instanceOf(Person);
|
|
|
|
p.name.should.equal('Jed');
|
|
|
|
p.gender.should.equal('male');
|
|
|
|
created.should.equal(false);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
describe('destroy', function () {
|
|
|
|
|
|
|
|
it('should destroy record', function (done) {
|
|
|
|
Person.create(function (err, p) {
|
|
|
|
p.destroy(function (err) {
|
|
|
|
should.not.exist(err);
|
|
|
|
Person.exists(p.id, function (err, ex) {
|
|
|
|
ex.should.not.be.ok;
|
|
|
|
done();
|
|
|
|
});
|
2013-03-27 00:51:00 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
});
|
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should destroy record (promise variant)', function (done) {
|
|
|
|
Person.create()
|
|
|
|
.then(function (p) {
|
|
|
|
return p.destroy()
|
|
|
|
.then(function () {
|
|
|
|
return Person.exists(p.id)
|
|
|
|
.then(function (ex) {
|
|
|
|
ex.should.not.be.ok;
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
it('should destroy all records', function (done) {
|
|
|
|
Person.destroyAll(function (err) {
|
|
|
|
should.not.exist(err);
|
|
|
|
Person.all(function (err, posts) {
|
|
|
|
posts.should.have.lengthOf(0);
|
|
|
|
Person.count(function (err, count) {
|
|
|
|
count.should.eql(0);
|
|
|
|
done();
|
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
});
|
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
|
Add Promises to DAO
When a callback is omitted from a DAO method, return a Promise that
resolves to the value normally passed to the callback of that method.
If a callback is provided, behave normally.
This API will use native ES6 promises if available. If not available,
or to force the use of another Promise library, you must assign the
global.Promise object.
e.g.:
global.Promise = require('bluebird')
Class methods affected:
- create
- updateOrCreate / upsert
- findOrCreate
- exists
- find
- findOne
- findById
- findByIds
- remove / deleteAll / destroyAll
- removeById / deleteById / destroyById
- count
- update / updateAll
Prototype methods affected:
- save
- delete / remove / destroy
- updateAttribute
- updateAttributes
- reload
Exceptions / edge cases:
- create() used to return the data object that was passed in, even if
no callback was provided. Now, if a callback is provided, it will
return the data object, otherwise it will return a Promise.
- If create() is provided an array of data objects for creation, it
will continue to always return the array. This batch creation mode
does not support promises.
- findOrCreate() has a callback of the form: cb(err, instance, created),
with the extra parameter indicating whether the instance was created
or not. When called with its promise variant, the resolver will
receive a single array parameter: [instance, created]
2015-02-18 04:55:03 +00:00
|
|
|
it('should destroy all records (promise variant)', function (done) {
|
|
|
|
Person.create()
|
|
|
|
.then(function() {
|
|
|
|
return Person.destroyAll()
|
|
|
|
.then(function () {
|
|
|
|
return Person.all()
|
|
|
|
.then(function (ps) {
|
|
|
|
ps.should.have.lengthOf(0);
|
|
|
|
return Person.count()
|
|
|
|
.then(function (count) {
|
|
|
|
count.should.eql(0);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
// TODO: implement destroy with filtered set
|
|
|
|
it('should destroy filtered set of records');
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('initialize', function () {
|
|
|
|
it('should initialize object properly', function () {
|
|
|
|
var hw = 'Hello word',
|
|
|
|
now = Date.now(),
|
|
|
|
person = new Person({name: hw});
|
|
|
|
|
|
|
|
person.name.should.equal(hw);
|
|
|
|
person.name = 'Goodbye, Lenin';
|
|
|
|
(person.createdAt >= now).should.be.true;
|
|
|
|
person.isNewRecord().should.be.true;
|
2013-03-26 19:33:11 +00:00
|
|
|
});
|
2014-01-24 17:09:53 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
describe('Date $now function', function() {
|
|
|
|
var CustomModel;
|
|
|
|
|
|
|
|
before(function(done) {
|
|
|
|
CustomModel = db.define('CustomModel1', {
|
2015-02-13 13:00:36 +00:00
|
|
|
createdAt: { type: Date, default: '$now' }
|
|
|
|
});
|
2015-02-21 05:44:49 +00:00
|
|
|
db.automigrate('CustomModel1', done);
|
|
|
|
});
|
2015-02-13 13:00:36 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
it('should report current date as default value for date property',
|
|
|
|
function(done) {
|
|
|
|
var now = Date.now();
|
2015-02-13 13:00:36 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
var myCustomModel = CustomModel.create(function(err, m) {
|
|
|
|
should.not.exists(err);
|
|
|
|
m.createdAt.should.be.instanceOf(Date);
|
|
|
|
(m.createdAt >= now).should.be.true;
|
|
|
|
});
|
2015-02-13 13:00:36 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
done();
|
|
|
|
});
|
2015-02-13 13:00:36 +00:00
|
|
|
});
|
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
describe('Date $now function', function() {
|
|
|
|
var CustomModel;
|
|
|
|
|
|
|
|
before(function(done) {
|
|
|
|
CustomModel = db.define('CustomModel2', {
|
2015-02-13 13:00:36 +00:00
|
|
|
now: { type: String, default: '$now' }
|
|
|
|
});
|
2015-02-21 05:44:49 +00:00
|
|
|
db.automigrate('CustomModel2', done);
|
|
|
|
});
|
2015-02-13 13:00:36 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
it('should report \'$now\' as default value for string property',
|
|
|
|
function(done) {
|
|
|
|
var myCustomModel = CustomModel.create(function(err, m) {
|
|
|
|
should.not.exists(err);
|
|
|
|
m.now.should.be.instanceOf(String);
|
|
|
|
m.now.should.equal('$now');
|
|
|
|
});
|
2015-02-13 13:00:36 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
done();
|
|
|
|
});
|
2015-02-13 13:00:36 +00:00
|
|
|
});
|
2015-02-20 10:18:47 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
describe('now defaultFn', function() {
|
|
|
|
var CustomModel;
|
2015-02-20 10:18:47 +00:00
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
before(function(done) {
|
|
|
|
CustomModel = db.define('CustomModel3', {
|
|
|
|
now: { type: Date, defaultFn: 'now' }
|
|
|
|
});
|
|
|
|
db.automigrate('CustomModel3', done);
|
2015-02-20 10:18:47 +00:00
|
|
|
});
|
2015-02-21 05:44:49 +00:00
|
|
|
|
|
|
|
it('should generate current time when "defaultFn" is "now"',
|
|
|
|
function(done) {
|
|
|
|
var now = Date.now();
|
|
|
|
var inst = CustomModel.create(function(err, m) {
|
|
|
|
should.not.exists(err);
|
|
|
|
m.now.should.be.instanceOf(Date);
|
|
|
|
m.now.should.be.within(now, now + 200);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2015-02-20 10:18:47 +00:00
|
|
|
});
|
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
describe('guid defaultFn', function() {
|
|
|
|
var CustomModel;
|
|
|
|
|
|
|
|
before(function(done) {
|
|
|
|
CustomModel = db.define('CustomModel4', {
|
|
|
|
guid: { type: String, defaultFn: 'guid' }
|
|
|
|
});
|
|
|
|
db.automigrate('CustomModel4', done);
|
2015-02-20 10:18:47 +00:00
|
|
|
});
|
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
it('should generate a new id when "defaultFn" is "guid"', function(done) {
|
|
|
|
var inst = CustomModel.create(function(err, m) {
|
|
|
|
should.not.exists(err);
|
|
|
|
m.guid.should.match(UUID_REGEXP);
|
|
|
|
done();
|
|
|
|
});
|
2015-02-20 10:18:47 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
describe('uuid defaultFn', function() {
|
|
|
|
var CustomModel;
|
|
|
|
|
|
|
|
before(function(done) {
|
|
|
|
CustomModel = db.define('CustomModel5', {
|
|
|
|
guid: { type: String, defaultFn: 'uuid' }
|
|
|
|
});
|
|
|
|
db.automigrate('CustomModel5', done);
|
2015-02-20 10:18:47 +00:00
|
|
|
});
|
|
|
|
|
2015-02-21 05:44:49 +00:00
|
|
|
it('should generate a new id when "defaultfn" is "uuid"', function(done) {
|
|
|
|
var inst = CustomModel.create(function(err, m) {
|
|
|
|
should.not.exists(err);
|
|
|
|
m.guid.should.match(UUID_REGEXP);
|
|
|
|
done();
|
|
|
|
});
|
2015-02-20 10:18:47 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-01-24 17:09:53 +00:00
|
|
|
// it('should work when constructor called as function', function() {
|
|
|
|
// var p = Person({name: 'John Resig'});
|
|
|
|
// p.should.be.an.instanceOf(Person);
|
|
|
|
// p.name.should.equal('John Resig');
|
|
|
|
// });
|
|
|
|
});
|
2015-02-08 18:54:42 +00:00
|
|
|
|
|
|
|
describe('property value coercion', function () {
|
|
|
|
it('should coerce boolean types properly', function() {
|
|
|
|
var p1 = new Person({name: 'John', married: 'false'});
|
|
|
|
p1.married.should.equal(false);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: 'true'});
|
|
|
|
p1.married.should.equal(true);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: '1'});
|
|
|
|
p1.married.should.equal(true);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: '0'});
|
|
|
|
p1.married.should.equal(false);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: true});
|
|
|
|
p1.married.should.equal(true);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: false});
|
|
|
|
p1.married.should.equal(false);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: 'null'});
|
|
|
|
p1.married.should.equal(true);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: ''});
|
|
|
|
p1.married.should.equal(false);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: 'X'});
|
|
|
|
p1.married.should.equal(true);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: 0});
|
|
|
|
p1.married.should.equal(false);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: 1});
|
|
|
|
p1.married.should.equal(true);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: null});
|
|
|
|
p1.should.have.property('married', null);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', married: undefined});
|
|
|
|
p1.should.have.property('married', undefined);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should coerce boolean types properly', function() {
|
|
|
|
var p1 = new Person({name: 'John', dob: '2/1/2015'});
|
|
|
|
p1.dob.should.eql(new Date('2/1/2015'));
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', dob: '2/1/2015'});
|
|
|
|
p1.dob.should.eql(new Date('2/1/2015'));
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', dob: '12'});
|
|
|
|
p1.dob.should.eql(new Date('12'));
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', dob: 12});
|
|
|
|
p1.dob.should.eql(new Date(12));
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', dob: null});
|
|
|
|
p1.should.have.property('dob', null);
|
|
|
|
|
|
|
|
p1 = new Person({name: 'John', dob: undefined});
|
|
|
|
p1.should.have.property('dob', undefined);
|
|
|
|
|
|
|
|
try {
|
|
|
|
p1 = new Person({name: 'John', dob: 'X'});
|
|
|
|
throw new Error('new Person() should have thrown');
|
|
|
|
} catch (e) {
|
|
|
|
e.should.be.eql(new Error('Invalid date: X'));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
2013-03-26 19:33:11 +00:00
|
|
|
});
|