123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- 'use strict';
- const chai = require('chai');
- const expect = chai.expect;
- const Support = require('../support');
- const {
- InstanceValidator,
- } = require('@sequelize/core/_non-semver-use-at-your-own-risk_/instance-validator.js');
- const sinon = require('sinon');
- const { DataTypes, ValidationError: SequelizeValidationError } = require('@sequelize/core');
- describe(Support.getTestDialectTeaser('InstanceValidator'), () => {
- beforeEach(function () {
- this.User = Support.sequelize.define('user', {
- fails: {
- type: DataTypes.BOOLEAN,
- validate: {
- isNotTrue(value) {
- if (value) {
- throw new Error('Manual model validation failure');
- }
- },
- },
- },
- });
- });
- it('configures itself to run hooks by default', () => {
- const instanceValidator = new InstanceValidator();
- expect(instanceValidator.options.hooks).to.equal(true);
- });
- describe('validate', () => {
- it('runs the validation sequence and hooks when the hooks option is true', function () {
- const instanceValidator = new InstanceValidator(this.User.build(), { hooks: true });
- const _validate = sinon.spy(instanceValidator, '_validate');
- const _validateAndRunHooks = sinon.spy(instanceValidator, '_validateAndRunHooks');
- instanceValidator.validate();
- expect(_validateAndRunHooks).to.have.been.calledOnce;
- expect(_validate).to.not.have.been.called;
- });
- it('runs the validation sequence but skips hooks if the hooks option is false', function () {
- const instanceValidator = new InstanceValidator(this.User.build(), { hooks: false });
- const _validate = sinon.spy(instanceValidator, '_validate');
- const _validateAndRunHooks = sinon.spy(instanceValidator, '_validateAndRunHooks');
- instanceValidator.validate();
- expect(_validate).to.have.been.calledOnce;
- expect(_validateAndRunHooks).to.not.have.been.called;
- });
- it('fulfills when validation is successful', async function () {
- const instanceValidator = new InstanceValidator(this.User.build());
- const result = instanceValidator.validate();
- await expect(result).to.be.fulfilled;
- });
- it('rejects with a validation error when validation fails', async function () {
- const instanceValidator = new InstanceValidator(this.User.build({ fails: true }));
- const result = instanceValidator.validate();
- await expect(result).to.be.rejectedWith(SequelizeValidationError);
- });
- it('has a useful default error message for not null validation failures', async () => {
- const User = Support.sequelize.define('user', {
- name: {
- type: DataTypes.STRING,
- allowNull: false,
- },
- });
- const instanceValidator = new InstanceValidator(User.build());
- const result = instanceValidator.validate();
- await expect(result).to.be.rejectedWith(
- SequelizeValidationError,
- /user\.name cannot be null/,
- );
- });
- });
- describe('_validateAndRunHooks', () => {
- beforeEach(function () {
- this.successfulInstanceValidator = new InstanceValidator(this.User.build());
- sinon.stub(this.successfulInstanceValidator, '_validate').resolves();
- });
- it('should run beforeValidate and afterValidate hooks when _validate is successful', async function () {
- const beforeValidate = sinon.spy();
- const afterValidate = sinon.spy();
- this.User.beforeValidate(beforeValidate);
- this.User.afterValidate(afterValidate);
- await expect(this.successfulInstanceValidator._validateAndRunHooks()).to.be.fulfilled;
- expect(beforeValidate).to.have.been.calledOnce;
- expect(afterValidate).to.have.been.calledOnce;
- });
- it('should run beforeValidate hook but not afterValidate hook when _validate is unsuccessful', async function () {
- const failingInstanceValidator = new InstanceValidator(this.User.build());
- sinon.stub(failingInstanceValidator, '_validate').rejects(new Error());
- const beforeValidate = sinon.spy();
- const afterValidate = sinon.spy();
- this.User.beforeValidate(beforeValidate);
- this.User.afterValidate(afterValidate);
- await expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected;
- expect(beforeValidate).to.have.been.calledOnce;
- expect(afterValidate).to.not.have.been.called;
- });
- it('should emit an error from after hook when afterValidate fails', async function () {
- this.User.afterValidate(() => {
- throw new Error('after validation error');
- });
- await expect(this.successfulInstanceValidator._validateAndRunHooks()).to.be.rejectedWith(
- 'after validation error',
- );
- });
- describe('validatedFailed hook', () => {
- it('should call validationFailed hook when validation fails', async function () {
- const failingInstanceValidator = new InstanceValidator(this.User.build());
- sinon.stub(failingInstanceValidator, '_validate').rejects(new Error());
- const validationFailedHook = sinon.spy();
- this.User.validationFailed(validationFailedHook);
- await expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected;
- expect(validationFailedHook).to.have.been.calledOnce;
- });
- it('should not replace the validation error in validationFailed hook by default', async function () {
- const failingInstanceValidator = new InstanceValidator(this.User.build());
- sinon.stub(failingInstanceValidator, '_validate').rejects(new SequelizeValidationError());
- const validationFailedHook = sinon.stub().resolves();
- this.User.validationFailed(validationFailedHook);
- const err = await expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected;
- expect(err.name).to.equal('SequelizeValidationError');
- });
- it('should replace the validation error if validationFailed hook creates a new error', async function () {
- const failingInstanceValidator = new InstanceValidator(this.User.build());
- sinon.stub(failingInstanceValidator, '_validate').rejects(new SequelizeValidationError());
- const validationFailedHook = sinon.stub().throws(new Error('validation failed hook error'));
- this.User.validationFailed(validationFailedHook);
- const err = await expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected;
- expect(err.message).to.equal('validation failed hook error');
- });
- });
- });
- });
|