123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- 'use strict';
- const chai = require('chai');
- const expect = chai.expect;
- const Support = require('../support');
- const { DataTypes } = require('@sequelize/core');
- const sinon = require('sinon');
- describe(Support.getTestDialectTeaser('Hooks'), () => {
- beforeEach(async function () {
- this.User = this.sequelize.define('User', {
- username: {
- type: DataTypes.STRING,
- allowNull: false,
- },
- mood: {
- type: DataTypes.ENUM(['happy', 'sad', 'neutral']),
- },
- });
- this.ParanoidUser = this.sequelize.define(
- 'ParanoidUser',
- {
- username: DataTypes.STRING,
- mood: {
- type: DataTypes.ENUM(['happy', 'sad', 'neutral']),
- },
- },
- {
- paranoid: true,
- },
- );
- await this.sequelize.sync({ force: true });
- });
- describe('#bulkCreate', () => {
- describe('on success', () => {
- it('should run hooks', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- this.User.beforeBulkCreate(beforeBulk);
- this.User.afterBulkCreate(afterBulk);
- await this.User.bulkCreate([
- { username: 'Cheech', mood: 'sad' },
- { username: 'Chong', mood: 'sad' },
- ]);
- expect(beforeBulk).to.have.been.calledOnce;
- expect(afterBulk).to.have.been.calledOnce;
- });
- });
- describe('on error', () => {
- it('should return an error from before', async function () {
- this.User.beforeBulkCreate(() => {
- throw new Error('Whoops!');
- });
- await expect(
- this.User.bulkCreate([
- { username: 'Cheech', mood: 'sad' },
- { username: 'Chong', mood: 'sad' },
- ]),
- ).to.be.rejected;
- });
- it('should return an error from after', async function () {
- this.User.afterBulkCreate(() => {
- throw new Error('Whoops!');
- });
- await expect(
- this.User.bulkCreate([
- { username: 'Cheech', mood: 'sad' },
- { username: 'Chong', mood: 'sad' },
- ]),
- ).to.be.rejected;
- });
- });
- describe('with the {individualHooks: true} option', () => {
- beforeEach(async function () {
- this.User = this.sequelize.define('User', {
- username: {
- type: DataTypes.STRING,
- defaultValue: '',
- },
- beforeHookTest: {
- type: DataTypes.BOOLEAN,
- defaultValue: false,
- },
- aNumber: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- });
- await this.User.sync({ force: true });
- });
- it('should run the afterCreate/beforeCreate functions for each item created successfully', async function () {
- let beforeBulkCreate = false;
- let afterBulkCreate = false;
- this.User.beforeBulkCreate(async () => {
- beforeBulkCreate = true;
- });
- this.User.afterBulkCreate(async () => {
- afterBulkCreate = true;
- });
- this.User.beforeCreate(async user => {
- user.beforeHookTest = true;
- });
- this.User.afterCreate(async user => {
- user.username = `User${user.id}`;
- });
- const records = await this.User.bulkCreate(
- [{ aNumber: 5 }, { aNumber: 7 }, { aNumber: 3 }],
- { fields: ['aNumber'], individualHooks: true },
- );
- for (const record of records) {
- expect(record.username).to.equal(`User${record.id}`);
- expect(record.beforeHookTest).to.be.true;
- }
- expect(beforeBulkCreate).to.be.true;
- expect(afterBulkCreate).to.be.true;
- });
- it('should run the afterCreate/beforeCreate functions for each item created with an error', async function () {
- let beforeBulkCreate = false;
- let afterBulkCreate = false;
- this.User.beforeBulkCreate(async () => {
- beforeBulkCreate = true;
- });
- this.User.afterBulkCreate(async () => {
- afterBulkCreate = true;
- });
- this.User.beforeCreate(async () => {
- throw new Error('You shall not pass!');
- });
- this.User.afterCreate(async user => {
- user.username = `User${user.id}`;
- });
- try {
- await this.User.bulkCreate([{ aNumber: 5 }, { aNumber: 7 }, { aNumber: 3 }], {
- fields: ['aNumber'],
- individualHooks: true,
- });
- } catch (error) {
- expect(error).to.be.instanceOf(Error);
- expect(beforeBulkCreate).to.be.true;
- expect(afterBulkCreate).to.be.false;
- }
- });
- });
- });
- describe('#bulkUpdate', () => {
- describe('on success', () => {
- it('should run hooks', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- this.User.beforeBulkUpdate(beforeBulk);
- this.User.afterBulkUpdate(afterBulk);
- await this.User.bulkCreate([
- { username: 'Cheech', mood: 'sad' },
- { username: 'Chong', mood: 'sad' },
- ]);
- await this.User.update({ mood: 'happy' }, { where: { mood: 'sad' } });
- expect(beforeBulk).to.have.been.calledOnce;
- expect(afterBulk).to.have.been.calledOnce;
- });
- });
- describe('on error', () => {
- it('should return an error from before', async function () {
- this.User.beforeBulkUpdate(() => {
- throw new Error('Whoops!');
- });
- await this.User.bulkCreate([
- { username: 'Cheech', mood: 'sad' },
- { username: 'Chong', mood: 'sad' },
- ]);
- await expect(this.User.update({ mood: 'happy' }, { where: { mood: 'sad' } })).to.be
- .rejected;
- });
- it('should return an error from after', async function () {
- this.User.afterBulkUpdate(() => {
- throw new Error('Whoops!');
- });
- await this.User.bulkCreate([
- { username: 'Cheech', mood: 'sad' },
- { username: 'Chong', mood: 'sad' },
- ]);
- await expect(this.User.update({ mood: 'happy' }, { where: { mood: 'sad' } })).to.be
- .rejected;
- });
- });
- describe('with the {individualHooks: true} option', () => {
- beforeEach(async function () {
- this.User = this.sequelize.define('User', {
- username: {
- type: DataTypes.STRING,
- defaultValue: '',
- },
- beforeHookTest: {
- type: DataTypes.BOOLEAN,
- defaultValue: false,
- },
- aNumber: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- });
- await this.User.sync({ force: true });
- });
- it('should run the after/before functions for each item created successfully', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- this.User.beforeBulkUpdate(beforeBulk);
- this.User.afterBulkUpdate(afterBulk);
- this.User.beforeUpdate(user => {
- expect(user.changed()).to.not.be.empty;
- user.beforeHookTest = true;
- });
- this.User.afterUpdate(user => {
- user.username = `User${user.id}`;
- });
- await this.User.bulkCreate([{ aNumber: 1 }, { aNumber: 1 }, { aNumber: 1 }]);
- const [, records] = await this.User.update(
- { aNumber: 10 },
- { where: { aNumber: 1 }, individualHooks: true },
- );
- for (const record of records) {
- expect(record.username).to.equal(`User${record.id}`);
- expect(record.beforeHookTest).to.be.true;
- }
- expect(beforeBulk).to.have.been.calledOnce;
- expect(afterBulk).to.have.been.calledOnce;
- });
- it('should run the after/before functions for each item created successfully changing some data before updating', async function () {
- this.User.beforeUpdate(user => {
- expect(user.changed()).to.not.be.empty;
- if (user.get('id') === 1) {
- user.set('aNumber', user.get('aNumber') + 3);
- }
- });
- await this.User.bulkCreate([{ aNumber: 1 }, { aNumber: 1 }, { aNumber: 1 }]);
- const [, records] = await this.User.update(
- { aNumber: 10 },
- { where: { aNumber: 1 }, individualHooks: true },
- );
- for (const record of records) {
- expect(record.aNumber).to.equal(10 + (record.id === 1 ? 3 : 0));
- }
- });
- it('should run the after/before functions for each item created with an error', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- this.User.beforeBulkUpdate(beforeBulk);
- this.User.afterBulkUpdate(afterBulk);
- this.User.beforeUpdate(() => {
- throw new Error('You shall not pass!');
- });
- this.User.afterUpdate(user => {
- user.username = `User${user.id}`;
- });
- await this.User.bulkCreate([{ aNumber: 1 }, { aNumber: 1 }, { aNumber: 1 }], {
- fields: ['aNumber'],
- });
- try {
- await this.User.update({ aNumber: 10 }, { where: { aNumber: 1 }, individualHooks: true });
- } catch (error) {
- expect(error).to.be.instanceOf(Error);
- expect(error.message).to.equal('You shall not pass!');
- expect(beforeBulk).to.have.been.calledOnce;
- expect(afterBulk).not.to.have.been.called;
- }
- });
- });
- });
- describe('#bulkDestroy', () => {
- describe('on success', () => {
- it('should run hooks', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- this.User.beforeBulkDestroy(beforeBulk);
- this.User.afterBulkDestroy(afterBulk);
- await this.User.destroy({ where: { username: 'Cheech', mood: 'sad' } });
- expect(beforeBulk).to.have.been.calledOnce;
- expect(afterBulk).to.have.been.calledOnce;
- });
- });
- describe('on error', () => {
- it('should return an error from before', async function () {
- this.User.beforeBulkDestroy(() => {
- throw new Error('Whoops!');
- });
- await expect(this.User.destroy({ where: { username: 'Cheech', mood: 'sad' } })).to.be
- .rejected;
- });
- it('should return an error from after', async function () {
- this.User.afterBulkDestroy(() => {
- throw new Error('Whoops!');
- });
- await expect(this.User.destroy({ where: { username: 'Cheech', mood: 'sad' } })).to.be
- .rejected;
- });
- });
- describe('with the {individualHooks: true} option', () => {
- beforeEach(async function () {
- this.User = this.sequelize.define('User', {
- username: {
- type: DataTypes.STRING,
- defaultValue: '',
- },
- beforeHookTest: {
- type: DataTypes.BOOLEAN,
- defaultValue: false,
- },
- aNumber: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- });
- await this.User.sync({ force: true });
- });
- it('should run the after/before functions for each item created successfully', async function () {
- let beforeBulk = false;
- let afterBulk = false;
- let beforeHook = false;
- let afterHook = false;
- this.User.beforeBulkDestroy(async () => {
- beforeBulk = true;
- });
- this.User.afterBulkDestroy(async () => {
- afterBulk = true;
- });
- this.User.beforeDestroy(async () => {
- beforeHook = true;
- });
- this.User.afterDestroy(async () => {
- afterHook = true;
- });
- await this.User.bulkCreate([{ aNumber: 1 }, { aNumber: 1 }, { aNumber: 1 }]);
- await this.User.destroy({ where: { aNumber: 1 }, individualHooks: true });
- expect(beforeBulk).to.be.true;
- expect(afterBulk).to.be.true;
- expect(beforeHook).to.be.true;
- expect(afterHook).to.be.true;
- });
- it('should run the after/before functions for each item created with an error', async function () {
- let beforeBulk = false;
- let afterBulk = false;
- let beforeHook = false;
- let afterHook = false;
- this.User.beforeBulkDestroy(async () => {
- beforeBulk = true;
- });
- this.User.afterBulkDestroy(async () => {
- afterBulk = true;
- });
- this.User.beforeDestroy(async () => {
- beforeHook = true;
- throw new Error('You shall not pass!');
- });
- this.User.afterDestroy(async () => {
- afterHook = true;
- });
- await this.User.bulkCreate([{ aNumber: 1 }, { aNumber: 1 }, { aNumber: 1 }], {
- fields: ['aNumber'],
- });
- try {
- await this.User.destroy({ where: { aNumber: 1 }, individualHooks: true });
- } catch (error) {
- expect(error).to.be.instanceOf(Error);
- expect(beforeBulk).to.be.true;
- expect(beforeHook).to.be.true;
- expect(afterBulk).to.be.false;
- expect(afterHook).to.be.false;
- }
- });
- });
- });
- describe('#bulkRestore', () => {
- beforeEach(async function () {
- await this.ParanoidUser.bulkCreate([
- { username: 'adam', mood: 'happy' },
- { username: 'joe', mood: 'sad' },
- ]);
- await this.ParanoidUser.truncate();
- });
- describe('on success', () => {
- it('should run hooks', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- this.ParanoidUser.beforeBulkRestore(beforeBulk);
- this.ParanoidUser.afterBulkRestore(afterBulk);
- await this.ParanoidUser.restore({ where: { username: 'adam', mood: 'happy' } });
- expect(beforeBulk).to.have.been.calledOnce;
- expect(afterBulk).to.have.been.calledOnce;
- });
- });
- describe('on error', () => {
- it('should return an error from before', async function () {
- this.ParanoidUser.beforeBulkRestore(() => {
- throw new Error('Whoops!');
- });
- await expect(this.ParanoidUser.restore({ where: { username: 'adam', mood: 'happy' } })).to
- .be.rejected;
- });
- it('should return an error from after', async function () {
- this.ParanoidUser.afterBulkRestore(() => {
- throw new Error('Whoops!');
- });
- await expect(this.ParanoidUser.restore({ where: { username: 'adam', mood: 'happy' } })).to
- .be.rejected;
- });
- });
- describe('with the {individualHooks: true} option', () => {
- beforeEach(async function () {
- this.ParanoidUser = this.sequelize.define(
- 'ParanoidUser',
- {
- aNumber: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- },
- {
- paranoid: true,
- },
- );
- await this.ParanoidUser.sync({ force: true });
- });
- it('should run the after/before functions for each item restored successfully', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- const beforeHook = sinon.spy();
- const afterHook = sinon.spy();
- this.ParanoidUser.beforeBulkRestore(beforeBulk);
- this.ParanoidUser.afterBulkRestore(afterBulk);
- this.ParanoidUser.beforeRestore(beforeHook);
- this.ParanoidUser.afterRestore(afterHook);
- await this.ParanoidUser.bulkCreate([{ aNumber: 1 }, { aNumber: 1 }, { aNumber: 1 }]);
- await this.ParanoidUser.destroy({ where: { aNumber: 1 } });
- await this.ParanoidUser.restore({ where: { aNumber: 1 }, individualHooks: true });
- expect(beforeBulk).to.have.been.calledOnce;
- expect(afterBulk).to.have.been.calledOnce;
- expect(beforeHook).to.have.been.calledThrice;
- expect(afterHook).to.have.been.calledThrice;
- });
- it('should run the after/before functions for each item restored with an error', async function () {
- const beforeBulk = sinon.spy();
- const afterBulk = sinon.spy();
- const beforeHook = sinon.spy();
- const afterHook = sinon.spy();
- this.ParanoidUser.beforeBulkRestore(beforeBulk);
- this.ParanoidUser.afterBulkRestore(afterBulk);
- this.ParanoidUser.beforeRestore(async () => {
- beforeHook();
- throw new Error('You shall not pass!');
- });
- this.ParanoidUser.afterRestore(afterHook);
- try {
- await this.ParanoidUser.bulkCreate([{ aNumber: 1 }, { aNumber: 1 }, { aNumber: 1 }], {
- fields: ['aNumber'],
- });
- await this.ParanoidUser.destroy({ where: { aNumber: 1 } });
- await this.ParanoidUser.restore({ where: { aNumber: 1 }, individualHooks: true });
- } catch (error) {
- expect(error).to.be.instanceOf(Error);
- expect(beforeBulk).to.have.been.calledOnce;
- expect(beforeHook).to.have.been.calledThrice;
- expect(afterBulk).not.to.have.been.called;
- expect(afterHook).not.to.have.been.called;
- }
- });
- });
- });
- });
|