UNPKG

22.4 kBJavaScriptView Raw
1// Copyright IBM Corp. 2015,2019. All Rights Reserved.
2// Node module: loopback-datasource-juggler
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6// This test written in mocha+should.js
7'use strict';
8
9/* global getSchema:false */
10const async = require('async');
11const should = require('./init.js');
12let db, User, options, ModelWithForceId, whereCount = 0;
13const j = require('../');
14const ValidationError = j.ValidationError;
15
16const INITIAL_NAME = 'Bert';
17const NEW_NAME = 'Ernie';
18const INVALID_DATA = {name: null};
19const VALID_DATA = {name: INITIAL_NAME};
20
21describe('optional-validation', function() {
22 before(function(done) {
23 db = getSchema();
24 ModelWithForceId = db.createModel(
25 'ModelWithForceId',
26 {name: String},
27 {forceId: true},
28 );
29 User = db.define('User', {
30 seq: {type: Number, index: true},
31 name: {type: String, index: true, sort: true},
32 email: {type: String, index: true},
33 birthday: {type: Date, index: true},
34 role: {type: String, index: true},
35 order: {type: Number, index: true, sort: true},
36 vip: {type: Boolean},
37 }, {forceId: true, strict: true});
38 db.automigrate(['ModelWithForceId', 'User'], done);
39 });
40
41 beforeEach(function(done) {
42 User.destroyAll(function() {
43 delete User.validations;
44 User.validatesPresenceOf('name');
45 done();
46 });
47 });
48
49 function expectValidationError(done) {
50 return function(err, result) {
51 should.exist(err);
52 err.should.be.instanceOf(Error);
53 err.should.be.instanceOf(ValidationError);
54 done();
55 };
56 }
57
58 function expectCreateSuccess(data, done) {
59 if (done === undefined && typeof data === 'function') {
60 done = data;
61 data = {name: INITIAL_NAME};
62 }
63 return function(err, instance) {
64 if (err) return done(err);
65 instance.should.be.instanceOf(User);
66 if (data.name) {
67 instance.name.should.eql(data.name || INITIAL_NAME);
68 } else {
69 should.not.exist(instance.name);
70 }
71 done();
72 };
73 }
74
75 function expectChangeSuccess(data, done) {
76 if (done === undefined && typeof data === 'function') {
77 done = data;
78 data = {name: NEW_NAME};
79 }
80 return function(err, instance) {
81 if (err) return done(err);
82 instance.should.be.instanceOf(User);
83 if (data.name) {
84 instance.name.should.eql(data.name || NEW_NAME);
85 } else {
86 should.not.exist(instance.name);
87 }
88 done();
89 };
90 }
91
92 function createUserAndChangeName(name, cb) {
93 User.create(VALID_DATA, {validate: true}, function(err, d) {
94 d.name = name;
95 cb(err, d);
96 });
97 }
98
99 function createUser(cb) {
100 User.create(VALID_DATA, {validate: true}, cb);
101 }
102
103 function callUpdateOrCreateWithExistingUserId(name, options, cb) {
104 User.create({'name': 'Groover'}, function(err, user) {
105 if (err) return cb(err);
106 const data = {name: name};
107 data.id = user.id;
108 User.updateOrCreate(data, options, cb);
109 });
110 }
111
112 function getNewWhere() {
113 return {name: 'DoesNotExist' + (whereCount++)};
114 }
115
116 describe('forceId', function() {
117 context('replaceAttributes', function() {
118 it('should not fail if you do not pass the Primary key in data object',
119 function(done) {
120 ModelWithForceId.create({name: 'foo'}, function(err, created) {
121 if (err) return done(err);
122 created.replaceAttributes({name: 'bar'}, function(err, data) {
123 done(err);
124 });
125 });
126 });
127
128 it('should fail if you pass the Primary key in data object',
129 function(done) {
130 ModelWithForceId.create({name: 'foo'}, function(err, created) {
131 if (err) return done(err);
132 created.replaceAttributes({name: 'bar', id: 999},
133 function(err, data) {
134 should.exist(err);
135 done();
136 });
137 });
138 });
139 });
140 });
141
142 describe('no model setting', function() {
143 describe('method create', function() {
144 it('should throw on create with validate:true with invalid data', function(done) {
145 User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
146 });
147
148 it('should NOT throw on create with validate:false with invalid data', function(done) {
149 User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
150 });
151
152 it('should NOT throw on create with validate:true with valid data', function(done) {
153 User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
154 });
155
156 it('should NOT throw on create with validate:false with valid data', function(done) {
157 User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
158 });
159
160 it('should throw on create with invalid data', function(done) {
161 User.create(INVALID_DATA, expectValidationError(done));
162 });
163
164 it('should NOT throw on create with valid data', function(done) {
165 User.create(VALID_DATA, expectCreateSuccess(done));
166 });
167 });
168
169 describe('method findOrCreate', function() {
170 it('should throw on findOrCreate with validate:true with invalid data',
171 function(done) {
172 User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
173 expectValidationError(done));
174 });
175
176 it('should NOT throw on findOrCreate with validate:false with invalid data',
177 function(done) {
178 User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
179 expectCreateSuccess(INVALID_DATA, done));
180 });
181
182 it('should NOT throw on findOrCreate with validate:true with valid data',
183 function(done) {
184 User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
185 expectCreateSuccess(done));
186 });
187
188 it('should NOT throw on findOrCreate with validate:false with valid data',
189 function(done) {
190 User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
191 expectCreateSuccess(done));
192 });
193
194 it('should throw on findOrCreate with invalid data', function(done) {
195 User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done));
196 });
197
198 it('should NOT throw on findOrCreate with valid data', function(done) {
199 User.findOrCreate(getNewWhere(), VALID_DATA, expectCreateSuccess(done));
200 });
201 });
202
203 describe('method updateOrCreate on existing data', function() {
204 it('should throw on updateOrCreate(id) with validate:true with invalid data',
205 function(done) {
206 callUpdateOrCreateWithExistingUserId(null, {validate: true},
207 expectValidationError(done));
208 });
209
210 it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
211 function(done) {
212 callUpdateOrCreateWithExistingUserId(null, {validate: false},
213 expectChangeSuccess(INVALID_DATA, done));
214 });
215
216 it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
217 function(done) {
218 callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
219 expectChangeSuccess(done));
220 });
221
222 it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
223 function(done) {
224 callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
225 expectChangeSuccess(done));
226 });
227
228 // backwards compatible with validateUpsert
229 it('should NOT throw on updateOrCreate(id) with invalid data', function(done) {
230 callUpdateOrCreateWithExistingUserId(null, expectChangeSuccess(INVALID_DATA, done));
231 });
232
233 it('should NOT throw on updateOrCreate(id) with valid data', function(done) {
234 callUpdateOrCreateWithExistingUserId(NEW_NAME, expectChangeSuccess(done));
235 });
236 });
237
238 describe('method save', function() {
239 it('should throw on save with {validate:true} with invalid data', function(done) {
240 createUserAndChangeName(null, function(err, d) {
241 d.save({validate: true}, expectValidationError(done));
242 });
243 });
244
245 it('should NOT throw on save with {validate:false} with invalid data', function(done) {
246 createUserAndChangeName(null, function(err, d) {
247 d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
248 });
249 });
250
251 it('should NOT throw on save with {validate:true} with valid data', function(done) {
252 createUserAndChangeName(NEW_NAME, function(err, d) {
253 d.save({validate: true}, expectChangeSuccess(done));
254 });
255 });
256
257 it('should NOT throw on save with {validate:false} with valid data', function(done) {
258 createUserAndChangeName(NEW_NAME, function(err, d) {
259 d.save({validate: false}, expectChangeSuccess(done));
260 });
261 });
262
263 it('should throw on save(cb) with invalid data', function(done) {
264 createUserAndChangeName(null, function(err, d) {
265 d.save(expectValidationError(done));
266 });
267 });
268
269 it('should NOT throw on save(cb) with valid data', function(done) {
270 createUserAndChangeName(NEW_NAME, function(err, d) {
271 d.save(expectChangeSuccess(done));
272 });
273 });
274 });
275
276 describe('method updateAttributes', function() {
277 it('should throw on updateAttributes with {validate:true} with invalid data', function(done) {
278 createUser(function(err, d) {
279 d.updateAttributes(INVALID_DATA, {validate: true}, expectValidationError(done));
280 });
281 });
282
283 it('should NOT throw on updateAttributes with {validate:false} with invalid data', function(done) {
284 createUser(function(err, d) {
285 d.updateAttributes(INVALID_DATA, {validate: false}, expectChangeSuccess(INVALID_DATA, done));
286 });
287 });
288
289 it('should NOT throw on updateAttributes with {validate:true} with valid data', function(done) {
290 createUser(function(err, d) {
291 d.updateAttributes({'name': NEW_NAME}, {validate: true}, expectChangeSuccess(done));
292 });
293 });
294
295 it('should NOT throw on updateAttributes with {validate:false} with valid data', function(done) {
296 createUser(function(err, d) {
297 d.updateAttributes({'name': NEW_NAME}, {validate: false}, expectChangeSuccess(done));
298 });
299 });
300
301 it('should throw on updateAttributes(cb) with invalid data', function(done) {
302 createUser(function(err, d) {
303 d.updateAttributes(INVALID_DATA, expectValidationError(done));
304 });
305 });
306
307 it('should NOT throw on updateAttributes(cb) with valid data', function(done) {
308 createUser(function(err, d) {
309 d.updateAttributes({'name': NEW_NAME}, expectChangeSuccess(done));
310 });
311 });
312
313 it('returns an error when trying to update the id property when forceId is set to true',
314 function(done) {
315 ModelWithForceId.create({name: 'foo'}, function(err, model) {
316 if (err) return done(err);
317 model.updateAttributes({id: 123}, function(err) {
318 err.should.be.instanceOf(Error);
319 err.message.should.eql('id cannot be updated from ' + model.id +
320 ' to 123 when forceId is set to true');
321 done();
322 });
323 });
324 });
325 });
326 });
327
328 describe('model setting: automaticValidation: false', function() {
329 before(function(done) {
330 User.settings.automaticValidation = false;
331 done();
332 });
333
334 describe('method create', function() {
335 it('should throw on create with validate:true with invalid data', function(done) {
336 User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
337 });
338
339 it('should NOT throw on create with validate:false with invalid data', function(done) {
340 User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
341 });
342
343 it('should NOT throw on create with validate:true with valid data', function(done) {
344 User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
345 });
346
347 it('should NOT throw on create with validate:false with valid data', function(done) {
348 User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
349 });
350
351 it('should NOT throw on create with invalid data', function(done) {
352 User.create(INVALID_DATA, expectCreateSuccess(INVALID_DATA, done));
353 });
354
355 it('should NOT throw on create with valid data', function(done) {
356 User.create(VALID_DATA, expectCreateSuccess(done));
357 });
358 });
359
360 describe('method findOrCreate', function() {
361 it('should throw on findOrCreate with validate:true with invalid data',
362 function(done) {
363 User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
364 expectValidationError(done));
365 });
366
367 it('should NOT throw on findOrCreate with validate:false with invalid data',
368 function(done) {
369 User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
370 expectCreateSuccess(INVALID_DATA, done));
371 });
372
373 it('should NOT throw on findOrCreate with validate:true with valid data',
374 function(done) {
375 User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
376 expectCreateSuccess(done));
377 });
378
379 it('should NOT throw on findOrCreate with validate:false with valid data',
380 function(done) {
381 User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
382 expectCreateSuccess(done));
383 });
384
385 it('should NOT throw on findOrCreate with invalid data', function(done) {
386 User.findOrCreate(getNewWhere(), INVALID_DATA,
387 expectCreateSuccess(INVALID_DATA, done));
388 });
389
390 it('should NOT throw on findOrCreate with valid data', function(done) {
391 User.findOrCreate(getNewWhere(), VALID_DATA, expectCreateSuccess(done));
392 });
393 });
394
395 describe('method updateOrCreate on existing data', function() {
396 it('should throw on updateOrCreate(id) with validate:true with invalid data',
397 function(done) {
398 callUpdateOrCreateWithExistingUserId(null, {validate: true},
399 expectValidationError(done));
400 });
401
402 it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
403 function(done) {
404 callUpdateOrCreateWithExistingUserId(null, {validate: false},
405 expectChangeSuccess(INVALID_DATA, done));
406 });
407
408 it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
409 function(done) {
410 callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
411 expectChangeSuccess(done));
412 });
413
414 it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
415 function(done) {
416 callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
417 expectChangeSuccess(done));
418 });
419
420 it('should NOT throw on updateOrCreate(id) with invalid data', function(done) {
421 callUpdateOrCreateWithExistingUserId(null, expectChangeSuccess(INVALID_DATA, done));
422 });
423
424 it('should NOT throw on updateOrCreate(id) with valid data', function(done) {
425 callUpdateOrCreateWithExistingUserId(NEW_NAME, expectChangeSuccess(done));
426 });
427 });
428
429 describe('method save', function() {
430 it('should throw on save with {validate:true} with invalid data', function(done) {
431 createUserAndChangeName(null, function(err, d) {
432 d.save({validate: true}, expectValidationError(done));
433 });
434 });
435
436 it('should NOT throw on save with {validate:false} with invalid data', function(done) {
437 createUserAndChangeName(null, function(err, d) {
438 d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
439 });
440 });
441
442 it('should NOT throw on save with {validate:true} with valid data', function(done) {
443 createUserAndChangeName(NEW_NAME, function(err, d) {
444 d.save({validate: true}, expectChangeSuccess(done));
445 });
446 });
447
448 it('should NOT throw on save with {validate:false} with valid data', function(done) {
449 createUserAndChangeName(NEW_NAME, function(err, d) {
450 d.save({validate: false}, expectChangeSuccess(done));
451 });
452 });
453
454 it('should NOT throw on save(cb) with invalid data', function(done) {
455 createUserAndChangeName(null, function(err, d) {
456 d.save(expectChangeSuccess(INVALID_DATA, done));
457 });
458 });
459
460 it('should NOT throw on save(cb) with valid data', function(done) {
461 createUserAndChangeName(NEW_NAME, function(err, d) {
462 d.save(expectChangeSuccess(done));
463 });
464 });
465 });
466 });
467
468 describe('model setting: automaticValidation: true', function() {
469 before(function(done) {
470 User.settings.automaticValidation = true;
471 done();
472 });
473
474 describe('method create', function() {
475 it('should throw on create with validate:true with invalid data', function(done) {
476 User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
477 });
478
479 it('should NOT throw on create with validate:false with invalid data', function(done) {
480 User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
481 });
482
483 it('should NOT throw on create with validate:true with valid data', function(done) {
484 User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
485 });
486
487 it('should NOT throw on create with validate:false with valid data', function(done) {
488 User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
489 });
490
491 it('should throw on create with invalid data', function(done) {
492 User.create(INVALID_DATA, expectValidationError(done));
493 });
494
495 it('should NOT throw on create with valid data', function(done) {
496 User.create(VALID_DATA, expectCreateSuccess(done));
497 });
498 });
499
500 describe('method findOrCreate', function() {
501 it('should throw on findOrCreate with validate:true with invalid data',
502 function(done) {
503 User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
504 expectValidationError(done));
505 });
506
507 it('should NOT throw on findOrCreate with validate:false with invalid data',
508 function(done) {
509 User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
510 expectCreateSuccess(INVALID_DATA, done));
511 });
512
513 it('should NOT throw on findOrCreate with validate:true with valid data',
514 function(done) {
515 User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
516 expectCreateSuccess(done));
517 });
518
519 it('should NOT throw on findOrCreate with validate:false with valid data',
520 function(done) {
521 User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
522 expectCreateSuccess(done));
523 });
524
525 it('should throw on findOrCreate with invalid data', function(done) {
526 User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done));
527 });
528
529 it('should NOT throw on findOrCreate with valid data', function(done) {
530 User.findOrCreate(getNewWhere(), VALID_DATA, expectCreateSuccess(done));
531 });
532 });
533
534 describe('method updateOrCreate on existing data', function() {
535 it('should throw on updateOrCreate(id) with validate:true with invalid data',
536 function(done) {
537 callUpdateOrCreateWithExistingUserId(null, {validate: true},
538 expectValidationError(done));
539 });
540
541 it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
542 function(done) {
543 callUpdateOrCreateWithExistingUserId(null, {validate: false},
544 expectChangeSuccess(INVALID_DATA, done));
545 });
546
547 it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
548 function(done) {
549 callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
550 expectChangeSuccess(done));
551 });
552
553 it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
554 function(done) {
555 callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
556 expectChangeSuccess(done));
557 });
558
559 it('should throw on updateOrCreate(id) with invalid data', function(done) {
560 callUpdateOrCreateWithExistingUserId(null, expectValidationError(done));
561 });
562
563 it('should NOT throw on updateOrCreate(id) with valid data', function(done) {
564 callUpdateOrCreateWithExistingUserId(NEW_NAME, expectChangeSuccess(done));
565 });
566 });
567
568 describe('method save', function() {
569 it('should throw on save with {validate:true} with invalid data', function(done) {
570 createUserAndChangeName(null, function(err, d) {
571 d.save(options, expectValidationError(done));
572 });
573 });
574
575 it('should NOT throw on save with {validate:false} with invalid data', function(done) {
576 createUserAndChangeName(null, function(err, d) {
577 d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
578 });
579 });
580
581 it('should NOT throw on save with {validate:true} with valid data', function(done) {
582 createUserAndChangeName(NEW_NAME, function(err, d) {
583 d.save({validate: true}, expectChangeSuccess(done));
584 });
585 });
586
587 it('should NOT throw on save with {validate:false} with valid data', function(done) {
588 createUserAndChangeName(NEW_NAME, function(err, d) {
589 d.save({validate: false}, expectChangeSuccess(done));
590 });
591 });
592
593 it('should throw on save(cb) with invalid data', function(done) {
594 createUserAndChangeName(null, function(err, d) {
595 d.save(expectValidationError(done));
596 });
597 });
598
599 it('should NOT throw on save(cb) with valid data', function(done) {
600 createUserAndChangeName(NEW_NAME, function(err, d) {
601 d.save(expectChangeSuccess(done));
602 });
603 });
604 });
605 });
606});