@builder6/query-mongodb 0.6.1

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,960 @@
1
+ 'use strict';
2
+
3
+ var chai = require('chai');
4
+ var expect = chai.expect;
5
+ var qs = require('qs');
6
+
7
+ var _require = require('./options'),
8
+ getOptions = _require.getOptions,
9
+ _require$private = _require.private,
10
+ fixFilterAndSearch = _require$private.fixFilterAndSearch,
11
+ validateAll = _require$private.validateAll,
12
+ check = _require$private.check,
13
+ takeOptions = _require$private.takeOptions,
14
+ skipOptions = _require$private.skipOptions,
15
+ totalCountOptions = _require$private.totalCountOptions,
16
+ sortOptions = _require$private.sortOptions,
17
+ groupOptions = _require$private.groupOptions,
18
+ totalSummaryOptions = _require$private.totalSummaryOptions,
19
+ filterOptions = _require$private.filterOptions,
20
+ searchOptions = _require$private.searchOptions,
21
+ selectOptions = _require$private.selectOptions,
22
+ sortOptionsChecker = _require$private.sortOptionsChecker,
23
+ groupOptionsChecker = _require$private.groupOptionsChecker,
24
+ summaryOptionsChecker = _require$private.summaryOptionsChecker,
25
+ asBool = _require$private.asBool,
26
+ parse = _require$private.parse;
27
+
28
+ function testOptions(queryString, expectedResult, schema) {
29
+ var result = getOptions(qs.parse(queryString), schema);
30
+
31
+
32
+ expect(result).to.eql(expectedResult);
33
+ }
34
+
35
+ suite('parse', function () {
36
+ test('parse correctly', function () {
37
+ var source = { test: 'text', test2: 42 };
38
+ expect(parse(JSON.stringify(source))).to.eql(source);
39
+ });
40
+
41
+ test('parse error', function () {
42
+ var sourceText = '{"field1":"thing",error:true}';
43
+ try {
44
+ parse(sourceText);
45
+ throw new Error('parse did not throw!');
46
+ } catch (e) {
47
+ expect(JSON.stringify(e)).to.not.eql('{}');
48
+ }
49
+ });
50
+ });
51
+
52
+ suite('asBool', function () {
53
+ test('true', function () {
54
+ expect(asBool(true)).to.be.true;
55
+ });
56
+
57
+ test('false', function () {
58
+ expect(asBool(false)).to.be.false;
59
+ });
60
+
61
+ test('true string', function () {
62
+ expect(asBool('TrUe')).to.be.true;
63
+ });
64
+
65
+ test('false string', function () {
66
+ expect(asBool('FaLsE')).to.be.false;
67
+ });
68
+
69
+ test('thruthy number', function () {
70
+ expect(asBool(7)).to.be.true;
71
+ });
72
+
73
+ test('falsy number', function () {
74
+ expect(asBool(0)).to.be.false;
75
+ });
76
+
77
+ test('thruthy string', function () {
78
+ expect(asBool('something')).to.be.true;
79
+ });
80
+
81
+ test('falsy string', function () {
82
+ expect(asBool('')).to.be.false;
83
+ });
84
+ });
85
+
86
+ suite('summaryOptionsChecker', function () {
87
+ test('valid', function () {
88
+ var result = summaryOptionsChecker.validate({
89
+ summaryType: 'sum',
90
+ selector: 'thing'
91
+ });
92
+ expect(result).to.eql(null);
93
+ });
94
+
95
+ test('extra prop', function () {
96
+ var result = summaryOptionsChecker.validate({
97
+ summaryType: 'sum',
98
+ selector: 'thing',
99
+ extra: 'thing'
100
+ });
101
+ expect(result).to.include({ name: 'ValidationError', type: 'noUnknown' });
102
+ });
103
+
104
+ test('invalid summaryType', function () {
105
+ var result = summaryOptionsChecker.validate({
106
+ summaryType: 'unknown',
107
+ selector: 'thing'
108
+ });
109
+ expect(result).to.include({ name: 'ValidationError', type: 'oneOf' });
110
+ });
111
+
112
+ test('invalid selector', function () {
113
+ var result = summaryOptionsChecker.validate({
114
+ summaryType: 'sum',
115
+ selector: true
116
+ });
117
+ expect(result).to.include({ name: 'ValidationError', type: 'typeError' });
118
+ });
119
+ });
120
+
121
+ suite('groupOptionsChecker', function () {
122
+ test('valid', function () {
123
+ var result = groupOptionsChecker.validate({
124
+ selector: 'thing',
125
+ desc: true,
126
+ isExpanded: true,
127
+ groupInterval: 'year'
128
+ });
129
+ expect(result).to.eql(null);
130
+ });
131
+
132
+ test('valid with groupInterval integer', function () {
133
+ var result = groupOptionsChecker.validate({
134
+ selector: 'thing',
135
+ desc: true,
136
+ isExpanded: true,
137
+ groupInterval: 11
138
+ });
139
+ expect(result).to.eql(null);
140
+ });
141
+
142
+ test('extra prop', function () {
143
+ var result = groupOptionsChecker.validate({
144
+ selector: 'thing',
145
+ desc: true,
146
+ isExpanded: true,
147
+ groupInterval: 'year',
148
+ extra: 'thing'
149
+ });
150
+ expect(result).to.include({ name: 'ValidationError', type: 'noUnknown' });
151
+ });
152
+
153
+ test('missing selector', function () {
154
+ var result = groupOptionsChecker.validate({
155
+ desc: true,
156
+ isExpanded: true,
157
+ groupInterval: 'year'
158
+ });
159
+ expect(result).to.include({ name: 'ValidationError', type: 'optionality' });
160
+ });
161
+
162
+ test('invalid desc', function () {
163
+ var result = groupOptionsChecker.validate({
164
+ selector: 'thing',
165
+ desc: 42,
166
+ isExpanded: true,
167
+ groupInterval: 'year'
168
+ });
169
+ expect(result).to.include({ name: 'ValidationError', type: 'typeError' });
170
+ });
171
+
172
+ test('invalid selector', function () {
173
+ var result = groupOptionsChecker.validate({
174
+ selector: 42,
175
+ desc: true,
176
+ isExpanded: true,
177
+ groupInterval: 'year'
178
+ });
179
+ expect(result).to.include({ name: 'ValidationError', type: 'typeError' });
180
+ });
181
+
182
+ test('invalid isExpanded', function () {
183
+ var result = groupOptionsChecker.validate({
184
+ selector: 'thing',
185
+ desc: true,
186
+ isExpanded: 42,
187
+ groupInterval: 'year'
188
+ });
189
+ expect(result).to.include({ name: 'ValidationError', type: 'typeError' });
190
+ });
191
+
192
+ test('invalid groupInterval - not string or number', function () {
193
+ var result = groupOptionsChecker.validate({
194
+ selector: 'thing',
195
+ desc: true,
196
+ isExpanded: true,
197
+ groupInterval: true
198
+ });
199
+ expect(result).to.include({ name: 'ValidationError', type: 'or' });
200
+ });
201
+
202
+ test('invalid groupInterval - not string or integer', function () {
203
+ var result = groupOptionsChecker.validate({
204
+ selector: 'thing',
205
+ desc: true,
206
+ isExpanded: true,
207
+ groupInterval: 10.3
208
+ });
209
+ expect(result).to.include({ name: 'ValidationError', type: 'or' });
210
+ });
211
+
212
+ test('invalid groupInterval - invalid string', function () {
213
+ var result = groupOptionsChecker.validate({
214
+ selector: 'thing',
215
+ desc: true,
216
+ isExpanded: true,
217
+ groupInterval: 'wrong string'
218
+ });
219
+ expect(result).to.include({ name: 'ValidationError', type: 'or' });
220
+ });
221
+ });
222
+
223
+ suite('sortOptionsChecker', function () {
224
+ test('missing desc', function () {
225
+ var result = sortOptionsChecker.validate({ selector: 'thing' });
226
+ expect(result).to.include({ name: 'ValidationError', type: 'optionality' });
227
+ });
228
+
229
+ test('missing selector', function () {
230
+ var result = sortOptionsChecker.validate({ desc: true });
231
+ expect(result).to.include({ name: 'ValidationError', type: 'optionality' });
232
+ });
233
+
234
+ test('valid', function () {
235
+ var result = sortOptionsChecker.validate({
236
+ selector: 'thing',
237
+ desc: true
238
+ });
239
+ expect(result).to.eql(null);
240
+ });
241
+
242
+ test('valid with isExpanded', function () {
243
+ var result = sortOptionsChecker.validate({
244
+ selector: 'thing',
245
+ desc: true,
246
+ isExpanded: 'random thing'
247
+ });
248
+ expect(result).to.eql(null);
249
+ });
250
+
251
+ test('extra prop', function () {
252
+ var result = sortOptionsChecker.validate({
253
+ selector: 'thing',
254
+ desc: true,
255
+ extra: 'thing'
256
+ });
257
+ expect(result).to.include({ name: 'ValidationError', type: 'noUnknown' });
258
+ });
259
+
260
+ test('incorrect desc type', function () {
261
+ var result = sortOptionsChecker.validate({
262
+ selector: 'thing',
263
+ desc: 42
264
+ });
265
+
266
+ expect(result).to.include({ name: 'ValidationError', type: 'typeError' });
267
+ });
268
+
269
+ test('incorrect selector type', function () {
270
+ var result = sortOptionsChecker.validate({
271
+ selector: 42,
272
+ desc: true
273
+ });
274
+ expect(result).to.include({ name: 'ValidationError', type: 'typeError' });
275
+ });
276
+ });
277
+
278
+ suite('takeOptions', function () {
279
+ test('valid', function () {
280
+ expect(takeOptions({ take: 10 })).to.eql({ loadOptions: { take: 10 } });
281
+ });
282
+
283
+ test('valid string value', function () {
284
+ expect(takeOptions({ take: '10' })).to.eql({ loadOptions: { take: 10 } });
285
+ });
286
+
287
+ test('missing parameter', function () {
288
+ expect(takeOptions({ tk: 10 })).to.eql({});
289
+ });
290
+
291
+ test('invalid value', function () {
292
+ expect(takeOptions({ take: -10 })).to.eql({
293
+ errors: ['Invalid \'take\': -10']
294
+ });
295
+ });
296
+ });
297
+
298
+ suite('skipOptions', function () {
299
+ test('valid', function () {
300
+ expect(skipOptions({ skip: 10 })).to.eql({ loadOptions: { skip: 10 } });
301
+ });
302
+
303
+ test('valid string value', function () {
304
+ expect(skipOptions({ skip: '10' })).to.eql({ loadOptions: { skip: 10 } });
305
+ });
306
+
307
+ test('missing parameter', function () {
308
+ expect(skipOptions({ skp: 10 })).to.eql({});
309
+ });
310
+
311
+ test('invalid value', function () {
312
+ expect(skipOptions({ skip: -10 })).to.eql({
313
+ errors: ['Invalid \'skip\': -10']
314
+ });
315
+ });
316
+ });
317
+
318
+ suite('totalCountOptions', function () {
319
+ test('valid', function () {
320
+ expect(totalCountOptions({ requireTotalCount: true })).to.eql({
321
+ loadOptions: { requireTotalCount: true }
322
+ });
323
+ });
324
+
325
+ test('valid string value', function () {
326
+ expect(totalCountOptions({ requireTotalCount: 'true' })).to.eql({
327
+ loadOptions: { requireTotalCount: true }
328
+ });
329
+ });
330
+
331
+ test('missing parameter', function () {
332
+ expect(totalCountOptions({ rqtc: true })).to.eql({});
333
+ });
334
+ });
335
+
336
+ suite('sortOptions', function () {
337
+ test('invalid', function () {
338
+ var result = sortOptions({ sort: ['thing'] });
339
+ expect(result.errors[0].message).to.match(/^Sort parameter validation errors/);
340
+ });
341
+
342
+ test('empty', function () {
343
+ var result = sortOptions({ sort: [] });
344
+ expect(result).to.eql({ errors: ['Invalid \'sort\': '] });
345
+ });
346
+ });
347
+
348
+ suite('totalSummaryOptions', function () {
349
+ test('invalid', function () {
350
+ var result = totalSummaryOptions({ totalSummary: ['thing'] });
351
+ expect(result.errors[0].message).to.match(/^Total summary parameter validation errors/);
352
+ });
353
+
354
+ test('empty', function () {
355
+ var result = totalSummaryOptions({ totalSummary: [] });
356
+ expect(result).to.eql({ loadOptions: {} });
357
+ });
358
+
359
+ test('non-array', function () {
360
+ var result = totalSummaryOptions({ totalSummary: {} });
361
+ expect(result).to.eql({
362
+ errors: ['Invalid \'totalSummary\': [object Object]']
363
+ });
364
+ });
365
+ });
366
+
367
+ suite('filterOptions', function () {
368
+ test('valid array', function () {
369
+ var result = filterOptions({ filter: ['thing'] });
370
+ expect(result).to.eql({ loadOptions: { filter: ['thing'] } });
371
+ });
372
+
373
+ test('valid string', function () {
374
+ var result = filterOptions({ filter: 'thing' });
375
+ expect(result).to.eql({ loadOptions: { filter: 'thing' } });
376
+ });
377
+
378
+ test('valid string with an array inside', function () {
379
+ var result = filterOptions({ filter: '["thing"]' });
380
+ expect(result).to.eql({ loadOptions: { filter: ['thing'] } });
381
+ });
382
+
383
+ test('not string or array', function () {
384
+ var result = filterOptions({ filter: {} });
385
+ expect(result).to.eql({ errors: ['Invalid \'filter\': [object Object]'] });
386
+ });
387
+ });
388
+
389
+ suite('searchOptions', function () {
390
+ test('valid with string', function () {
391
+ var result = searchOptions({
392
+ searchExpr: 'expr',
393
+ searchOperation: '=',
394
+ searchValue: 'val'
395
+ });
396
+ expect(result).to.eql({
397
+ loadOptions: {
398
+ searchExpr: 'expr',
399
+ searchOperation: '=',
400
+ searchValue: 'val'
401
+ }
402
+ });
403
+ });
404
+
405
+ test('valid with array', function () {
406
+ var result = searchOptions({
407
+ searchExpr: ['expr1', 'expr2'],
408
+ searchOperation: '=',
409
+ searchValue: 'val'
410
+ });
411
+ expect(result).to.eql({
412
+ loadOptions: {
413
+ searchExpr: ['expr1', 'expr2'],
414
+ searchOperation: '=',
415
+ searchValue: 'val'
416
+ }
417
+ });
418
+ });
419
+
420
+ test('invalid searchExpr', function () {
421
+ var result = searchOptions({
422
+ searchExpr: 42,
423
+ searchOperation: '=',
424
+ searchValue: 'val'
425
+ });
426
+ expect(result).to.eql({
427
+ errors: ['Invalid \'searchExpr\': 42', 'Invalid \'searchOperation\': =', 'Invalid \'searchValue\': val']
428
+ });
429
+ });
430
+ });
431
+
432
+ suite('selectOptions', function () {
433
+ test('valid string', function () {
434
+ var result = selectOptions({ select: 'something' });
435
+ expect(result).to.eql({ loadOptions: { select: ['something'] } });
436
+ });
437
+
438
+ test('valid array', function () {
439
+ var result = selectOptions({ select: ['something', 'other'] });
440
+ expect(result).to.eql({ loadOptions: { select: ['something', 'other'] } });
441
+ });
442
+
443
+ test('array with invalid content', function () {
444
+ var result = selectOptions({ select: ['something', 'other', 42] });
445
+ expect(result.errors[0].message).to.match(/Select array parameter has invalid content/);
446
+ });
447
+
448
+ test('empty array', function () {
449
+ var result = selectOptions({ select: [] });
450
+ expect(result).to.eql({ loadOptions: {} });
451
+ });
452
+
453
+ test('type other than string and array', function () {
454
+ var result = selectOptions({ select: 42 });
455
+ expect(result).to.eql({ errors: ['Invalid \'select\': 42'] });
456
+ });
457
+ });
458
+
459
+ suite('groupOptions', function () {
460
+ test('invalid top level options', function () {
461
+ var result = groupOptions({ group: ['thing'] });
462
+ expect(result.errors[0].message).to.match(/^Group parameter validation errors/);
463
+ });
464
+
465
+ test('empty top level options', function () {
466
+ var result = groupOptions({ group: [] });
467
+ expect(result).to.eql({});
468
+ });
469
+
470
+ test('non-array top level options', function () {
471
+ var result = groupOptions({ group: {} });
472
+ expect(result).to.eql({ errors: ['Invalid \'group\': [object Object]'] });
473
+ });
474
+
475
+ test('invalid group summary options', function () {
476
+ var result = groupOptions({
477
+ group: [{ selector: 'x' }],
478
+ groupSummary: ['thing']
479
+ });
480
+ expect(result.errors[0].message).to.match(/^Group summary parameter validation errors/);
481
+ });
482
+
483
+ test('empty group summary options', function () {
484
+ var result = groupOptions({
485
+ group: [{ selector: 'x' }],
486
+ groupSummary: []
487
+ });
488
+ expect(result).to.eql({
489
+ errors: [],
490
+ loadOptions: { group: [{ isExpanded: false, selector: 'x' }] },
491
+ processingOptions: {}
492
+ });
493
+ });
494
+
495
+ test('non-array group summary options', function () {
496
+ var result = groupOptions({
497
+ group: [{ selector: 'x' }],
498
+ groupSummary: {}
499
+ });
500
+ expect(result).to.eql({
501
+ errors: ['Invalid \'groupSummary\': [object Object]'],
502
+ loadOptions: { group: [{ isExpanded: false, selector: 'x' }] },
503
+ processingOptions: {}
504
+ });
505
+ });
506
+ });
507
+
508
+ suite('check', function () {
509
+ test('default value for one option', function () {
510
+ expect(check({ one: 1, other: 2 }, 'nonexistent', undefined, undefined, 'default value')).to.eql('default value');
511
+ });
512
+
513
+ test('default value for multiple options', function () {
514
+ expect(check({ one: 1, other: 2 }, ['one', 'nonexistent'], undefined, undefined, 'default value')).to.eql('default value');
515
+ });
516
+
517
+ test('simple converter', function () {
518
+ expect(check({ one: 1, other: 2 }, ['one', 'other'], function (one, other) {
519
+ return {
520
+ one: one,
521
+ other: other
522
+ };
523
+ }, function (x) {
524
+ return x * 2;
525
+ })).to.eql({ loadOptions: { one: 2, other: 4 } });
526
+ });
527
+
528
+ test('checker is unhappy', function () {
529
+ expect(check({ one: 1, other: 2 }, ['one', 'other'], function () {
530
+ return undefined;
531
+ })).to.eql({ errors: ['Invalid \'one\': 1', 'Invalid \'other\': 2'] });
532
+ });
533
+
534
+ test('checker is really unhappy', function () {
535
+ expect(check({ one: 1, other: 2 }, ['one', 'other'], function () {
536
+ throw 'argh!';
537
+ })).to.eql({ errors: ['argh!'] });
538
+ });
539
+ });
540
+
541
+ suite('validateAll', function () {
542
+ test('simple short circuit test', function () {
543
+ var checker = { validate: function validate(x) {
544
+ return x > 10;
545
+ } };
546
+ expect(validateAll([5, 7, 15, 25], checker, true)).to.eql({
547
+ valid: false,
548
+ errors: [true]
549
+ });
550
+ });
551
+
552
+ test('test without short circuit', function () {
553
+ var checker = { validate: function validate(x) {
554
+ return x > 10;
555
+ } };
556
+ expect(validateAll([5, 7, 15, 25], checker, false)).to.eql({
557
+ valid: false,
558
+ errors: [true, true]
559
+ });
560
+ });
561
+ });
562
+
563
+ suite('fixFilterAndSearch', function () {
564
+ test('fixes filter int', function () {
565
+ expect(fixFilterAndSearch({
566
+ int: 'int'
567
+ })({
568
+ filter: [['int', '=', '34']]
569
+ })).to.eql({
570
+ filter: [['int', '=', 34]]
571
+ });
572
+ });
573
+
574
+ test('accepts undefined query input', function () {
575
+ expect(fixFilterAndSearch('schema')(undefined)).to.eql(undefined);
576
+ });
577
+
578
+ test('fixes search int', function () {
579
+ expect(fixFilterAndSearch({
580
+ int: 'int'
581
+ })({
582
+ searchExpr: 'int',
583
+ searchOperation: '=',
584
+ searchValue: '34'
585
+ })).to.eql({
586
+ searchExpr: 'int',
587
+ searchOperation: '=',
588
+ searchValue: 34
589
+ });
590
+ });
591
+
592
+ test('no fix for field not defined in schema', function () {
593
+ expect(fixFilterAndSearch({
594
+ int: 'int'
595
+ })({
596
+ searchExpr: 'other',
597
+ searchOperation: '=',
598
+ searchValue: '34'
599
+ })).to.eql({
600
+ searchExpr: 'other',
601
+ searchOperation: '=',
602
+ searchValue: '34'
603
+ });
604
+ });
605
+
606
+ test('fixes search expr list', function () {
607
+ expect(fixFilterAndSearch({
608
+ int: 'int'
609
+ })({
610
+ searchExpr: ['int', 'other'],
611
+ searchOperation: '=',
612
+ searchValue: '34'
613
+ })).to.eql({
614
+ searchExpr: ['int', 'other'],
615
+ searchOperation: '=',
616
+ searchValue: 34
617
+ });
618
+ });
619
+
620
+ test('no fix for expr list without schema entries', function () {
621
+ expect(fixFilterAndSearch({
622
+ int: 'int'
623
+ })({
624
+ searchExpr: ['one', 'other'],
625
+ searchOperation: '=',
626
+ searchValue: '34'
627
+ })).to.eql({
628
+ searchExpr: ['one', 'other'],
629
+ searchOperation: '=',
630
+ searchValue: '34'
631
+ });
632
+ });
633
+
634
+ test('no fix for expr thats not string or array', function () {
635
+ expect(fixFilterAndSearch({
636
+ int: 'int'
637
+ })({
638
+ searchExpr: 42,
639
+ searchOperation: '=',
640
+ searchValue: '34'
641
+ })).to.eql({
642
+ searchExpr: 42,
643
+ searchOperation: '=',
644
+ searchValue: '34'
645
+ });
646
+ });
647
+ });
648
+
649
+ suite('getOptions', function () {
650
+ test('take and total count', function () {
651
+ testOptions('take=10&requireTotalCount=true', {
652
+ errors: [],
653
+ loadOptions: {
654
+ take: 10,
655
+ requireTotalCount: true
656
+ },
657
+ processingOptions: {}
658
+ });
659
+ });
660
+
661
+ test('take and total count with tzOffset', function () {
662
+ testOptions('take=10&requireTotalCount=true&tzOffset=-60', {
663
+ errors: [],
664
+ loadOptions: {
665
+ take: 10,
666
+ requireTotalCount: true
667
+ },
668
+ processingOptions: {
669
+ timezoneOffset: -60
670
+ }
671
+ });
672
+ });
673
+
674
+ test('take and total count with caseInsensitiveRegex', function () {
675
+ testOptions('take=10&requireTotalCount=true&caseInsensitiveRegex=false', {
676
+ errors: [],
677
+ loadOptions: {
678
+ take: 10,
679
+ requireTotalCount: true
680
+ },
681
+ processingOptions: {
682
+ caseInsensitiveRegex: false
683
+ }
684
+ });
685
+ });
686
+
687
+ test('take, skip, total count', function () {
688
+ testOptions('take=10&requireTotalCount=true&skip=30', {
689
+ errors: [],
690
+ loadOptions: {
691
+ take: 10,
692
+ skip: 30,
693
+ requireTotalCount: true
694
+ },
695
+ processingOptions: {}
696
+ });
697
+ });
698
+
699
+ test('contains 3 digits', function () {
700
+ testOptions('filter%5B0%5D%5B0%5D=field&filter%5B0%5D%5B1%5D=contains&filter%5B0%5D%5B2%5D=234', {
701
+ errors: [],
702
+ loadOptions: {
703
+ filter: [['field', 'contains', '234']]
704
+ },
705
+ processingOptions: {}
706
+ });
707
+ });
708
+
709
+ test('contains 4 digits', function () {
710
+ testOptions('filter%5B0%5D%5B0%5D=field&filter%5B0%5D%5B1%5D=contains&filter%5B0%5D%5B2%5D=2345', {
711
+ errors: [],
712
+ loadOptions: {
713
+ filter: [['field', 'contains', '2345']]
714
+ },
715
+ processingOptions: {}
716
+ });
717
+ });
718
+
719
+ test('contains 4 digits with dashes', function () {
720
+ testOptions('filter%5B0%5D%5B0%5D=field&filter%5B0%5D%5B1%5D=contains&filter%5B0%5D%5B2%5D=23-45', {
721
+ errors: [],
722
+ loadOptions: {
723
+ filter: [['field', 'contains', '23-45']]
724
+ },
725
+ processingOptions: {}
726
+ });
727
+ });
728
+
729
+ test('contains 5 digits', function () {
730
+ testOptions('filter%5B0%5D%5B0%5D=field&filter%5B0%5D%5B1%5D=contains&filter%5B0%5D%5B2%5D=23456', {
731
+ errors: [],
732
+ loadOptions: {
733
+ filter: [['field', 'contains', '23456']]
734
+ },
735
+ processingOptions: {}
736
+ });
737
+ });
738
+
739
+ test('contains 3 chars', function () {
740
+ testOptions('filter%5B0%5D%5B0%5D=field&filter%5B0%5D%5B1%5D=contains&filter%5B0%5D%5B2%5D=abc', {
741
+ errors: [],
742
+ loadOptions: {
743
+ filter: [['field', 'contains', 'abc']]
744
+ },
745
+ processingOptions: {}
746
+ });
747
+ });
748
+
749
+ test('contains 4 chars', function () {
750
+ testOptions('filter%5B0%5D%5B0%5D=field&filter%5B0%5D%5B1%5D=contains&filter%5B0%5D%5B2%5D=abcd', {
751
+ errors: [],
752
+ loadOptions: {
753
+ filter: [['field', 'contains', 'abcd']]
754
+ },
755
+ processingOptions: {}
756
+ });
757
+ });
758
+
759
+ test('sort, take and total count', function () {
760
+ testOptions('sort%5B0%5D%5Bselector%5D=date2&sort%5B0%5D%5Bdesc%5D=false&take=10&requireTotalCount=true', {
761
+ errors: [],
762
+ loadOptions: {
763
+ sort: [{
764
+ selector: 'date2',
765
+ desc: false
766
+ }],
767
+ take: 10,
768
+ requireTotalCount: true
769
+ },
770
+ processingOptions: {}
771
+ });
772
+ });
773
+
774
+ test('sort with correct parameter', function () {
775
+ testOptions('sort=[{%22selector%22:%22population%22,%22desc%22:true}]', {
776
+ errors: [],
777
+ loadOptions: {
778
+ sort: [{
779
+ selector: 'population',
780
+ desc: true
781
+ }]
782
+ },
783
+ processingOptions: {}
784
+ });
785
+ });
786
+
787
+ test('sort with incorrect parameter', function () {
788
+ var queryString = 'sort=[{%22selectorX%22:%22population%22,%22desc%22:true}]';
789
+ var result = getOptions(qs.parse(queryString));
790
+
791
+ expect(result.errors.length).to.eql(1);
792
+
793
+ expect(result.errors[0].message).to.be.a('string').and.satisfy(function (s) {
794
+ return s.startsWith('Sort parameter validation errors:');
795
+ });
796
+ });
797
+
798
+ test('issue #10 - filter works when given as array', function () {
799
+ expect(getOptions({
800
+ filter: [['dtFinished', '>=', '2018-08-01T16:20:30.000Z'], 'and', ['dtFinished', '<', '2018-08-01T16:20:30.000Z']]
801
+ }, { dtFinished: 'datetime' })).to.eql({
802
+ errors: [],
803
+ loadOptions: {
804
+ filter: [['dtFinished', '>=', new Date('2018-08-01T16:20:30.000Z')], 'and', ['dtFinished', '<', new Date('2018-08-01T16:20:30.000Z')]]
805
+ },
806
+ processingOptions: {}
807
+ });
808
+ });
809
+
810
+ test('filter works with a bool value', function () {
811
+ expect(getOptions({
812
+ filter: [['done', '=', true]]
813
+ })).to.eql({
814
+ errors: [],
815
+ loadOptions: {
816
+ filter: [['done', '=', true]]
817
+ },
818
+ processingOptions: {}
819
+ });
820
+ });
821
+
822
+ test('filter works with a bool value given as a string', function () {
823
+ expect(getOptions({
824
+ filter: [['done', '=', 'true']]
825
+ }, { done: 'bool' })).to.eql({
826
+ errors: [],
827
+ loadOptions: {
828
+ filter: [['done', '=', true]]
829
+ },
830
+ processingOptions: {}
831
+ });
832
+ });
833
+
834
+ test('issue #10 - filter works when given as string', function () {
835
+ expect(getOptions({
836
+ filter: '[["dtFinished",">=","2018-08-01T16:20:30.000Z"],"and",["dtFinished","<","2018-08-01T16:20:30.000Z"]]'
837
+ }, { dtFinished: 'datetime' })).to.eql({
838
+ errors: [],
839
+ loadOptions: {
840
+ filter: [['dtFinished', '>=', new Date('2018-08-01T16:20:30.000Z')], 'and', ['dtFinished', '<', new Date('2018-08-01T16:20:30.000Z')]]
841
+ },
842
+ processingOptions: {}
843
+ });
844
+ });
845
+
846
+ test('total count, group, group count', function () {
847
+ testOptions('sort%5B0%5D%5Bselector%5D=date2&sort%5B0%5D%5Bdesc%5D=false&requireTotalCount=true&group%5B0%5D%5Bselector%5D=date2&group%5B0%5D%5BisExpanded%5D=false&requireGroupCount=true', {
848
+ errors: [],
849
+ loadOptions: {
850
+ sort: [{
851
+ selector: 'date2',
852
+ desc: false
853
+ }],
854
+ requireTotalCount: true,
855
+ group: [{
856
+ selector: 'date2',
857
+ isExpanded: false
858
+ }],
859
+ requireGroupCount: true
860
+ },
861
+ processingOptions: {}
862
+ });
863
+ });
864
+
865
+ test('sort, filter with datetime in schema', function () {
866
+ testOptions('sort%5B0%5D%5Bselector%5D=date2&sort%5B0%5D%5Bdesc%5D=false&filter%5B0%5D%5B0%5D=date2&filter%5B0%5D%5B1%5D=%3D&filter%5B0%5D%5B2%5D=2017-07-13T00%3A00%3A00.000Z', {
867
+ errors: [],
868
+ loadOptions: {
869
+ sort: [{
870
+ selector: 'date2',
871
+ desc: false
872
+ }],
873
+ filter: [['date2', '=', new Date(Date.parse('2017-07-13'))]]
874
+ },
875
+ processingOptions: {}
876
+ }, { date2: 'datetime' });
877
+ });
878
+
879
+ test('take, total count, filter with int', function () {
880
+ testOptions('take=10&requireTotalCount=true&filter%5B0%5D%5B0%5D=int1&filter%5B0%5D%5B1%5D=%3D&filter%5B0%5D%5B2%5D=4', {
881
+ errors: [],
882
+ loadOptions: {
883
+ take: 10,
884
+ requireTotalCount: true,
885
+ filter: [['int1', '=', 4]]
886
+ },
887
+ processingOptions: {}
888
+ }, {
889
+ int1: 'int'
890
+ });
891
+ });
892
+
893
+ test('summaryQueryLimit, skip, take, requireTotalCount, totalSummary, tzOffset', function () {
894
+ testOptions('summaryQueryLimit=500&skip=0&take=20&requireTotalCount=true&totalSummary=%5B%7B%22selector%22%3A%22date1%22%2C%22summaryType%22%3A%22max%22%7D%2C%7B%22selector%22%3A%22int1%22%2C%22summaryType%22%3A%22avg%22%7D%2C%7B%22selector%22%3A%22int1%22%2C%22summaryType%22%3A%22sum%22%7D%5D&tzOffset=-60', {
895
+ errors: [],
896
+ loadOptions: {
897
+ skip: 0,
898
+ take: 20,
899
+ requireTotalCount: true,
900
+ totalSummary: [{
901
+ selector: 'date1',
902
+ summaryType: 'max'
903
+ }, {
904
+ selector: 'int1',
905
+ summaryType: 'avg'
906
+ }, {
907
+ selector: 'int1',
908
+ summaryType: 'sum'
909
+ }]
910
+ },
911
+ processingOptions: {
912
+ timezoneOffset: -60,
913
+ summaryQueryLimit: 500
914
+ }
915
+ });
916
+ });
917
+
918
+ test('summaryQueryLimit, skip, take, requireTotalCount, totalSummary, group, requireGroupCount, groupSummary, tzOffset', function () {
919
+ testOptions('summaryQueryLimit=500&skip=0&take=20&requireTotalCount=true&totalSummary=%5B%7B%22selector%22%3A%22date1%22%2C%22summaryType%22%3A%22max%22%7D%2C%7B%22selector%22%3A%22int1%22%2C%22summaryType%22%3A%22avg%22%7D%2C%7B%22selector%22%3A%22int1%22%2C%22summaryType%22%3A%22sum%22%7D%5D&group=%5B%7B%22selector%22%3A%22int1%22%2C%22desc%22%3Afalse%2C%22isExpanded%22%3Afalse%7D%5D&requireGroupCount=true&groupSummary=%5B%7B%22selector%22%3A%22date1%22%2C%22summaryType%22%3A%22min%22%7D%2C%7B%22selector%22%3A%22int1%22%2C%22summaryType%22%3A%22avg%22%7D%2C%7B%22selector%22%3A%22int1%22%2C%22summaryType%22%3A%22sum%22%7D%2C%7B%22summaryType%22%3A%22count%22%7D%5D&tzOffset=-60', {
920
+ errors: [],
921
+ loadOptions: {
922
+ skip: 0,
923
+ take: 20,
924
+ requireTotalCount: true,
925
+ totalSummary: [{
926
+ selector: 'date1',
927
+ summaryType: 'max'
928
+ }, {
929
+ selector: 'int1',
930
+ summaryType: 'avg'
931
+ }, {
932
+ selector: 'int1',
933
+ summaryType: 'sum'
934
+ }],
935
+ requireGroupCount: true,
936
+ group: [{
937
+ selector: 'int1',
938
+ desc: false,
939
+ isExpanded: false
940
+ }],
941
+ groupSummary: [{
942
+ selector: 'date1',
943
+ summaryType: 'min'
944
+ }, {
945
+ selector: 'int1',
946
+ summaryType: 'avg'
947
+ }, {
948
+ selector: 'int1',
949
+ summaryType: 'sum'
950
+ }, {
951
+ summaryType: 'count'
952
+ }]
953
+ },
954
+ processingOptions: {
955
+ timezoneOffset: -60,
956
+ summaryQueryLimit: 500
957
+ }
958
+ });
959
+ });
960
+ });