instance-validator.test.js
6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
'use strict';
const chai = require('chai');
const expect = chai.expect;
const Support = require('./support');
const InstanceValidator = require('../../lib/instance-validator');
const sinon = require('sinon');
const Promise = Support.Sequelize.Promise;
const SequelizeValidationError = require('../../lib/errors').ValidationError;
describe(Support.getTestDialectTeaser('InstanceValidator'), () => {
beforeEach(function() {
this.User = Support.sequelize.define('user', {
fails: {
type: Support.Sequelize.BOOLEAN,
validate: {
isNotTrue(value) {
if (value) {
throw 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', function() {
const instanceValidator = new InstanceValidator(this.User.build());
const result = instanceValidator.validate();
return expect(result).to.be.fulfilled;
});
it('rejects with a validation error when validation fails', function() {
const instanceValidator = new InstanceValidator(this.User.build({ fails: true }));
const result = instanceValidator.validate();
return expect(result).to.be.rejectedWith(SequelizeValidationError);
});
it('has a useful default error message for not null validation failures', () => {
const User = Support.sequelize.define('user', {
name: {
type: Support.Sequelize.STRING,
allowNull: false
}
});
const instanceValidator = new InstanceValidator(User.build());
const result = instanceValidator.validate();
return 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').returns(Promise.resolve());
});
it('should run beforeValidate and afterValidate hooks when _validate is successful', function() {
const beforeValidate = sinon.spy();
const afterValidate = sinon.spy();
this.User.beforeValidate(beforeValidate);
this.User.afterValidate(afterValidate);
return expect(this.successfulInstanceValidator._validateAndRunHooks()).to.be.fulfilled.then(() => {
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', function() {
const failingInstanceValidator = new InstanceValidator(this.User.build());
sinon.stub(failingInstanceValidator, '_validate').callsFake(() => {
return Promise.reject(new Error());
});
const beforeValidate = sinon.spy();
const afterValidate = sinon.spy();
this.User.beforeValidate(beforeValidate);
this.User.afterValidate(afterValidate);
return expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected.then(() => {
expect(beforeValidate).to.have.been.calledOnce;
expect(afterValidate).to.not.have.been.called;
});
});
it('should emit an error from after hook when afterValidate fails', function() {
this.User.afterValidate(() => {
throw new Error('after validation error');
});
return expect(this.successfulInstanceValidator._validateAndRunHooks()).to.be.rejectedWith('after validation error');
});
describe('validatedFailed hook', () => {
it('should call validationFailed hook when validation fails', function() {
const failingInstanceValidator = new InstanceValidator(this.User.build());
sinon.stub(failingInstanceValidator, '_validate').callsFake(() => {
return Promise.reject(new Error());
});
const validationFailedHook = sinon.spy();
this.User.validationFailed(validationFailedHook);
return expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected.then(() => {
expect(validationFailedHook).to.have.been.calledOnce;
});
});
it('should not replace the validation error in validationFailed hook by default', function() {
const failingInstanceValidator = new InstanceValidator(this.User.build());
sinon.stub(failingInstanceValidator, '_validate').callsFake(() => {
return Promise.reject(new SequelizeValidationError());
});
const validationFailedHook = sinon.stub().returns(Promise.resolve());
this.User.validationFailed(validationFailedHook);
return expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected.then(err => {
expect(err.name).to.equal('SequelizeValidationError');
});
});
it('should replace the validation error if validationFailed hook creates a new error', function() {
const failingInstanceValidator = new InstanceValidator(this.User.build());
sinon.stub(failingInstanceValidator, '_validate').callsFake(() => {
return Promise.reject(new SequelizeValidationError());
});
const validationFailedHook = sinon.stub().throws(new Error('validation failed hook error'));
this.User.validationFailed(validationFailedHook);
return expect(failingInstanceValidator._validateAndRunHooks()).to.be.rejected.then(err => {
expect(err.message).to.equal('validation failed hook error');
});
});
});
});
});