2013-04-06 10:57:12 +00:00
|
|
|
// This test written in mocha+should.js
|
|
|
|
var should = require('./init.js');
|
|
|
|
|
2013-03-24 21:25:10 +00:00
|
|
|
var j = require('../'),
|
|
|
|
Schema = j.Schema,
|
|
|
|
AbstractClass = j.AbstractClass,
|
|
|
|
Hookable = j.Hookable,
|
|
|
|
|
|
|
|
db, User;
|
|
|
|
|
|
|
|
describe('hooks', function() {
|
|
|
|
|
2013-03-27 00:50:34 +00:00
|
|
|
before(function(done) {
|
2013-03-26 00:41:00 +00:00
|
|
|
db = getSchema();
|
2013-03-24 21:25:10 +00:00
|
|
|
|
|
|
|
User = db.define('User', {
|
2013-03-27 00:50:34 +00:00
|
|
|
email: {type: String, index: true},
|
2013-03-24 21:25:10 +00:00
|
|
|
name: String,
|
|
|
|
password: String,
|
|
|
|
state: String
|
|
|
|
});
|
2013-03-27 00:50:34 +00:00
|
|
|
|
|
|
|
db.automigrate(done);
|
2013-03-24 21:25:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('initialize', function() {
|
|
|
|
|
|
|
|
afterEach(function() {
|
|
|
|
User.afterInitialize = null;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on new', function(done) {
|
|
|
|
User.afterInitialize = function() {
|
|
|
|
done();
|
|
|
|
};
|
|
|
|
new User;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on create', function(done) {
|
|
|
|
var user;
|
|
|
|
User.afterInitialize = function() {
|
|
|
|
if (this.name === 'Nickolay') {
|
|
|
|
this.name += ' Rozental';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
User.create({name: 'Nickolay'}, function(err, u) {
|
2013-03-27 17:53:07 +00:00
|
|
|
u.id.should.be.ok;
|
2013-03-24 21:25:10 +00:00
|
|
|
u.name.should.equal('Nickolay Rozental');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('create', function() {
|
|
|
|
|
|
|
|
afterEach(removeHooks('Create'));
|
|
|
|
|
|
|
|
it('should be triggered on create', function(done) {
|
|
|
|
addHooks('Create', done);
|
|
|
|
User.create();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not be triggered on new', function() {
|
|
|
|
User.beforeCreate = function(next) {
|
|
|
|
should.fail('This should not be called');
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
var u = new User;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on new+save', function(done) {
|
|
|
|
addHooks('Create', done);
|
|
|
|
(new User).save();
|
|
|
|
});
|
|
|
|
|
2013-03-31 00:20:32 +00:00
|
|
|
it('afterCreate should not be triggered on failed create', function(done) {
|
2013-07-23 18:16:43 +00:00
|
|
|
var old = User.dataSource.connector.create;
|
|
|
|
User.dataSource.connector.create = function(modelName, id, cb) {
|
2013-03-31 00:20:32 +00:00
|
|
|
cb(new Error('error'));
|
|
|
|
}
|
|
|
|
|
|
|
|
User.afterCreate = function() {
|
|
|
|
throw new Error('shouldn\'t be called')
|
|
|
|
};
|
|
|
|
User.create(function (err, user) {
|
2013-07-23 18:16:43 +00:00
|
|
|
User.dataSource.connector.create = old;
|
2013-03-31 00:20:32 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2013-03-24 21:25:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('save', function() {
|
|
|
|
afterEach(removeHooks('Save'));
|
|
|
|
|
|
|
|
it('should be triggered on create', function(done) {
|
|
|
|
addHooks('Save', done);
|
|
|
|
User.create();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on new+save', function(done) {
|
|
|
|
addHooks('Save', done);
|
|
|
|
(new User).save();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on updateAttributes', function(done) {
|
|
|
|
User.create(function(err, user) {
|
|
|
|
addHooks('Save', done);
|
|
|
|
user.updateAttributes({name: 'Anatoliy'});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on save', function(done) {
|
|
|
|
User.create(function(err, user) {
|
|
|
|
addHooks('Save', done);
|
|
|
|
user.name = 'Hamburger';
|
|
|
|
user.save();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should save full object', function(done) {
|
|
|
|
User.create(function(err, user) {
|
|
|
|
User.beforeSave = function(next, data) {
|
2013-03-28 11:27:50 +00:00
|
|
|
data.should.have.keys('id', 'name', 'email',
|
2013-03-24 21:25:10 +00:00
|
|
|
'password', 'state')
|
|
|
|
done();
|
|
|
|
};
|
|
|
|
user.save();
|
|
|
|
});
|
|
|
|
});
|
2013-03-26 20:49:02 +00:00
|
|
|
|
|
|
|
it('should save actual modifications to database', function(done) {
|
|
|
|
User.beforeSave = function(next, data) {
|
|
|
|
data.password = 'hash';
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
User.destroyAll(function() {
|
|
|
|
User.create({
|
|
|
|
email: 'james.bond@example.com',
|
2013-04-18 09:05:11 +00:00
|
|
|
password: '53cr3t'
|
2013-03-26 20:49:02 +00:00
|
|
|
}, function() {
|
|
|
|
User.findOne({
|
|
|
|
where: {email: 'james.bond@example.com'}
|
|
|
|
}, function(err, jb) {
|
|
|
|
jb.password.should.equal('hash');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2013-03-27 14:53:46 +00:00
|
|
|
|
|
|
|
it('should save actual modifications on updateAttributes', function(done) {
|
|
|
|
User.beforeSave = function(next, data) {
|
|
|
|
data.password = 'hash';
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
User.destroyAll(function() {
|
|
|
|
User.create({
|
|
|
|
email: 'james.bond@example.com'
|
|
|
|
}, function(err, u) {
|
|
|
|
u.updateAttribute('password', 'new password', function(e, u) {
|
|
|
|
should.not.exist(e);
|
|
|
|
should.exist(u);
|
|
|
|
u.password.should.equal('hash');
|
|
|
|
User.findOne({
|
|
|
|
where: {email: 'james.bond@example.com'}
|
|
|
|
}, function(err, jb) {
|
|
|
|
jb.password.should.equal('hash');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-03-24 21:25:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('update', function() {
|
|
|
|
afterEach(removeHooks('Update'));
|
|
|
|
|
|
|
|
it('should not be triggered on create', function() {
|
|
|
|
User.beforeUpdate = function(next) {
|
|
|
|
should.fail('This should not be called');
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
User.create();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not be triggered on new+save', function() {
|
|
|
|
User.beforeUpdate = function(next) {
|
|
|
|
should.fail('This should not be called');
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
(new User).save();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on updateAttributes', function(done) {
|
|
|
|
User.create(function (err, user) {
|
|
|
|
addHooks('Update', done);
|
|
|
|
user.updateAttributes({name: 'Anatoliy'});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be triggered on save', function(done) {
|
|
|
|
User.create(function (err, user) {
|
|
|
|
addHooks('Update', done);
|
|
|
|
user.name = 'Hamburger';
|
|
|
|
user.save();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should update limited set of fields', function(done) {
|
|
|
|
User.create(function (err, user) {
|
|
|
|
User.beforeUpdate = function(next, data) {
|
|
|
|
data.should.have.keys('name', 'email');
|
|
|
|
done();
|
|
|
|
};
|
|
|
|
user.updateAttributes({name: 1, email: 2});
|
|
|
|
});
|
|
|
|
});
|
2013-03-31 00:20:32 +00:00
|
|
|
|
2013-03-31 10:17:25 +00:00
|
|
|
it('should not trigger after-hook on failed save', function(done) {
|
2013-03-31 00:20:32 +00:00
|
|
|
User.afterUpdate = function() {
|
2013-03-31 10:17:25 +00:00
|
|
|
should.fail('afterUpdate shouldn\'t be called')
|
2013-03-31 00:20:32 +00:00
|
|
|
};
|
|
|
|
User.create(function (err, user) {
|
2013-07-23 18:16:43 +00:00
|
|
|
var save = User.dataSource.connector.save;
|
|
|
|
User.dataSource.connector.save = function(modelName, id, cb) {
|
|
|
|
User.dataSource.connector.save = save;
|
2013-03-31 10:17:25 +00:00
|
|
|
cb(new Error('Error'));
|
2013-03-31 00:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
user.save(function(err) {
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2013-03-24 21:25:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('destroy', function() {
|
2013-03-31 10:17:25 +00:00
|
|
|
|
2013-03-24 21:25:10 +00:00
|
|
|
afterEach(removeHooks('Destroy'));
|
|
|
|
|
2013-03-28 11:27:50 +00:00
|
|
|
it('should be triggered on destroy', function(done) {
|
2013-03-24 21:25:10 +00:00
|
|
|
var hook = 'not called';
|
2013-03-28 11:27:50 +00:00
|
|
|
User.beforeDestroy = function(next) {
|
2013-03-24 21:25:10 +00:00
|
|
|
hook = 'called';
|
2013-03-28 11:27:50 +00:00
|
|
|
next();
|
2013-03-24 21:25:10 +00:00
|
|
|
};
|
2013-03-31 10:17:25 +00:00
|
|
|
User.afterDestroy = function(next) {
|
2013-03-24 21:25:10 +00:00
|
|
|
hook.should.eql('called');
|
2013-03-31 10:17:25 +00:00
|
|
|
next();
|
2013-03-24 21:25:10 +00:00
|
|
|
};
|
|
|
|
User.create(function (err, user) {
|
2013-03-31 10:17:25 +00:00
|
|
|
user.destroy(done);
|
2013-03-24 21:25:10 +00:00
|
|
|
});
|
|
|
|
});
|
2013-03-31 00:18:47 +00:00
|
|
|
|
2013-03-31 10:17:25 +00:00
|
|
|
it('should not trigger after-hook on failed destroy', function(done) {
|
2013-07-23 18:16:43 +00:00
|
|
|
var destroy = User.dataSource.connector.destroy;
|
|
|
|
User.dataSource.connector.destroy = function(modelName, id, cb) {
|
2013-03-31 00:18:47 +00:00
|
|
|
cb(new Error('error'));
|
|
|
|
}
|
|
|
|
User.afterDestroy = function() {
|
2013-03-31 10:17:25 +00:00
|
|
|
should.fail('afterDestroy shouldn\'t be called')
|
2013-03-31 00:18:47 +00:00
|
|
|
};
|
|
|
|
User.create(function (err, user) {
|
|
|
|
user.destroy(function(err) {
|
2013-07-23 18:16:43 +00:00
|
|
|
User.dataSource.connector.destroy = destroy;
|
2013-03-31 00:18:47 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2013-03-31 10:17:25 +00:00
|
|
|
|
2013-03-24 21:25:10 +00:00
|
|
|
});
|
2013-03-28 11:27:50 +00:00
|
|
|
|
|
|
|
describe('lifecycle', function() {
|
|
|
|
var life = [], user;
|
|
|
|
before(function(done) {
|
|
|
|
User.beforeSave = function(d){life.push('beforeSave'); d();};
|
|
|
|
User.beforeCreate = function(d){life.push('beforeCreate'); d();};
|
|
|
|
User.beforeUpdate = function(d){life.push('beforeUpdate'); d();};
|
|
|
|
User.beforeDestroy = function(d){life.push('beforeDestroy');d();};
|
|
|
|
User.beforeValidate = function(d){life.push('beforeValidate');d();};
|
|
|
|
User.afterInitialize= function( ){life.push('afterInitialize'); };
|
|
|
|
User.afterSave = function(d){life.push('afterSave'); d();};
|
|
|
|
User.afterCreate = function(d){life.push('afterCreate'); d();};
|
|
|
|
User.afterUpdate = function(d){life.push('afterUpdate'); d();};
|
|
|
|
User.afterDestroy = function(d){life.push('afterDestroy'); d();};
|
|
|
|
User.afterValidate = function(d){life.push('afterValidate');d();};
|
|
|
|
User.create(function(e, u) {
|
|
|
|
user = u;
|
|
|
|
life = [];
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
beforeEach(function() {
|
|
|
|
life = [];
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should describe create sequence', function(done) {
|
|
|
|
User.create(function() {
|
|
|
|
life.should.eql([
|
|
|
|
'afterInitialize',
|
|
|
|
'beforeValidate',
|
|
|
|
'afterValidate',
|
|
|
|
'beforeCreate',
|
|
|
|
'beforeSave',
|
|
|
|
'afterSave',
|
|
|
|
'afterCreate'
|
|
|
|
]);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should describe new+save sequence', function(done) {
|
|
|
|
var u = new User;
|
|
|
|
u.save(function() {
|
|
|
|
life.should.eql([
|
|
|
|
'afterInitialize',
|
|
|
|
'beforeValidate',
|
|
|
|
'afterValidate',
|
|
|
|
'beforeCreate',
|
|
|
|
'beforeSave',
|
|
|
|
'afterSave',
|
|
|
|
'afterCreate'
|
|
|
|
]);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-03-29 07:43:04 +00:00
|
|
|
it('should describe updateAttributes sequence', function(done) {
|
|
|
|
user.updateAttributes({name: 'Antony'}, function() {
|
2013-03-28 11:27:50 +00:00
|
|
|
life.should.eql([
|
|
|
|
'beforeValidate',
|
|
|
|
'afterValidate',
|
|
|
|
'beforeSave',
|
2013-03-29 07:43:04 +00:00
|
|
|
'beforeUpdate',
|
|
|
|
'afterUpdate',
|
2013-03-28 11:27:50 +00:00
|
|
|
'afterSave',
|
|
|
|
]);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-03-29 07:43:04 +00:00
|
|
|
it('should describe isValid sequence', function(done) {
|
|
|
|
should.not.exist(
|
|
|
|
user.constructor._validations,
|
|
|
|
'Expected user to have no validations, but she have');
|
|
|
|
user.isValid(function(valid) {
|
|
|
|
valid.should.be.true;
|
2013-03-28 11:27:50 +00:00
|
|
|
life.should.eql([
|
|
|
|
'beforeValidate',
|
2013-03-29 07:43:04 +00:00
|
|
|
'afterValidate'
|
|
|
|
]);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should describe destroy sequence', function(done) {
|
|
|
|
user.destroy(function() {
|
|
|
|
life.should.eql([
|
|
|
|
'beforeDestroy',
|
|
|
|
'afterDestroy'
|
2013-03-28 11:27:50 +00:00
|
|
|
]);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
2013-03-24 21:25:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
function addHooks(name, done) {
|
2013-04-07 13:59:24 +00:00
|
|
|
var called = false, random = String(Math.floor(Math.random() * 1000));
|
2013-03-24 21:25:10 +00:00
|
|
|
User['before' + name] = function(next, data) {
|
|
|
|
called = true;
|
|
|
|
data.email = random;
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
User['after' + name] = function(next) {
|
|
|
|
(new Boolean(called)).should.equal(true);
|
|
|
|
this.email.should.equal(random);
|
|
|
|
done();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function removeHooks(name) {
|
|
|
|
return function() {
|
|
|
|
User['after' + name] = null;
|
|
|
|
User['before' + name] = null;
|
|
|
|
};
|
|
|
|
}
|