不要怂,就是干,撸起袖子干!

Commit 382ea2aa by Mick Hansen

Merge pull request #5506 from sushantdhiman/fix-hooks-1

Hooks Tests and Refractor
2 parents d1ec689e 4f0efb34
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + '/../../../lib/data-types');
describe(Support.getTestDialectTeaser('Hooks'), function() {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
});
return this.sequelize.sync({ force: true });
});
describe('#count', function() {
beforeEach(function() {
return this.User.bulkCreate([
{username: 'adam', mood: 'happy'},
{username: 'joe', mood: 'sad'},
{username: 'joe', mood: 'happy'}
]);
});
describe('on success', function() {
it('hook runs', function() {
var beforeHook = false;
this.User.beforeCount(function() {
beforeHook = true;
});
return this.User.count().then(function(count) {
expect(count).to.equal(3);
expect(beforeHook).to.be.true;
});
});
it('beforeCount hook can change options', function() {
this.User.beforeCount(function(options) {
options.where.username = 'adam';
});
return expect(this.User.count({where: {username: 'joe'}})).to.eventually.equal(1);
});
});
describe('on error', function() {
it('in beforeCount hook returns error', function() {
this.User.beforeCount(function() {
throw new Error('Oops!');
});
return expect(this.User.count({where: {username: 'adam'}})).to.be.rejectedWith('Oops!');
});
});
});
});
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + '/../../../lib/data-types')
, Sequelize = Support.Sequelize
, sinon = require('sinon');
describe(Support.getTestDialectTeaser('Hooks'), function() {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
});
return this.sequelize.sync({ force: true });
});
describe('#create', function() {
describe('on success', function() {
it('should run hooks', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeCreate(beforeHook);
this.User.afterCreate(afterHook);
return this.User.create({username: 'Toni', mood: 'happy'}).then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
});
});
});
describe('on error', function() {
it('should return an error from before', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeCreate(function(user, options) {
beforeHook();
throw new Error('Whoops!');
});
this.User.afterCreate(afterHook);
return expect(this.User.create({username: 'Toni', mood: 'happy'})).to.be.rejected.then(function(err) {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).not.to.have.been.called;
});
});
it('should return an error from after', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeCreate(beforeHook);
this.User.afterCreate(function(user, options) {
afterHook();
throw new Error('Whoops!');
});
return expect(this.User.create({username: 'Toni', mood: 'happy'})).to.be.rejected.then(function(err) {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
});
});
});
it('should not trigger hooks on parent when using N:M association setters', function() {
var A = this.sequelize.define('A', {
name: Sequelize.STRING
});
var B = this.sequelize.define('B', {
name: Sequelize.STRING
});
var hookCalled = 0;
A.addHook('afterCreate', function(instance, options, next) {
hookCalled++;
next();
});
B.belongsToMany(A, {through: 'a_b'});
A.belongsToMany(B, {through: 'a_b'});
return this.sequelize.sync({force: true}).bind(this).then(function() {
return this.sequelize.Promise.all([
A.create({name: 'a'}),
B.create({name: 'b'})
]).spread(function(a, b) {
return a.addB(b).then(function() {
expect(hookCalled).to.equal(1);
});
});
});
});
describe('preserves changes to instance', function() {
it('beforeValidate', function(){
var hookCalled = 0;
this.User.beforeValidate(function(user, options) {
user.mood = 'happy';
hookCalled++;
});
return this.User.create({mood: 'sad', username: 'leafninja'}).then(function(user) {
expect(user.mood).to.equal('happy');
expect(user.username).to.equal('leafninja');
expect(hookCalled).to.equal(1);
});
});
it('afterValidate', function() {
var hookCalled = 0;
this.User.afterValidate(function(user, options) {
user.mood = 'neutral';
hookCalled++;
});
return this.User.create({mood: 'sad', username: 'fireninja'}).then(function(user) {
expect(user.mood).to.equal('neutral');
expect(user.username).to.equal('fireninja');
expect(hookCalled).to.equal(1);
});
});
it('beforeCreate', function(){
var hookCalled = 0;
this.User.beforeCreate(function(user, options) {
user.mood = 'happy';
hookCalled++;
});
return this.User.create({username: 'akira'}).then(function(user) {
expect(user.mood).to.equal('happy');
expect(user.username).to.equal('akira');
expect(hookCalled).to.equal(1);
});
});
});
});
});
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + '/../../../lib/data-types')
, sinon = require('sinon');
describe(Support.getTestDialectTeaser('Hooks'), function() {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
});
return this.sequelize.sync({ force: true });
});
describe('#destroy', function() {
describe('on success', function() {
it('should run hooks', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeDestroy(beforeHook);
this.User.afterDestroy(afterHook);
return this.User.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return user.destroy().then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
});
});
});
});
describe('on error', function() {
it('should return an error from before', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeDestroy(function(user, options) {
beforeHook();
throw new Error('Whoops!');
});
this.User.afterDestroy(afterHook);
return this.User.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return expect(user.destroy()).to.be.rejected.then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).not.to.have.been.called;
});
});
});
it('should return an error from after', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeDestroy(beforeHook);
this.User.afterDestroy(function(user, options) {
afterHook();
throw new Error('Whoops!');
});
return this.User.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return expect(user.destroy()).to.be.rejected.then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
});
});
});
});
});
});
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + '/../../../lib/data-types');
describe(Support.getTestDialectTeaser('Hooks'), function() {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
});
return this.sequelize.sync({ force: true });
});
describe('#find', function() {
beforeEach(function() {
return this.User.bulkCreate([
{username: 'adam', mood: 'happy'},
{username: 'joe', mood: 'sad'}
]);
});
describe('on success', function() {
it('all hooks run', function() {
var beforeHook = false
, beforeHook2 = false
, beforeHook3 = false
, afterHook = false;
this.User.beforeFind(function() {
beforeHook = true;
});
this.User.beforeFindAfterExpandIncludeAll(function() {
beforeHook2 = true;
});
this.User.beforeFindAfterOptions(function() {
beforeHook3 = true;
});
this.User.afterFind(function() {
afterHook = true;
});
return this.User.find({where: {username: 'adam'}}).then(function(user) {
expect(user.mood).to.equal('happy');
expect(beforeHook).to.be.true;
expect(beforeHook2).to.be.true;
expect(beforeHook3).to.be.true;
expect(afterHook).to.be.true;
});
});
it('beforeFind hook can change options', function() {
this.User.beforeFind(function(options) {
options.where.username = 'joe';
});
return this.User.find({where: {username: 'adam'}}).then(function(user) {
expect(user.mood).to.equal('sad');
});
});
it('beforeFindAfterExpandIncludeAll hook can change options', function() {
this.User.beforeFindAfterExpandIncludeAll(function(options) {
options.where.username = 'joe';
});
return this.User.find({where: {username: 'adam'}}).then(function(user) {
expect(user.mood).to.equal('sad');
});
});
it('beforeFindAfterOptions hook can change options', function() {
this.User.beforeFindAfterOptions(function(options) {
options.where.username = 'joe';
});
return this.User.find({where: {username: 'adam'}}).then(function(user) {
expect(user.mood).to.equal('sad');
});
});
it('afterFind hook can change results', function() {
this.User.afterFind(function(user) {
user.mood = 'sad';
});
return this.User.find({where: {username: 'adam'}}).then(function(user) {
expect(user.mood).to.equal('sad');
});
});
});
describe('on error', function() {
it('in beforeFind hook returns error', function() {
this.User.beforeFind(function() {
throw new Error('Oops!');
});
return this.User.find({where: {username: 'adam'}}).catch (function(err) {
expect(err.message).to.equal('Oops!');
});
});
it('in beforeFindAfterExpandIncludeAll hook returns error', function() {
this.User.beforeFindAfterExpandIncludeAll(function() {
throw new Error('Oops!');
});
return this.User.find({where: {username: 'adam'}}).catch (function(err) {
expect(err.message).to.equal('Oops!');
});
});
it('in beforeFindAfterOptions hook returns error', function() {
this.User.beforeFindAfterOptions(function() {
throw new Error('Oops!');
});
return this.User.find({where: {username: 'adam'}}).catch (function(err) {
expect(err.message).to.equal('Oops!');
});
});
it('in afterFind hook returns error', function() {
this.User.afterFind(function() {
throw new Error('Oops!');
});
return this.User.find({where: {username: 'adam'}}).catch (function(err) {
expect(err.message).to.equal('Oops!');
});
});
});
});
});
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + '/../../../lib/data-types')
, sinon = require('sinon');
describe(Support.getTestDialectTeaser('Hooks'), function() {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
});
this.ParanoidUser = this.sequelize.define('ParanoidUser', {
username: DataTypes.STRING,
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
}, {
paranoid: true
});
return this.sequelize.sync({ force: true });
});
describe('#restore', function() {
describe('on success', function() {
it('should run hooks', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.ParanoidUser.beforeRestore(beforeHook);
this.ParanoidUser.afterRestore(afterHook);
return this.ParanoidUser.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return user.destroy().then(function() {
return user.restore().then(function(user) {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
});
});
});
});
});
describe('on error', function() {
it('should return an error from before', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.ParanoidUser.beforeRestore(function(user, options) {
beforeHook();
throw new Error('Whoops!');
});
this.ParanoidUser.afterRestore(afterHook);
return this.ParanoidUser.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return user.destroy().then(function() {
return expect(user.restore()).to.be.rejected.then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).not.to.have.been.called;
});
});
});
});
it('should return an error from after', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.ParanoidUser.beforeRestore(beforeHook);
this.ParanoidUser.afterRestore(function(user, options) {
afterHook();
throw new Error('Whoops!');
});
return this.ParanoidUser.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return user.destroy().then(function() {
return expect(user.restore()).to.be.rejected.then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
});
});
});
});
});
});
});
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + '/../../../lib/data-types')
, sinon = require('sinon');
describe(Support.getTestDialectTeaser('Hooks'), function() {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
});
return this.sequelize.sync({ force: true });
});
describe('#updateAttributes', function() {
describe('on success', function() {
it('should run hooks', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeUpdate(beforeHook);
this.User.afterUpdate(afterHook);
return this.User.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return user.updateAttributes({username: 'Chong'}).then(function(user) {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
expect(user.username).to.equal('Chong');
});
});
});
});
describe('on error', function() {
it('should return an error from before', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeUpdate(function(user, options) {
beforeHook();
throw new Error('Whoops!');
});
this.User.afterUpdate(afterHook);
return this.User.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return expect(user.updateAttributes({username: 'Chong'})).to.be.rejected.then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).not.to.have.been.called;
});
});
});
it('should return an error from after', function() {
var beforeHook = sinon.spy()
, afterHook = sinon.spy();
this.User.beforeUpdate(beforeHook);
this.User.afterUpdate(function(user, options) {
afterHook();
throw new Error('Whoops!');
});
return this.User.create({username: 'Toni', mood: 'happy'}).then(function(user) {
return expect(user.updateAttributes({username: 'Chong'})).to.be.rejected.then(function() {
expect(beforeHook).to.have.been.calledOnce;
expect(afterHook).to.have.been.calledOnce;
});
});
});
});
describe('preserves changes to instance', function() {
it('beforeValidate', function(){
this.User.beforeValidate(function(user, options) {
user.mood = 'happy';
});
return this.User.create({username: 'fireninja', mood: 'invalid'}).then(function(user) {
return user.updateAttributes({username: 'hero'});
}).then(function(user) {
expect(user.username).to.equal('hero');
expect(user.mood).to.equal('happy');
});
});
it('afterValidate', function() {
this.User.afterValidate(function(user, options) {
user.mood = 'sad';
});
return this.User.create({username: 'fireninja', mood: 'nuetral'}).then(function(user) {
return user.updateAttributes({username: 'spider'});
}).then(function(user) {
expect(user.username).to.equal('spider');
expect(user.mood).to.equal('sad');
});
});
});
});
});
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + '/../../../lib/data-types')
, sinon = require('sinon');
describe(Support.getTestDialectTeaser('Hooks'), function() {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
});
return this.sequelize.sync({ force: true });
});
describe('#validate', function() {
describe('#create', function() {
it('should return the user', function() {
this.User.beforeValidate(function(user, options) {
user.username = 'Bob';
user.mood = 'happy';
});
this.User.afterValidate(function(user, options) {
user.username = 'Toni';
});
return this.User.create({mood: 'ecstatic'}).then(function(user) {
expect(user.mood).to.equal('happy');
expect(user.username).to.equal('Toni');
});
});
});
describe('on error', function() {
it('should emit an error from after hook', function() {
this.User.afterValidate(function(user, options) {
user.mood = 'ecstatic';
throw new Error('Whoops! Changed user.mood!');
});
return expect(this.User.create({username: 'Toni', mood: 'happy'})).to.be.rejectedWith('Whoops! Changed user.mood!');
});
it('should call validationFailed hook', function() {
var validationFailedHook = sinon.spy();
this.User.validationFailed(validationFailedHook);
return expect(this.User.create({mood: 'happy'})).to.be.rejected.then(function(err) {
expect(validationFailedHook).to.have.been.calledOnce;
});
});
it('should not replace the validation error in validationFailed hook by default', function() {
var validationFailedHook = sinon.stub();
this.User.validationFailed(validationFailedHook);
return expect(this.User.create({mood: 'happy'})).to.be.rejected.then(function(err) {
expect(err.name).to.equal('SequelizeValidationError');
});
});
it('should replace the validation error if validationFailed hook creates a new error', function() {
var validationFailedHook = sinon.stub().throws(new Error('Whoops!'));
this.User.validationFailed(validationFailedHook);
return expect(this.User.create({mood: 'happy'})).to.be.rejected.then(function(err) {
expect(err.message).to.equal('Whoops!');
});
});
});
});
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!