@e22m4u/js-repository 0.8.3 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,544 @@
1
+ import {expect} from 'chai';
2
+ import {DataType} from './data-type.js';
3
+ import {format} from '@e22m4u/js-format';
4
+ import {DatabaseSchema} from '../../../database-schema.js';
5
+ import {RequiredPropertyValidator} from './required-property-validator.js';
6
+
7
+ describe('RequiredPropertyValidator', function () {
8
+ describe('validate', function () {
9
+ it('should require the parameter "modelName" to be a non-empty String', function () {
10
+ const dbs = new DatabaseSchema();
11
+ const S = dbs.getService(RequiredPropertyValidator);
12
+ dbs.defineModel({name: 'model'});
13
+ const throwable = v => () => S.validate(v, {});
14
+ const error = s =>
15
+ format(
16
+ 'Parameter "modelName" must be a non-empty String, but %s was given.',
17
+ s,
18
+ );
19
+ expect(throwable('')).to.throw(error('""'));
20
+ expect(throwable(10)).to.throw(error('10'));
21
+ expect(throwable(0)).to.throw(error('0'));
22
+ expect(throwable(true)).to.throw(error('true'));
23
+ expect(throwable(false)).to.throw(error('false'));
24
+ expect(throwable([])).to.throw(error('Array'));
25
+ expect(throwable({})).to.throw(error('Object'));
26
+ expect(throwable(undefined)).to.throw(error('undefined'));
27
+ expect(throwable(null)).to.throw(error('null'));
28
+ throwable('model')();
29
+ });
30
+
31
+ it('should require the parameter "modelData" to be an Object', function () {
32
+ const dbs = new DatabaseSchema();
33
+ const S = dbs.getService(RequiredPropertyValidator);
34
+ dbs.defineModel({name: 'model'});
35
+ const throwable = v => () => S.validate('model', v);
36
+ const error = s =>
37
+ format(
38
+ 'Data of the model "model" should be an Object, but %s was given.',
39
+ s,
40
+ );
41
+ expect(throwable('str')).to.throw(error('"str"'));
42
+ expect(throwable('')).to.throw(error('""'));
43
+ expect(throwable(10)).to.throw(error('10'));
44
+ expect(throwable(0)).to.throw(error('0'));
45
+ expect(throwable(true)).to.throw(error('true'));
46
+ expect(throwable(false)).to.throw(error('false'));
47
+ expect(throwable([])).to.throw(error('Array'));
48
+ expect(throwable(undefined)).to.throw(error('undefined'));
49
+ expect(throwable(null)).to.throw(error('null'));
50
+ throwable({})();
51
+ });
52
+
53
+ it('should require the parameter "isPartial" to be an Object', function () {
54
+ const dbs = new DatabaseSchema();
55
+ const S = dbs.getService(RequiredPropertyValidator);
56
+ dbs.defineModel({name: 'model'});
57
+ const throwable = v => () => S.validate('model', {}, v);
58
+ const error = s =>
59
+ format('Parameter "isPartial" must be a Boolean, but %s was given.', s);
60
+ expect(throwable('str')).to.throw(error('"str"'));
61
+ expect(throwable('')).to.throw(error('""'));
62
+ expect(throwable(10)).to.throw(error('10'));
63
+ expect(throwable(0)).to.throw(error('0'));
64
+ expect(throwable([])).to.throw(error('Array'));
65
+ expect(throwable({})).to.throw(error('Object'));
66
+ expect(throwable(null)).to.throw(error('null'));
67
+ throwable(true)();
68
+ throwable(false)();
69
+ throwable(undefined)();
70
+ });
71
+
72
+ it('should not throw an error if no properties in the model definition', function () {
73
+ const dbs = new DatabaseSchema();
74
+ const S = dbs.getService(RequiredPropertyValidator);
75
+ dbs.defineModel({name: 'model'});
76
+ S.validate('model', {foo: 'bar', baz: undefined});
77
+ });
78
+
79
+ it('should not throw an error if the property definition in short form', function () {
80
+ const dbs = new DatabaseSchema();
81
+ const S = dbs.getService(RequiredPropertyValidator);
82
+ dbs.defineModel({name: 'model', properties: {foo: DataType.STRING}});
83
+ S.validate('model', {foo: 'bar'});
84
+ });
85
+
86
+ it('should not throw an error if a required property is defined', function () {
87
+ const dbs = new DatabaseSchema();
88
+ const S = dbs.getService(RequiredPropertyValidator);
89
+ dbs.defineModel({
90
+ name: 'model',
91
+ properties: {
92
+ foo: {
93
+ type: DataType.STRING,
94
+ required: true,
95
+ },
96
+ },
97
+ });
98
+ S.validate('model', {foo: 'bar'});
99
+ });
100
+
101
+ it('should throw an error if a required property is undefined', function () {
102
+ const dbs = new DatabaseSchema();
103
+ const S = dbs.getService(RequiredPropertyValidator);
104
+ dbs.defineModel({
105
+ name: 'model',
106
+ properties: {
107
+ foo: {
108
+ type: DataType.STRING,
109
+ required: true,
110
+ },
111
+ },
112
+ });
113
+ const throwable = () => S.validate('model', {foo: undefined});
114
+ expect(throwable).to.throw(
115
+ 'Property "foo" of the model "model" is required, ' +
116
+ 'but undefined was given.',
117
+ );
118
+ });
119
+
120
+ describe('embedded model', function () {
121
+ it('should not throw an error if no data is provided for an embedded model', function () {
122
+ const dbs = new DatabaseSchema();
123
+ const S = dbs.getService(RequiredPropertyValidator);
124
+ dbs.defineModel({
125
+ name: 'modelA',
126
+ properties: {
127
+ embedded: {
128
+ type: DataType.OBJECT,
129
+ model: 'modelB',
130
+ },
131
+ },
132
+ });
133
+ dbs.defineModel({
134
+ name: 'modelB',
135
+ properties: {
136
+ foo: {
137
+ type: DataType.STRING,
138
+ },
139
+ },
140
+ });
141
+ S.validate('modelA', {embedded: undefined});
142
+ });
143
+
144
+ it('should throw an error if an embedded model is required but not provided', function () {
145
+ const dbs = new DatabaseSchema();
146
+ const S = dbs.getService(RequiredPropertyValidator);
147
+ dbs.defineModel({
148
+ name: 'modelA',
149
+ properties: {
150
+ embedded: {
151
+ type: DataType.OBJECT,
152
+ model: 'modelB',
153
+ required: true,
154
+ },
155
+ },
156
+ });
157
+ dbs.defineModel({
158
+ name: 'modelB',
159
+ properties: {
160
+ foo: {
161
+ type: DataType.STRING,
162
+ },
163
+ },
164
+ });
165
+ const throwable = () => S.validate('modelA', {embedded: undefined});
166
+ expect(throwable).to.throw(
167
+ 'Property "embedded" of the model "modelA" is required, ' +
168
+ 'but undefined was given.',
169
+ );
170
+ });
171
+
172
+ it('should allow a model data to have properties without a specified schema', function () {
173
+ const dbs = new DatabaseSchema();
174
+ const S = dbs.getService(RequiredPropertyValidator);
175
+ dbs.defineModel({
176
+ name: 'modelA',
177
+ properties: {
178
+ embedded: {
179
+ type: DataType.OBJECT,
180
+ model: 'modelB',
181
+ },
182
+ },
183
+ });
184
+ dbs.defineModel({
185
+ name: 'modelB',
186
+ properties: {
187
+ foo: {
188
+ type: DataType.STRING,
189
+ },
190
+ },
191
+ });
192
+ S.validate('modelA', {embedded: {bar: 'baz', qux: undefined}});
193
+ });
194
+
195
+ it('should allow omit a model data when its model has a required property', function () {
196
+ const dbs = new DatabaseSchema();
197
+ const S = dbs.getService(RequiredPropertyValidator);
198
+ dbs.defineModel({
199
+ name: 'modelA',
200
+ properties: {
201
+ embedded: {
202
+ type: DataType.OBJECT,
203
+ model: 'modelB',
204
+ },
205
+ },
206
+ });
207
+ dbs.defineModel({
208
+ name: 'modelB',
209
+ properties: {
210
+ foo: {
211
+ type: DataType.STRING,
212
+ required: true,
213
+ },
214
+ },
215
+ });
216
+ S.validate('modelA', {embedded: undefined});
217
+ });
218
+
219
+ it('should allow omit an optional property for an embedded model', function () {
220
+ const dbs = new DatabaseSchema();
221
+ const S = dbs.getService(RequiredPropertyValidator);
222
+ dbs.defineModel({
223
+ name: 'modelA',
224
+ properties: {
225
+ embedded: {
226
+ type: DataType.OBJECT,
227
+ model: 'modelB',
228
+ },
229
+ },
230
+ });
231
+ dbs.defineModel({
232
+ name: 'modelB',
233
+ properties: {
234
+ foo: {
235
+ type: DataType.STRING,
236
+ },
237
+ },
238
+ });
239
+ S.validate('modelA', {embedded: {}});
240
+ });
241
+
242
+ it('should throw an error if a required property is not provided', function () {
243
+ const dbs = new DatabaseSchema();
244
+ const S = dbs.getService(RequiredPropertyValidator);
245
+ dbs.defineModel({
246
+ name: 'modelA',
247
+ properties: {
248
+ embedded: {
249
+ type: DataType.OBJECT,
250
+ model: 'modelB',
251
+ },
252
+ },
253
+ });
254
+ dbs.defineModel({
255
+ name: 'modelB',
256
+ properties: {
257
+ foo: {
258
+ type: DataType.STRING,
259
+ required: true,
260
+ },
261
+ },
262
+ });
263
+ const throwable = () => S.validate('modelA', {embedded: {}});
264
+ expect(throwable).to.throw(
265
+ 'Property "foo" of the model "modelB" is required, ' +
266
+ 'but undefined was given.',
267
+ );
268
+ });
269
+ });
270
+
271
+ describe('object array', function () {
272
+ it('should allow omit an optional array', function () {
273
+ const dbs = new DatabaseSchema();
274
+ const S = dbs.getService(RequiredPropertyValidator);
275
+ dbs.defineModel({
276
+ name: 'modelA',
277
+ properties: {
278
+ array: {
279
+ type: DataType.ARRAY,
280
+ itemType: DataType.OBJECT,
281
+ itemModel: 'modelB',
282
+ },
283
+ },
284
+ });
285
+ dbs.defineModel({
286
+ name: 'modelB',
287
+ properties: {
288
+ foo: {
289
+ type: DataType.STRING,
290
+ },
291
+ },
292
+ });
293
+ S.validate('modelA', {});
294
+ });
295
+
296
+ it('should allow a required array to be empty', function () {
297
+ const dbs = new DatabaseSchema();
298
+ const S = dbs.getService(RequiredPropertyValidator);
299
+ dbs.defineModel({
300
+ name: 'modelA',
301
+ properties: {
302
+ array: {
303
+ type: DataType.ARRAY,
304
+ itemType: DataType.OBJECT,
305
+ itemModel: 'modelB',
306
+ required: true,
307
+ },
308
+ },
309
+ });
310
+ dbs.defineModel({
311
+ name: 'modelB',
312
+ properties: {
313
+ foo: {
314
+ type: DataType.STRING,
315
+ },
316
+ },
317
+ });
318
+ S.validate('modelA', {array: []});
319
+ });
320
+
321
+ it('should allow omit an optional array even if an item model has a required property', function () {
322
+ const dbs = new DatabaseSchema();
323
+ const S = dbs.getService(RequiredPropertyValidator);
324
+ dbs.defineModel({
325
+ name: 'modelA',
326
+ properties: {
327
+ array: {
328
+ type: DataType.ARRAY,
329
+ itemType: DataType.OBJECT,
330
+ itemModel: 'modelB',
331
+ },
332
+ },
333
+ });
334
+ dbs.defineModel({
335
+ name: 'modelB',
336
+ properties: {
337
+ foo: {
338
+ type: DataType.STRING,
339
+ required: true,
340
+ },
341
+ },
342
+ });
343
+ S.validate('modelA', {});
344
+ });
345
+
346
+ it('should allow an empty array even if an item model has a required property', function () {
347
+ const dbs = new DatabaseSchema();
348
+ const S = dbs.getService(RequiredPropertyValidator);
349
+ dbs.defineModel({
350
+ name: 'modelA',
351
+ properties: {
352
+ array: {
353
+ type: DataType.ARRAY,
354
+ itemType: DataType.OBJECT,
355
+ itemModel: 'modelB',
356
+ },
357
+ },
358
+ });
359
+ dbs.defineModel({
360
+ name: 'modelB',
361
+ properties: {
362
+ foo: {
363
+ type: DataType.STRING,
364
+ required: true,
365
+ },
366
+ },
367
+ });
368
+ S.validate('modelA', {});
369
+ });
370
+
371
+ it('should throw an error when a required array is not provided', function () {
372
+ const dbs = new DatabaseSchema();
373
+ const S = dbs.getService(RequiredPropertyValidator);
374
+ dbs.defineModel({
375
+ name: 'modelA',
376
+ properties: {
377
+ array: {
378
+ type: DataType.ARRAY,
379
+ itemType: DataType.OBJECT,
380
+ itemModel: 'modelB',
381
+ required: true,
382
+ },
383
+ },
384
+ });
385
+ dbs.defineModel({
386
+ name: 'modelB',
387
+ properties: {
388
+ foo: {
389
+ type: DataType.STRING,
390
+ },
391
+ },
392
+ });
393
+ const throwable = () => S.validate('modelA', {});
394
+ expect(throwable).to.throw(
395
+ 'Property "array" of the model "modelA" is required, ' +
396
+ 'but undefined was given.',
397
+ );
398
+ });
399
+
400
+ it('should allow omit an optional property of the item model', function () {
401
+ const dbs = new DatabaseSchema();
402
+ const S = dbs.getService(RequiredPropertyValidator);
403
+ dbs.defineModel({
404
+ name: 'modelA',
405
+ properties: {
406
+ array: {
407
+ type: DataType.ARRAY,
408
+ itemType: DataType.OBJECT,
409
+ itemModel: 'modelB',
410
+ required: true,
411
+ },
412
+ },
413
+ });
414
+ dbs.defineModel({
415
+ name: 'modelB',
416
+ properties: {
417
+ foo: {
418
+ type: DataType.STRING,
419
+ },
420
+ },
421
+ });
422
+ S.validate('modelA', {array: [{}]});
423
+ });
424
+
425
+ it('should allow an item date to have properties without a specified schema', function () {
426
+ const dbs = new DatabaseSchema();
427
+ const S = dbs.getService(RequiredPropertyValidator);
428
+ dbs.defineModel({
429
+ name: 'modelA',
430
+ properties: {
431
+ array: {
432
+ type: DataType.ARRAY,
433
+ itemType: DataType.OBJECT,
434
+ itemModel: 'modelB',
435
+ required: true,
436
+ },
437
+ },
438
+ });
439
+ dbs.defineModel({
440
+ name: 'modelB',
441
+ properties: {
442
+ foo: {
443
+ type: DataType.STRING,
444
+ },
445
+ },
446
+ });
447
+ S.validate('modelA', {array: [{bar: 'baz', qux: undefined}]});
448
+ });
449
+ });
450
+
451
+ describe('isPartial', function () {
452
+ it('should throw an error if a required property is undefined', function () {
453
+ const dbs = new DatabaseSchema();
454
+ const S = dbs.getService(RequiredPropertyValidator);
455
+ dbs.defineModel({
456
+ name: 'model',
457
+ properties: {
458
+ foo: {
459
+ type: DataType.STRING,
460
+ required: true,
461
+ },
462
+ },
463
+ });
464
+ const throwable = () => S.validate('model', {foo: undefined}, true);
465
+ expect(throwable).to.throw(
466
+ 'Property "foo" of the model "model" is required, ' +
467
+ 'but undefined was given.',
468
+ );
469
+ });
470
+
471
+ it('should not validate required but not provided properties', function () {
472
+ const dbs = new DatabaseSchema();
473
+ const S = dbs.getService(RequiredPropertyValidator);
474
+ dbs.defineModel({
475
+ name: 'model',
476
+ properties: {
477
+ foo: {
478
+ type: DataType.STRING,
479
+ required: true,
480
+ },
481
+ },
482
+ });
483
+ S.validate('model', {}, true);
484
+ });
485
+
486
+ it('should validate not provided properties of an embedded model', function () {
487
+ const dbs = new DatabaseSchema();
488
+ const S = dbs.getService(RequiredPropertyValidator);
489
+ dbs.defineModel({
490
+ name: 'modelA',
491
+ properties: {
492
+ embedded: {
493
+ type: DataType.OBJECT,
494
+ model: 'modelB',
495
+ },
496
+ },
497
+ });
498
+ dbs.defineModel({
499
+ name: 'modelB',
500
+ properties: {
501
+ foo: {
502
+ type: DataType.STRING,
503
+ required: true,
504
+ },
505
+ },
506
+ });
507
+ const throwable = () => S.validate('modelA', {embedded: {}}, true);
508
+ expect(throwable).to.throw(
509
+ 'Property "foo" of the model "modelB" is required, ' +
510
+ 'but undefined was given.',
511
+ );
512
+ });
513
+
514
+ it('should validate not provided properties of an item model', function () {
515
+ const dbs = new DatabaseSchema();
516
+ const S = dbs.getService(RequiredPropertyValidator);
517
+ dbs.defineModel({
518
+ name: 'modelA',
519
+ properties: {
520
+ array: {
521
+ type: DataType.ARRAY,
522
+ itemType: DataType.OBJECT,
523
+ itemModel: 'modelB',
524
+ },
525
+ },
526
+ });
527
+ dbs.defineModel({
528
+ name: 'modelB',
529
+ properties: {
530
+ foo: {
531
+ type: DataType.STRING,
532
+ required: true,
533
+ },
534
+ },
535
+ });
536
+ const throwable = () => S.validate('modelA', {array: [{}]}, true);
537
+ expect(throwable).to.throw(
538
+ 'Property "foo" of the model "modelB" is required, ' +
539
+ 'but undefined was given.',
540
+ );
541
+ });
542
+ });
543
+ });
544
+ });