@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,2333 @@
1
+ /* global suite, test */
2
+ /* eslint-disable no-unused-expressions */
3
+
4
+ const chai = require('chai');
5
+ const expect = chai.expect;
6
+ const { MongoClient, ObjectId } = require('mongodb');
7
+
8
+ const query = require('.');
9
+
10
+ const TESTRECORD_COUNT = 100;
11
+
12
+ const initClient = () =>
13
+ MongoClient.connect('mongodb://localhost:27017/dxtqutests', {
14
+ useNewUrlParser: true,
15
+ useUnifiedTopology: true,
16
+ });
17
+
18
+ function testQueryValues(
19
+ tdone,
20
+ loadOptions,
21
+ test,
22
+ getTestDataPromises,
23
+ contextOptions
24
+ ) {
25
+ function date(start, addDays) {
26
+ return new Date(start + addDays * (24 * 60 * 60 * 1000));
27
+ }
28
+
29
+ initClient()
30
+ .then(
31
+ (client) =>
32
+ /* eslint-disable promise/always-return, promise/no-nesting */
33
+ client
34
+ .db()
35
+ .dropDatabase()
36
+ .then(() => {
37
+ const values = client.db().collection('values');
38
+ const currentYear = 2017;
39
+ const currentYearStart = new Date(currentYear, 0, 1).valueOf();
40
+ const nextYearStart = new Date(currentYear + 1, 0, 1).valueOf();
41
+
42
+ return Promise.all(
43
+ getTestDataPromises
44
+ ? getTestDataPromises(values)
45
+ : Array.from(new Array(TESTRECORD_COUNT), (v, i) => i).map(
46
+ (n) =>
47
+ values.insertOne({
48
+ date1: date(currentYearStart, n),
49
+ date2: date(nextYearStart, n),
50
+ int1: n % 10,
51
+ int2: n % 5,
52
+ string: 'Item ' + n,
53
+ })
54
+ )
55
+ )
56
+ .then(() => query(values, loadOptions, contextOptions))
57
+ .then(test);
58
+ })
59
+
60
+ .then(() => client.close())
61
+ .then(tdone)
62
+ /* eslint-enable promise/always-return, promise/no-nesting */
63
+ )
64
+ .catch((err) => tdone(err));
65
+ }
66
+
67
+ suite('query-values', function () {
68
+ suite('#aggregateOptions', function () {
69
+ // these tests are only to make sure that the aggregate setting
70
+ // are passed through correctly to the aggregate calls
71
+ test('collation', function (tdone) {
72
+ testQueryValues(
73
+ tdone,
74
+ { sort: [{ selector: 'string' }], requireTotalCount: true },
75
+ function (res) {
76
+ expect(res.totalCount, 'totalCount').to.eql(2);
77
+
78
+ expect(res.data, 'res.data').to.be.instanceof(Array);
79
+ expect(res.data, 'list length').to.have.lengthOf(2);
80
+ expect(res.data[0].string).to.eql('something');
81
+ expect(res.data[1].string).to.eql('Something');
82
+ },
83
+ function (collection) {
84
+ return [
85
+ collection.insertOne({
86
+ string: 'something',
87
+ }),
88
+ collection.insertOne({
89
+ string: 'Something',
90
+ }),
91
+ ];
92
+ },
93
+ {
94
+ aggregateOptions: {
95
+ collation: { locale: 'en', caseFirst: 'lower' },
96
+ },
97
+ }
98
+ );
99
+ });
100
+
101
+ test('collation dynamic', function (tdone) {
102
+ testQueryValues(
103
+ tdone,
104
+ { sort: [{ selector: 'string' }], requireTotalCount: true },
105
+ function (res) {
106
+ expect(res.totalCount, 'totalCount').to.eql(2);
107
+
108
+ expect(res.data, 'res.data').to.be.instanceof(Array);
109
+ expect(res.data, 'list length').to.have.lengthOf(2);
110
+ expect(res.data[0].string).to.eql('something');
111
+ expect(res.data[1].string).to.eql('Something');
112
+ },
113
+ function (collection) {
114
+ return [
115
+ collection.insertOne({
116
+ string: 'something',
117
+ }),
118
+ collection.insertOne({
119
+ string: 'Something',
120
+ }),
121
+ ];
122
+ },
123
+ {
124
+ dynamicAggregateOptions: (identifier /*, pipeline,collection*/) =>
125
+ identifier === 'mainQueryResult'
126
+ ? {
127
+ collation: { locale: 'en', caseFirst: 'lower' },
128
+ }
129
+ : {},
130
+ }
131
+ );
132
+ });
133
+ });
134
+
135
+ suite('#entitiesQuery.values', function () {
136
+ test('list should retrieve all entities', function (tdone) {
137
+ testQueryValues(
138
+ tdone,
139
+ {
140
+ requireTotalCount: true,
141
+ },
142
+ function (res) {
143
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
144
+
145
+ expect(res.data, 'res.data').to.be.instanceof(Array);
146
+ expect(res.data, 'result').to.have.lengthOf(TESTRECORD_COUNT);
147
+ }
148
+ );
149
+ });
150
+
151
+ test('list should accept skip', function (tdone) {
152
+ testQueryValues(
153
+ tdone,
154
+ {
155
+ skip: 5,
156
+ requireTotalCount: true,
157
+ },
158
+ function (res) {
159
+ expect(res.totalCount).to.eql(TESTRECORD_COUNT);
160
+
161
+ expect(res.data, 'res.data').to.be.instanceof(Array);
162
+ expect(res.data, 'result').to.have.lengthOf(TESTRECORD_COUNT - 5);
163
+ }
164
+ );
165
+ });
166
+
167
+ test('list should accept take', function (tdone) {
168
+ testQueryValues(
169
+ tdone,
170
+ {
171
+ take: 5,
172
+ requireTotalCount: true,
173
+ },
174
+ function (res) {
175
+ expect(res.totalCount).to.eql(TESTRECORD_COUNT);
176
+
177
+ expect(res.data, 'res.data').to.be.instanceof(Array);
178
+ expect(res.data, 'result').to.have.lengthOf(5);
179
+ }
180
+ );
181
+ });
182
+
183
+ test('list should sort ascending', function (tdone) {
184
+ testQueryValues(
185
+ tdone,
186
+ {
187
+ take: 5,
188
+ sort: [
189
+ {
190
+ selector: 'int1',
191
+ desc: false,
192
+ },
193
+ ],
194
+ },
195
+ function (res) {
196
+ expect(res.data, 'res.data').to.be.instanceof(Array);
197
+ expect(res.data, 'result').to.have.lengthOf(5);
198
+ expect(res.data[0].int1).to.eql(0);
199
+ expect(res.data[1].int1).to.eql(0);
200
+ expect(res.data[2].int1).to.eql(0);
201
+ expect(res.data[3].int1).to.eql(0);
202
+ expect(res.data[4].int1).to.eql(0);
203
+ }
204
+ );
205
+ });
206
+
207
+ test('list should sort descending', function (tdone) {
208
+ testQueryValues(
209
+ tdone,
210
+ {
211
+ take: 5,
212
+ sort: [
213
+ {
214
+ selector: 'int1',
215
+ desc: true,
216
+ },
217
+ ],
218
+ },
219
+ function (res) {
220
+ expect(res.data, 'res.data').to.be.instanceof(Array);
221
+ expect(res.data, 'result').to.have.lengthOf(5);
222
+ expect(res.data[0].int1).to.eql(9);
223
+ expect(res.data[1].int1).to.eql(9);
224
+ expect(res.data[2].int1).to.eql(9);
225
+ expect(res.data[3].int1).to.eql(9);
226
+ expect(res.data[4].int1).to.eql(9);
227
+ }
228
+ );
229
+ });
230
+
231
+ test('list should sort by two fields', function (tdone) {
232
+ testQueryValues(
233
+ tdone,
234
+ {
235
+ take: 20,
236
+ sort: [
237
+ {
238
+ selector: 'int2',
239
+ desc: true,
240
+ },
241
+ { selector: 'int1', desc: false },
242
+ ],
243
+ },
244
+ function (res) {
245
+ // the highest 20 are all 4 for int2, but then
246
+ // there's 4 and 9 for int1. Sorting ascending on int1,
247
+ // we should start with the 4s and then see the 9s.
248
+
249
+ // I guess this is not a perfect sorting test because it
250
+ // doesn't have much variety. But I was testing just now
251
+ // on suspicion that something was severely out of order,
252
+ // and that is apparently not the case.
253
+
254
+ // console.log(JSON.stringify(res.data, null, 2));
255
+
256
+ expect(res.data, 'res.data').to.be.instanceof(Array);
257
+ expect(res.data, 'result').to.have.lengthOf(20);
258
+ expect(res.data[0].int2).to.eql(4);
259
+ expect(res.data[1].int2).to.eql(4);
260
+ expect(res.data[2].int2).to.eql(4);
261
+ expect(res.data[3].int2).to.eql(4);
262
+ expect(res.data[4].int2).to.eql(4);
263
+ expect(res.data[5].int2).to.eql(4);
264
+ expect(res.data[6].int2).to.eql(4);
265
+ expect(res.data[7].int2).to.eql(4);
266
+ expect(res.data[8].int2).to.eql(4);
267
+ expect(res.data[9].int2).to.eql(4);
268
+ expect(res.data[10].int2).to.eql(4);
269
+ expect(res.data[11].int2).to.eql(4);
270
+ expect(res.data[12].int2).to.eql(4);
271
+ expect(res.data[13].int2).to.eql(4);
272
+ expect(res.data[14].int2).to.eql(4);
273
+ expect(res.data[15].int2).to.eql(4);
274
+ expect(res.data[16].int2).to.eql(4);
275
+ expect(res.data[17].int2).to.eql(4);
276
+ expect(res.data[18].int2).to.eql(4);
277
+ expect(res.data[19].int2).to.eql(4);
278
+
279
+ expect(res.data[0].int1).to.eql(4);
280
+ expect(res.data[1].int1).to.eql(4);
281
+ expect(res.data[2].int1).to.eql(4);
282
+ expect(res.data[3].int1).to.eql(4);
283
+ expect(res.data[4].int1).to.eql(4);
284
+ expect(res.data[5].int1).to.eql(4);
285
+ expect(res.data[6].int1).to.eql(4);
286
+ expect(res.data[7].int1).to.eql(4);
287
+ expect(res.data[8].int1).to.eql(4);
288
+ expect(res.data[9].int1).to.eql(4);
289
+ expect(res.data[10].int1).to.eql(9);
290
+ expect(res.data[11].int1).to.eql(9);
291
+ expect(res.data[12].int1).to.eql(9);
292
+ expect(res.data[13].int1).to.eql(9);
293
+ expect(res.data[14].int1).to.eql(9);
294
+ expect(res.data[15].int1).to.eql(9);
295
+ expect(res.data[16].int1).to.eql(9);
296
+ expect(res.data[17].int1).to.eql(9);
297
+ expect(res.data[18].int1).to.eql(9);
298
+ expect(res.data[19].int1).to.eql(9);
299
+ }
300
+ );
301
+ });
302
+
303
+ test('list should filter with =', function (tdone) {
304
+ testQueryValues(
305
+ tdone,
306
+ {
307
+ filter: ['int1', '=', 3],
308
+ requireTotalCount: true,
309
+ },
310
+ function (res) {
311
+ expect(res.totalCount, 'totalCount').to.eql(10);
312
+
313
+ expect(res.data, 'res.data').to.be.instanceof(Array);
314
+ expect(res.data, 'list length').to.have.lengthOf(10);
315
+ }
316
+ );
317
+ });
318
+
319
+ test('list should filter with multiple criteria', function (tdone) {
320
+ testQueryValues(
321
+ tdone,
322
+ {
323
+ filter: [['int1', '=', 3], 'or', ['int1', '=', 5]],
324
+ requireTotalCount: true,
325
+ },
326
+ function (res) {
327
+ expect(res.totalCount, 'totalCount').to.eql(20);
328
+
329
+ expect(res.data, 'res.data').to.be.instanceof(Array);
330
+ expect(res.data, 'list length').to.have.lengthOf(20);
331
+ }
332
+ );
333
+ });
334
+
335
+ test('list should search with =', function (tdone) {
336
+ testQueryValues(
337
+ tdone,
338
+ {
339
+ searchExpr: 'int1',
340
+ searchOperation: '=',
341
+ searchValue: 3,
342
+ requireTotalCount: true,
343
+ },
344
+ function (res) {
345
+ expect(res.totalCount, 'totalCount').to.eql(10);
346
+
347
+ expect(res.data, 'res.data').to.be.instanceof(Array);
348
+ expect(res.data, 'list length').to.have.lengthOf(10);
349
+ }
350
+ );
351
+ });
352
+
353
+ test('list should project with select', function (tdone) {
354
+ testQueryValues(
355
+ tdone,
356
+ {
357
+ filter: ['int1', '=', 3],
358
+ requireTotalCount: false,
359
+ select: ['int2', 'date1'],
360
+ },
361
+ function (res) {
362
+ //console.log("Result: ", JSON.stringify(res, null, 2));
363
+
364
+ expect(res.data[0]).to.have.ownProperty('_id');
365
+ expect(res.data[0]).to.have.ownProperty('int2');
366
+ expect(res.data[0]).to.have.ownProperty('date1');
367
+
368
+ expect(res.data[0]).to.not.have.ownProperty('int1');
369
+ expect(res.data[0]).to.not.have.ownProperty('date2');
370
+ expect(res.data[0]).to.not.have.ownProperty('string');
371
+ }
372
+ );
373
+ });
374
+
375
+ test('list should search with multiple fields', function (tdone) {
376
+ testQueryValues(
377
+ tdone,
378
+ {
379
+ searchExpr: ['int1', 'int2'],
380
+ searchOperation: '=',
381
+ searchValue: 3,
382
+ requireTotalCount: true,
383
+ },
384
+ function (res) {
385
+ //console.log("Result: ", JSON.stringify(res, null, 2));
386
+
387
+ expect(res.totalCount, 'totalCount').to.eql(20);
388
+
389
+ expect(res.data, 'res.data').to.be.instanceof(Array);
390
+ expect(res.data, 'list length').to.have.lengthOf(20);
391
+ }
392
+ );
393
+ });
394
+
395
+ test('list should filter with <', function (tdone) {
396
+ testQueryValues(
397
+ tdone,
398
+ {
399
+ filter: ['int1', '<', 5],
400
+ requireTotalCount: true,
401
+ },
402
+ function (res) {
403
+ expect(res.totalCount, 'totalCount').to.eql(50);
404
+
405
+ expect(res.data, 'res.data').to.be.instanceof(Array);
406
+ expect(res.data, 'list length').to.have.lengthOf(50);
407
+ }
408
+ );
409
+ });
410
+
411
+ test('list should filter with date.Month and nested array', function (tdone) {
412
+ testQueryValues(
413
+ tdone,
414
+ {
415
+ // some pivot grid queries nest a single filter condition in an extra array
416
+ filter: [['date1.Month', '<=', 2]],
417
+ requireTotalCount: true,
418
+ },
419
+ function (res) {
420
+ //console.log("Result is ", JSON.stringify(res, null, 2));
421
+ expect(res.totalCount, 'totalCount').to.eql(59);
422
+
423
+ expect(res.data, 'res.data').to.be.instanceof(Array);
424
+ expect(res.data, 'list length').to.have.lengthOf(59);
425
+ }
426
+ );
427
+ });
428
+
429
+ test('list should filter with date.Quarter', function (tdone) {
430
+ testQueryValues(
431
+ tdone,
432
+ {
433
+ filter: ['date1.quarter', '=', 2],
434
+ requireTotalCount: true,
435
+ },
436
+ function (res) {
437
+ //console.log("Result is ", JSON.stringify(res, null, 2));
438
+ expect(res.totalCount, 'totalCount').to.eql(10);
439
+
440
+ expect(res.data, 'res.data').to.be.instanceof(Array);
441
+ expect(res.data, 'list length').to.have.lengthOf(10);
442
+
443
+ expect(res.data[0].date1, 'date1').to.be.a('date');
444
+ expect(res.data[0].date2, 'date2').to.be.a('date');
445
+ expect(res.data[0].int1, 'int1').to.be.a('number');
446
+ expect(res.data[0].int2, 'int2').to.be.a('number');
447
+ expect(res.data[0].string, 'string').to.be.a('string');
448
+ expect(res.data[0].___date1_mp2, '___date1_mp2').to.be.undefined;
449
+ expect(res.data[0].___date1_quarter, '___date1_quarter').to.be
450
+ .undefined;
451
+ }
452
+ );
453
+ });
454
+
455
+ test('list should filter and group (sample 1)', function (tdone) {
456
+ testQueryValues(
457
+ tdone,
458
+ {
459
+ filter: [['date2.Month', '>=', 4], 'and', ['date2.Month', '<', 7]],
460
+ group: [
461
+ {
462
+ groupInterval: 'month',
463
+ isExpanded: false,
464
+ selector: 'date1',
465
+ },
466
+ ],
467
+ groupSummary: [
468
+ {
469
+ selector: 'int1',
470
+ summaryType: 'sum',
471
+ },
472
+ ],
473
+ totalSummary: [
474
+ {
475
+ selector: 'int1',
476
+ summaryType: 'sum',
477
+ },
478
+ ],
479
+ requireTotalCount: true,
480
+ },
481
+ function (res) {
482
+ //console.log("Result is ", JSON.stringify(res, null, 2));
483
+
484
+ expect(res.totalCount, 'totalCount').to.eql(10);
485
+
486
+ expect(res.data, 'res.data').to.be.instanceof(Array);
487
+ expect(res.data, 'list length').to.have.lengthOf(1);
488
+
489
+ expect(res.summary[0], 'summary value').to.eql(45);
490
+ }
491
+ );
492
+ });
493
+
494
+ test('list should group and filter by quarter without extra fields', function (tdone) {
495
+ testQueryValues(
496
+ tdone,
497
+ {
498
+ filter: [['date2.quarter', '=', 1]],
499
+ group: [
500
+ {
501
+ groupInterval: 'month',
502
+ isExpanded: true,
503
+ selector: 'date1',
504
+ },
505
+ ],
506
+ requireTotalCount: true,
507
+ },
508
+ function (res) {
509
+ //console.log("Result is ", JSON.stringify(res, null, 2));
510
+
511
+ expect(res.totalCount, 'totalCount').to.eql(90);
512
+
513
+ expect(res.data, 'res.data').to.be.instanceof(Array);
514
+ expect(res.data, 'list length').to.have.lengthOf(3);
515
+
516
+ for (const group of res.data) {
517
+ expect(group.key, 'group.key').to.not.be.undefined;
518
+ expect(group.items, `group(${group.key}).items`).to.be.instanceof(
519
+ Array
520
+ );
521
+ expect(
522
+ group.items,
523
+ `group(${group.key}) items list`
524
+ ).to.have.length.of.at.least(10); // arbitrary
525
+ expect(group.count, `group(${group.key}).count`).to.eql(
526
+ group.items.length
527
+ );
528
+
529
+ for (const item of group.items) {
530
+ expect(item.___date2_mp2, 'item.___date2_mp2').to.be.undefined;
531
+ expect(item.___date2_quarter, 'item.___date2_quarter').to.be
532
+ .undefined;
533
+ // leaving the group key in place for now, Mongo doesn't seem to have a
534
+ // very easy way to remove this while data is queried as part of the
535
+ // $group step with $push $$CURRENT
536
+ //expect(item.___group_key_0, "item.___group_key_0").to.be.undefined;
537
+ }
538
+ }
539
+ }
540
+ );
541
+ });
542
+
543
+ test('list should filter with endswith', function (tdone) {
544
+ testQueryValues(
545
+ tdone,
546
+ {
547
+ filter: ['string', 'endswith', '23'],
548
+ requireTotalCount: true,
549
+ },
550
+ function (res) {
551
+ expect(res.totalCount, 'totalCount').to.eql(1);
552
+
553
+ expect(res.data, 'res.data').to.be.instanceof(Array);
554
+ expect(res.data, 'list length').to.have.lengthOf(1);
555
+ }
556
+ );
557
+ });
558
+
559
+ test('prefer metadata count with filter', function (tdone) {
560
+ testQueryValues(
561
+ tdone,
562
+ {
563
+ filter: ['string', 'contains', '7'],
564
+ requireTotalCount: true,
565
+ },
566
+ function (res) {
567
+ expect(res.totalCount, 'totalCount').to.eql(19);
568
+
569
+ expect(res.data, 'res.data').to.be.instanceof(Array);
570
+ expect(res.data, 'list length').to.have.lengthOf(19);
571
+ },
572
+ undefined,
573
+ { preferMetadataCount: true }
574
+ );
575
+ });
576
+
577
+ test('prefer metadata count without filter', function (tdone) {
578
+ testQueryValues(
579
+ tdone,
580
+ {
581
+ requireTotalCount: true,
582
+ },
583
+ function (res) {
584
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
585
+ },
586
+ undefined,
587
+ { preferMetadataCount: true }
588
+ );
589
+ });
590
+
591
+ test('list should filter with contains', function (tdone) {
592
+ testQueryValues(
593
+ tdone,
594
+ {
595
+ filter: ['string', 'contains', 'Item'],
596
+ requireTotalCount: true,
597
+ },
598
+ function (res) {
599
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
600
+
601
+ expect(res.data, 'res.data').to.be.instanceof(Array);
602
+ expect(res.data, 'list length').to.have.lengthOf(TESTRECORD_COUNT);
603
+ }
604
+ );
605
+ });
606
+
607
+ test('list should filter with contains (case insensitive)', function (tdone) {
608
+ testQueryValues(
609
+ tdone,
610
+ {
611
+ filter: ['string', 'contains', 'item'],
612
+ requireTotalCount: true,
613
+ },
614
+ function (res) {
615
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
616
+
617
+ expect(res.data, 'res.data').to.be.instanceof(Array);
618
+ expect(res.data, 'list length').to.have.lengthOf(TESTRECORD_COUNT);
619
+ }
620
+ );
621
+ });
622
+
623
+ test('list should filter with contains (case sensitive!)', function (tdone) {
624
+ testQueryValues(
625
+ tdone,
626
+ {
627
+ filter: ['string', 'contains', 'Something'],
628
+ requireTotalCount: true,
629
+ },
630
+ function (res) {
631
+ expect(res.totalCount, 'totalCount').to.eql(1);
632
+
633
+ expect(res.data, 'res.data').to.be.instanceof(Array);
634
+ expect(res.data, 'list length').to.have.lengthOf(1);
635
+ },
636
+ function (collection) {
637
+ return [
638
+ collection.insertOne({
639
+ string: 'something',
640
+ }),
641
+ collection.insertOne({
642
+ string: 'Something',
643
+ }),
644
+ ];
645
+ },
646
+ { caseInsensitiveRegex: false }
647
+ );
648
+ });
649
+
650
+ test('ids should be strings by default', function (tdone) {
651
+ testQueryValues(
652
+ tdone,
653
+ {
654
+ requireTotalCount: true,
655
+ },
656
+ function (res) {
657
+ expect(res.totalCount, 'totalCount').to.eql(1);
658
+
659
+ expect(res.data, 'res.data').to.be.instanceof(Array);
660
+ expect(res.data, 'list length').to.have.lengthOf(1);
661
+ expect(res.data[0]._id, 'id').to.be.a('string');
662
+ },
663
+ function (collection) {
664
+ return [
665
+ collection.insertOne({
666
+ data: 42,
667
+ }),
668
+ ];
669
+ },
670
+ {
671
+ // replaceIds:true // default is true
672
+ }
673
+ );
674
+ });
675
+
676
+ test('ids should not be strings if replaceId=false', function (tdone) {
677
+ testQueryValues(
678
+ tdone,
679
+ {
680
+ requireTotalCount: true,
681
+ },
682
+ function (res) {
683
+ expect(res.totalCount, 'totalCount').to.eql(1);
684
+
685
+ expect(res.data, 'res.data').to.be.instanceof(Array);
686
+ expect(res.data, 'list length').to.have.lengthOf(1);
687
+ expect(res.data[0]._id, 'id').to.be.a('object');
688
+ },
689
+ function (collection) {
690
+ return [
691
+ collection.insertOne({
692
+ data: 42,
693
+ }),
694
+ ];
695
+ },
696
+ {
697
+ replaceIds: false, // default is true
698
+ }
699
+ );
700
+ });
701
+
702
+ test('list should filter with endswith, no results', function (tdone) {
703
+ testQueryValues(
704
+ tdone,
705
+ {
706
+ filter: ['string', 'endswith', "something that doesn't exist"],
707
+ requireTotalCount: true,
708
+ },
709
+ function (res) {
710
+ expect(res.totalCount, 'totalCount').to.eql(0);
711
+
712
+ expect(res.data, 'res.data').to.be.instanceof(Array);
713
+ expect(res.data, 'list length').to.have.lengthOf(0);
714
+ }
715
+ );
716
+ });
717
+
718
+ test('list should filter with endswith, no results, total summary defined', function (tdone) {
719
+ testQueryValues(
720
+ tdone,
721
+ {
722
+ filter: ['string', 'endswith', "something that doesn't exist"],
723
+ totalSummary: [
724
+ {
725
+ selector: 'int1',
726
+ summaryType: 'sum',
727
+ },
728
+ ],
729
+ requireTotalCount: true,
730
+ },
731
+ function (res) {
732
+ expect(res.totalCount, 'totalCount').to.eql(0);
733
+
734
+ expect(res.data, 'res.data').to.be.instanceof(Array);
735
+ expect(res.data, 'list length').to.have.lengthOf(0);
736
+
737
+ expect(res.summary, 'res.summary').to.be.undefined;
738
+ }
739
+ );
740
+ });
741
+
742
+ test('list should calculate total summaries for simple queries', function (tdone) {
743
+ testQueryValues(
744
+ tdone,
745
+ {
746
+ filter: ['int1', '<', 5],
747
+ totalSummary: [
748
+ {
749
+ selector: 'int1',
750
+ summaryType: 'sum',
751
+ },
752
+ {
753
+ selector: 'int2',
754
+ summaryType: 'max',
755
+ },
756
+ ],
757
+ requireTotalCount: true,
758
+ },
759
+ function (res) {
760
+ expect(res.totalCount, 'totalCount').to.eql(50);
761
+
762
+ expect(res.summary, 'res.summary').to.be.instanceof(Array);
763
+ expect(res.summary, 'res.summary').to.have.lengthOf(2);
764
+ expect(res.summary[0], 'sum(int1)').to.eql(100);
765
+ expect(res.summary[1], 'max(int2)').to.eql(4);
766
+ }
767
+ );
768
+ });
769
+
770
+ test('list should group with items', function (tdone) {
771
+ testQueryValues(
772
+ tdone,
773
+ {
774
+ group: [
775
+ {
776
+ selector: 'int1',
777
+ desc: false,
778
+ isExpanded: true,
779
+ },
780
+ ],
781
+ requireTotalCount: true,
782
+ requireGroupCount: true,
783
+ },
784
+ function (res) {
785
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
786
+ expect(res.groupCount, 'groupCount').to.eql(10);
787
+
788
+ expect(res.data, 'res.data').to.be.instanceof(Array);
789
+ expect(res.data, 'group list length').to.have.lengthOf(10);
790
+
791
+ for (const group of res.data) {
792
+ expect(group.key, 'group.key').to.not.be.undefined;
793
+ expect(group.items, `group(${group.key}).items`).to.be.instanceof(
794
+ Array
795
+ );
796
+ expect(
797
+ group.items,
798
+ `group(${group.key}) items list`
799
+ ).to.have.lengthOf(10);
800
+ expect(group.count, `group(${group.key}).count`).to.eql(
801
+ group.items.length
802
+ );
803
+
804
+ for (const item of group.items) {
805
+ expect(item.int1, 'item.int1').to.eql(group.key);
806
+ }
807
+ }
808
+ }
809
+ );
810
+ });
811
+
812
+ test('group item id should be type string by default', function (tdone) {
813
+ testQueryValues(
814
+ tdone,
815
+ {
816
+ group: [
817
+ {
818
+ selector: 'int1',
819
+ desc: false,
820
+ isExpanded: true,
821
+ },
822
+ ],
823
+ requireTotalCount: true,
824
+ requireGroupCount: true,
825
+ },
826
+ function (res) {
827
+ expect(res.data[0].items[0]._id, 'group item id').to.be.a('string');
828
+ },
829
+ undefined,
830
+ {
831
+ // replaceIds: true, // default is true
832
+ }
833
+ );
834
+ });
835
+
836
+ test('group item id should not be type string if replaceIds=false', function (tdone) {
837
+ testQueryValues(
838
+ tdone,
839
+ {
840
+ group: [
841
+ {
842
+ selector: 'int1',
843
+ desc: false,
844
+ isExpanded: true,
845
+ },
846
+ ],
847
+ requireTotalCount: true,
848
+ requireGroupCount: true,
849
+ },
850
+ function (res) {
851
+ expect(res.data[0].items[0]._id, 'group item id').to.be.a('object');
852
+ },
853
+ undefined,
854
+ {
855
+ replaceIds: false, // default is true
856
+ }
857
+ );
858
+ });
859
+
860
+ test('list should group with items and select', function (tdone) {
861
+ testQueryValues(
862
+ tdone,
863
+ {
864
+ group: [
865
+ {
866
+ selector: 'int1',
867
+ desc: false,
868
+ isExpanded: true,
869
+ },
870
+ ],
871
+ select: ['int2', 'date1'],
872
+ },
873
+ function (res) {
874
+ //console.log("Result: ", JSON.stringify(res, null, 2));
875
+
876
+ const x = res.data[0].items[0];
877
+
878
+ expect(x).to.have.ownProperty('_id');
879
+ expect(x).to.have.ownProperty('int2');
880
+ expect(x).to.have.ownProperty('date1');
881
+
882
+ expect(x).to.not.have.ownProperty('int1');
883
+ expect(x).to.not.have.ownProperty('date2');
884
+ expect(x).to.not.have.ownProperty('string');
885
+ }
886
+ );
887
+ });
888
+
889
+ test('list should group with items and secondary sort', function (tdone) {
890
+ testQueryValues(
891
+ tdone,
892
+ {
893
+ filter: ['int2', '=', 3],
894
+ group: [
895
+ {
896
+ selector: 'int2',
897
+ desc: false,
898
+ isExpanded: true,
899
+ },
900
+ ],
901
+ sort: [
902
+ {
903
+ selector: 'int1',
904
+ desc: true,
905
+ },
906
+ ],
907
+ requireTotalCount: true,
908
+ requireGroupCount: true,
909
+ },
910
+ function (res) {
911
+ expect(res.totalCount, 'totalCount').to.eql(20);
912
+ expect(res.groupCount, 'groupCount').to.eql(1);
913
+
914
+ expect(res.data, 'res.data').to.be.instanceof(Array);
915
+ expect(res.data, 'group list length').to.have.lengthOf(1);
916
+
917
+ for (const group of res.data) {
918
+ //console.log("Checking group", JSON.stringify(group, null, 2));
919
+
920
+ expect(group.key, 'group.key').to.not.be.undefined;
921
+ expect(group.items, `group(${group.key}).items`).to.be.instanceof(
922
+ Array
923
+ );
924
+ expect(
925
+ group.items,
926
+ `group(${group.key}) items list`
927
+ ).to.have.lengthOf(20);
928
+
929
+ for (let i = 0; i <= 9; i++) {
930
+ expect(group.items[i].int1, `groupitem ${i}`).to.eql(8);
931
+ }
932
+ for (let i = 10; i <= 19; i++) {
933
+ expect(group.items[i].int1, `groupitem ${i}`).to.eql(3);
934
+ }
935
+ }
936
+ }
937
+ );
938
+ });
939
+
940
+ test('list should group without items', function (tdone) {
941
+ testQueryValues(
942
+ tdone,
943
+ {
944
+ group: [
945
+ {
946
+ selector: 'int1',
947
+ desc: false,
948
+ // , isExpanded: false
949
+ },
950
+ ],
951
+ requireTotalCount: true,
952
+ requireGroupCount: true,
953
+ },
954
+ function (res) {
955
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
956
+ expect(res.groupCount, 'groupCount').to.eql(10);
957
+
958
+ expect(res.data, 'res.data').to.be.instanceof(Array);
959
+ expect(res.data, 'group list length').to.have.lengthOf(10);
960
+
961
+ for (const group of res.data) {
962
+ expect(group.key, 'group.key').to.not.be.undefined;
963
+ expect(group.items, `group(${group.key}).items`).to.be.null;
964
+ expect(group.count, `group(${group.key}).count`).to.eql(10);
965
+ }
966
+ }
967
+ );
968
+ });
969
+
970
+ test('list should group without items, with filter', function (tdone) {
971
+ testQueryValues(
972
+ tdone,
973
+ {
974
+ filter: ['int1', '=', 3],
975
+ group: [
976
+ {
977
+ selector: 'int1',
978
+ desc: false,
979
+ // , isExpanded: false
980
+ },
981
+ ],
982
+ requireTotalCount: true,
983
+ requireGroupCount: true,
984
+ },
985
+ function (res) {
986
+ expect(res.totalCount, 'totalCount').to.eql(10);
987
+ expect(res.groupCount, 'groupCount').to.eql(1);
988
+
989
+ expect(res.data, 'res.data').to.be.instanceof(Array);
990
+ expect(res.data, 'group list length').to.have.lengthOf(1);
991
+
992
+ for (const group of res.data) {
993
+ expect(group.key, 'group.key').to.not.be.undefined;
994
+ expect(group.items, `group(${group.key}).items`).to.be.null;
995
+ expect(group.count, `group(${group.key}).count`).to.eql(10);
996
+ }
997
+ }
998
+ );
999
+ });
1000
+
1001
+ test('list should group without items, with complex filter', function (tdone) {
1002
+ testQueryValues(
1003
+ tdone,
1004
+ {
1005
+ filter: [
1006
+ ['int1', '=', 3],
1007
+ 'or',
1008
+ ['int1', '=', 5],
1009
+ 'or',
1010
+ ['int1', '=', 7],
1011
+ ],
1012
+ group: [
1013
+ {
1014
+ selector: 'int1',
1015
+ desc: false,
1016
+ // , isExpanded: false
1017
+ },
1018
+ ],
1019
+ requireTotalCount: true,
1020
+ requireGroupCount: true,
1021
+ },
1022
+ function (res) {
1023
+ expect(res.totalCount, 'totalCount').to.eql(30);
1024
+ expect(res.groupCount, 'groupCount').to.eql(3);
1025
+
1026
+ expect(res.data, 'res.data').to.be.instanceof(Array);
1027
+ expect(res.data, 'group list length').to.have.lengthOf(3);
1028
+
1029
+ for (const group of res.data) {
1030
+ expect(group.key, 'group.key').to.not.be.undefined;
1031
+ expect(group.items, `group(${group.key}).items`).to.be.null;
1032
+ expect(group.count, `group(${group.key}).count`).to.eql(10);
1033
+ }
1034
+ }
1035
+ );
1036
+ });
1037
+
1038
+ test('list should group with items, with complex filter', function (tdone) {
1039
+ testQueryValues(
1040
+ tdone,
1041
+ {
1042
+ filter: [
1043
+ ['int1', '=', 3],
1044
+ 'or',
1045
+ ['int1', '=', 5],
1046
+ 'or',
1047
+ ['int1', '=', 7],
1048
+ ],
1049
+ group: [
1050
+ {
1051
+ selector: 'int1',
1052
+ desc: false,
1053
+ isExpanded: true,
1054
+ },
1055
+ ],
1056
+ requireTotalCount: true,
1057
+ requireGroupCount: true,
1058
+ },
1059
+ function (res) {
1060
+ expect(res.totalCount, 'totalCount').to.eql(30);
1061
+ expect(res.groupCount, 'groupCount').to.eql(3);
1062
+
1063
+ expect(res.data, 'res.data').to.be.instanceof(Array);
1064
+ expect(res.data, 'group list length').to.have.lengthOf(3);
1065
+
1066
+ for (const group of res.data) {
1067
+ expect(group.key, 'group.key').to.not.be.undefined;
1068
+ expect(group.items, `group(${group.key}).items`).to.be.instanceof(
1069
+ Array
1070
+ );
1071
+
1072
+ expect(group.items, 'group items list').to.have.lengthOf(10);
1073
+ expect(group.count, `group(${group.key}).count`).to.eql(
1074
+ group.items.length
1075
+ );
1076
+
1077
+ for (const item of group.items) {
1078
+ expect(item.int1, 'item.int1').to.eql(group.key);
1079
+ }
1080
+ }
1081
+ }
1082
+ );
1083
+ });
1084
+
1085
+ test('list should group two levels with bottom-level items', function (tdone) {
1086
+ testQueryValues(
1087
+ tdone,
1088
+ {
1089
+ filter: [
1090
+ [['int1', '=', 3], 'or', ['int1', '=', 6]],
1091
+ 'and',
1092
+ [['int2', '=', 3], 'or', ['int2', '=', 1]],
1093
+ ],
1094
+ group: [
1095
+ {
1096
+ selector: 'int1',
1097
+ desc: false,
1098
+ isExpanded: false,
1099
+ },
1100
+ {
1101
+ selector: 'int2',
1102
+ desc: false,
1103
+ isExpanded: true,
1104
+ },
1105
+ ],
1106
+ requireTotalCount: true,
1107
+ requireGroupCount: true,
1108
+ },
1109
+ function (res) {
1110
+ //console.log("Result is ", JSON.stringify(res, null, 2));
1111
+
1112
+ expect(res.totalCount, 'totalCount').to.eql(20);
1113
+ expect(res.groupCount, 'groupCount').to.eql(2);
1114
+
1115
+ expect(res.data, 'res.data').to.be.instanceof(Array);
1116
+ expect(res.data, 'group list length').to.have.lengthOf(2);
1117
+
1118
+ for (const group1 of res.data) {
1119
+ expect(group1.key, 'group1.key').to.not.be.undefined;
1120
+ expect(
1121
+ group1.items,
1122
+ `group1(${group1.key}).items`
1123
+ ).to.be.instanceof(Array);
1124
+
1125
+ expect(group1.items, 'group1 items list').to.have.lengthOf(1);
1126
+ expect(group1.count, `group(${group1.key}).count`).to.eql(
1127
+ group1.items.length
1128
+ );
1129
+
1130
+ for (const group2 of group1.items) {
1131
+ expect(group2.key, 'group2.key').to.not.be.undefined;
1132
+ expect(
1133
+ group2.items,
1134
+ `group2(${group2.key}).items`
1135
+ ).to.be.instanceof(Array);
1136
+
1137
+ expect(group2.items, 'group2 items list').to.have.lengthOf(10);
1138
+ expect(group2.count, `group(${group2.key}).count`).to.eql(
1139
+ group2.items.length
1140
+ );
1141
+ for (const item of group2.items) {
1142
+ expect(item.int1, 'item.int1').to.eql(group1.key);
1143
+ expect(item.int2, 'item.int2').to.eql(group2.key);
1144
+ }
1145
+ }
1146
+ }
1147
+ }
1148
+ );
1149
+ });
1150
+
1151
+ test('list should group two levels without bottom-level items', function (tdone) {
1152
+ testQueryValues(
1153
+ tdone,
1154
+ {
1155
+ filter: [
1156
+ [['int1', '=', 3], 'or', ['int1', '=', 6]],
1157
+ 'and',
1158
+ [['int2', '=', 3], 'or', ['int2', '=', 1]],
1159
+ ],
1160
+ group: [
1161
+ {
1162
+ selector: 'int1',
1163
+ desc: false,
1164
+ isExpanded: false,
1165
+ },
1166
+ {
1167
+ selector: 'int2',
1168
+ desc: false,
1169
+ isExpanded: false,
1170
+ },
1171
+ ],
1172
+ requireTotalCount: true,
1173
+ requireGroupCount: true,
1174
+ },
1175
+ function (res) {
1176
+ //console.log("Result is ", JSON.stringify(res, null, 2));
1177
+
1178
+ expect(res.totalCount, 'totalCount').to.eql(20);
1179
+ expect(res.groupCount, 'groupCount').to.eql(2);
1180
+
1181
+ expect(res.data, 'res.data').to.be.instanceof(Array);
1182
+ expect(res.data, 'group list length').to.have.lengthOf(2);
1183
+
1184
+ for (const group1 of res.data) {
1185
+ expect(group1.key, 'group1.key').to.not.be.undefined;
1186
+ expect(
1187
+ group1.items,
1188
+ `group1(${group1.key}).items`
1189
+ ).to.be.instanceof(Array);
1190
+
1191
+ expect(group1.items, 'group1 items list').to.have.lengthOf(1);
1192
+ expect(group1.count, `group(${group1.key}).count`).to.eql(
1193
+ group1.items.length
1194
+ );
1195
+
1196
+ for (const group2 of group1.items) {
1197
+ expect(group2.key, 'group2.key').to.not.be.undefined;
1198
+ expect(group2.items, 'group2 items list').to.be.null;
1199
+ expect(group2.count, `group(${group2.key}).count`).to.eql(10);
1200
+ }
1201
+ }
1202
+ }
1203
+ );
1204
+ });
1205
+
1206
+ test('list should group three levels without items', function (tdone) {
1207
+ testQueryValues(
1208
+ tdone,
1209
+ {
1210
+ group: [
1211
+ {
1212
+ selector: 'int1',
1213
+ isExpanded: false,
1214
+ },
1215
+ {
1216
+ selector: 'int2',
1217
+ isExpanded: false,
1218
+ },
1219
+ {
1220
+ selector: 'string',
1221
+ isExpanded: false,
1222
+ },
1223
+ ],
1224
+ requireTotalCount: true,
1225
+ requireGroupCount: true,
1226
+ },
1227
+ function (res) {
1228
+ //console.log('Result is ', JSON.stringify(res, null, 2));
1229
+ expect(res).to.deep.eql({
1230
+ data: [
1231
+ {
1232
+ key: 0,
1233
+ items: [
1234
+ {
1235
+ key: 0,
1236
+ items: [
1237
+ {
1238
+ count: 1,
1239
+ key: 'Item 0',
1240
+ items: null,
1241
+ },
1242
+ {
1243
+ count: 1,
1244
+ key: 'Item 10',
1245
+ items: null,
1246
+ },
1247
+ {
1248
+ count: 1,
1249
+ key: 'Item 20',
1250
+ items: null,
1251
+ },
1252
+ {
1253
+ count: 1,
1254
+ key: 'Item 30',
1255
+ items: null,
1256
+ },
1257
+ {
1258
+ count: 1,
1259
+ key: 'Item 40',
1260
+ items: null,
1261
+ },
1262
+ {
1263
+ count: 1,
1264
+ key: 'Item 50',
1265
+ items: null,
1266
+ },
1267
+ {
1268
+ count: 1,
1269
+ key: 'Item 60',
1270
+ items: null,
1271
+ },
1272
+ {
1273
+ count: 1,
1274
+ key: 'Item 70',
1275
+ items: null,
1276
+ },
1277
+ {
1278
+ count: 1,
1279
+ key: 'Item 80',
1280
+ items: null,
1281
+ },
1282
+ {
1283
+ count: 1,
1284
+ key: 'Item 90',
1285
+ items: null,
1286
+ },
1287
+ ],
1288
+ count: 10,
1289
+ },
1290
+ ],
1291
+ count: 1,
1292
+ },
1293
+ {
1294
+ key: 1,
1295
+ items: [
1296
+ {
1297
+ key: 1,
1298
+ items: [
1299
+ {
1300
+ count: 1,
1301
+ key: 'Item 1',
1302
+ items: null,
1303
+ },
1304
+ {
1305
+ count: 1,
1306
+ key: 'Item 11',
1307
+ items: null,
1308
+ },
1309
+ {
1310
+ count: 1,
1311
+ key: 'Item 21',
1312
+ items: null,
1313
+ },
1314
+ {
1315
+ count: 1,
1316
+ key: 'Item 31',
1317
+ items: null,
1318
+ },
1319
+ {
1320
+ count: 1,
1321
+ key: 'Item 41',
1322
+ items: null,
1323
+ },
1324
+ {
1325
+ count: 1,
1326
+ key: 'Item 51',
1327
+ items: null,
1328
+ },
1329
+ {
1330
+ count: 1,
1331
+ key: 'Item 61',
1332
+ items: null,
1333
+ },
1334
+ {
1335
+ count: 1,
1336
+ key: 'Item 71',
1337
+ items: null,
1338
+ },
1339
+ {
1340
+ count: 1,
1341
+ key: 'Item 81',
1342
+ items: null,
1343
+ },
1344
+ {
1345
+ count: 1,
1346
+ key: 'Item 91',
1347
+ items: null,
1348
+ },
1349
+ ],
1350
+ count: 10,
1351
+ },
1352
+ ],
1353
+ count: 1,
1354
+ },
1355
+ {
1356
+ key: 2,
1357
+ items: [
1358
+ {
1359
+ key: 2,
1360
+ items: [
1361
+ {
1362
+ count: 1,
1363
+ key: 'Item 12',
1364
+ items: null,
1365
+ },
1366
+ {
1367
+ count: 1,
1368
+ key: 'Item 2',
1369
+ items: null,
1370
+ },
1371
+ {
1372
+ count: 1,
1373
+ key: 'Item 22',
1374
+ items: null,
1375
+ },
1376
+ {
1377
+ count: 1,
1378
+ key: 'Item 32',
1379
+ items: null,
1380
+ },
1381
+ {
1382
+ count: 1,
1383
+ key: 'Item 42',
1384
+ items: null,
1385
+ },
1386
+ {
1387
+ count: 1,
1388
+ key: 'Item 52',
1389
+ items: null,
1390
+ },
1391
+ {
1392
+ count: 1,
1393
+ key: 'Item 62',
1394
+ items: null,
1395
+ },
1396
+ {
1397
+ count: 1,
1398
+ key: 'Item 72',
1399
+ items: null,
1400
+ },
1401
+ {
1402
+ count: 1,
1403
+ key: 'Item 82',
1404
+ items: null,
1405
+ },
1406
+ {
1407
+ count: 1,
1408
+ key: 'Item 92',
1409
+ items: null,
1410
+ },
1411
+ ],
1412
+ count: 10,
1413
+ },
1414
+ ],
1415
+ count: 1,
1416
+ },
1417
+ {
1418
+ key: 3,
1419
+ items: [
1420
+ {
1421
+ key: 3,
1422
+ items: [
1423
+ {
1424
+ count: 1,
1425
+ key: 'Item 13',
1426
+ items: null,
1427
+ },
1428
+ {
1429
+ count: 1,
1430
+ key: 'Item 23',
1431
+ items: null,
1432
+ },
1433
+ {
1434
+ count: 1,
1435
+ key: 'Item 3',
1436
+ items: null,
1437
+ },
1438
+ {
1439
+ count: 1,
1440
+ key: 'Item 33',
1441
+ items: null,
1442
+ },
1443
+ {
1444
+ count: 1,
1445
+ key: 'Item 43',
1446
+ items: null,
1447
+ },
1448
+ {
1449
+ count: 1,
1450
+ key: 'Item 53',
1451
+ items: null,
1452
+ },
1453
+ {
1454
+ count: 1,
1455
+ key: 'Item 63',
1456
+ items: null,
1457
+ },
1458
+ {
1459
+ count: 1,
1460
+ key: 'Item 73',
1461
+ items: null,
1462
+ },
1463
+ {
1464
+ count: 1,
1465
+ key: 'Item 83',
1466
+ items: null,
1467
+ },
1468
+ {
1469
+ count: 1,
1470
+ key: 'Item 93',
1471
+ items: null,
1472
+ },
1473
+ ],
1474
+ count: 10,
1475
+ },
1476
+ ],
1477
+ count: 1,
1478
+ },
1479
+ {
1480
+ key: 4,
1481
+ items: [
1482
+ {
1483
+ key: 4,
1484
+ items: [
1485
+ {
1486
+ count: 1,
1487
+ key: 'Item 14',
1488
+ items: null,
1489
+ },
1490
+ {
1491
+ count: 1,
1492
+ key: 'Item 24',
1493
+ items: null,
1494
+ },
1495
+ {
1496
+ count: 1,
1497
+ key: 'Item 34',
1498
+ items: null,
1499
+ },
1500
+ {
1501
+ count: 1,
1502
+ key: 'Item 4',
1503
+ items: null,
1504
+ },
1505
+ {
1506
+ count: 1,
1507
+ key: 'Item 44',
1508
+ items: null,
1509
+ },
1510
+ {
1511
+ count: 1,
1512
+ key: 'Item 54',
1513
+ items: null,
1514
+ },
1515
+ {
1516
+ count: 1,
1517
+ key: 'Item 64',
1518
+ items: null,
1519
+ },
1520
+ {
1521
+ count: 1,
1522
+ key: 'Item 74',
1523
+ items: null,
1524
+ },
1525
+ {
1526
+ count: 1,
1527
+ key: 'Item 84',
1528
+ items: null,
1529
+ },
1530
+ {
1531
+ count: 1,
1532
+ key: 'Item 94',
1533
+ items: null,
1534
+ },
1535
+ ],
1536
+ count: 10,
1537
+ },
1538
+ ],
1539
+ count: 1,
1540
+ },
1541
+ {
1542
+ key: 5,
1543
+ items: [
1544
+ {
1545
+ key: 0,
1546
+ items: [
1547
+ {
1548
+ count: 1,
1549
+ key: 'Item 15',
1550
+ items: null,
1551
+ },
1552
+ {
1553
+ count: 1,
1554
+ key: 'Item 25',
1555
+ items: null,
1556
+ },
1557
+ {
1558
+ count: 1,
1559
+ key: 'Item 35',
1560
+ items: null,
1561
+ },
1562
+ {
1563
+ count: 1,
1564
+ key: 'Item 45',
1565
+ items: null,
1566
+ },
1567
+ {
1568
+ count: 1,
1569
+ key: 'Item 5',
1570
+ items: null,
1571
+ },
1572
+ {
1573
+ count: 1,
1574
+ key: 'Item 55',
1575
+ items: null,
1576
+ },
1577
+ {
1578
+ count: 1,
1579
+ key: 'Item 65',
1580
+ items: null,
1581
+ },
1582
+ {
1583
+ count: 1,
1584
+ key: 'Item 75',
1585
+ items: null,
1586
+ },
1587
+ {
1588
+ count: 1,
1589
+ key: 'Item 85',
1590
+ items: null,
1591
+ },
1592
+ {
1593
+ count: 1,
1594
+ key: 'Item 95',
1595
+ items: null,
1596
+ },
1597
+ ],
1598
+ count: 10,
1599
+ },
1600
+ ],
1601
+ count: 1,
1602
+ },
1603
+ {
1604
+ key: 6,
1605
+ items: [
1606
+ {
1607
+ key: 1,
1608
+ items: [
1609
+ {
1610
+ count: 1,
1611
+ key: 'Item 16',
1612
+ items: null,
1613
+ },
1614
+ {
1615
+ count: 1,
1616
+ key: 'Item 26',
1617
+ items: null,
1618
+ },
1619
+ {
1620
+ count: 1,
1621
+ key: 'Item 36',
1622
+ items: null,
1623
+ },
1624
+ {
1625
+ count: 1,
1626
+ key: 'Item 46',
1627
+ items: null,
1628
+ },
1629
+ {
1630
+ count: 1,
1631
+ key: 'Item 56',
1632
+ items: null,
1633
+ },
1634
+ {
1635
+ count: 1,
1636
+ key: 'Item 6',
1637
+ items: null,
1638
+ },
1639
+ {
1640
+ count: 1,
1641
+ key: 'Item 66',
1642
+ items: null,
1643
+ },
1644
+ {
1645
+ count: 1,
1646
+ key: 'Item 76',
1647
+ items: null,
1648
+ },
1649
+ {
1650
+ count: 1,
1651
+ key: 'Item 86',
1652
+ items: null,
1653
+ },
1654
+ {
1655
+ count: 1,
1656
+ key: 'Item 96',
1657
+ items: null,
1658
+ },
1659
+ ],
1660
+ count: 10,
1661
+ },
1662
+ ],
1663
+ count: 1,
1664
+ },
1665
+ {
1666
+ key: 7,
1667
+ items: [
1668
+ {
1669
+ key: 2,
1670
+ items: [
1671
+ {
1672
+ count: 1,
1673
+ key: 'Item 17',
1674
+ items: null,
1675
+ },
1676
+ {
1677
+ count: 1,
1678
+ key: 'Item 27',
1679
+ items: null,
1680
+ },
1681
+ {
1682
+ count: 1,
1683
+ key: 'Item 37',
1684
+ items: null,
1685
+ },
1686
+ {
1687
+ count: 1,
1688
+ key: 'Item 47',
1689
+ items: null,
1690
+ },
1691
+ {
1692
+ count: 1,
1693
+ key: 'Item 57',
1694
+ items: null,
1695
+ },
1696
+ {
1697
+ count: 1,
1698
+ key: 'Item 67',
1699
+ items: null,
1700
+ },
1701
+ {
1702
+ count: 1,
1703
+ key: 'Item 7',
1704
+ items: null,
1705
+ },
1706
+ {
1707
+ count: 1,
1708
+ key: 'Item 77',
1709
+ items: null,
1710
+ },
1711
+ {
1712
+ count: 1,
1713
+ key: 'Item 87',
1714
+ items: null,
1715
+ },
1716
+ {
1717
+ count: 1,
1718
+ key: 'Item 97',
1719
+ items: null,
1720
+ },
1721
+ ],
1722
+ count: 10,
1723
+ },
1724
+ ],
1725
+ count: 1,
1726
+ },
1727
+ {
1728
+ key: 8,
1729
+ items: [
1730
+ {
1731
+ key: 3,
1732
+ items: [
1733
+ {
1734
+ count: 1,
1735
+ key: 'Item 18',
1736
+ items: null,
1737
+ },
1738
+ {
1739
+ count: 1,
1740
+ key: 'Item 28',
1741
+ items: null,
1742
+ },
1743
+ {
1744
+ count: 1,
1745
+ key: 'Item 38',
1746
+ items: null,
1747
+ },
1748
+ {
1749
+ count: 1,
1750
+ key: 'Item 48',
1751
+ items: null,
1752
+ },
1753
+ {
1754
+ count: 1,
1755
+ key: 'Item 58',
1756
+ items: null,
1757
+ },
1758
+ {
1759
+ count: 1,
1760
+ key: 'Item 68',
1761
+ items: null,
1762
+ },
1763
+ {
1764
+ count: 1,
1765
+ key: 'Item 78',
1766
+ items: null,
1767
+ },
1768
+ {
1769
+ count: 1,
1770
+ key: 'Item 8',
1771
+ items: null,
1772
+ },
1773
+ {
1774
+ count: 1,
1775
+ key: 'Item 88',
1776
+ items: null,
1777
+ },
1778
+ {
1779
+ count: 1,
1780
+ key: 'Item 98',
1781
+ items: null,
1782
+ },
1783
+ ],
1784
+ count: 10,
1785
+ },
1786
+ ],
1787
+ count: 1,
1788
+ },
1789
+ {
1790
+ key: 9,
1791
+ items: [
1792
+ {
1793
+ key: 4,
1794
+ items: [
1795
+ {
1796
+ count: 1,
1797
+ key: 'Item 19',
1798
+ items: null,
1799
+ },
1800
+ {
1801
+ count: 1,
1802
+ key: 'Item 29',
1803
+ items: null,
1804
+ },
1805
+ {
1806
+ count: 1,
1807
+ key: 'Item 39',
1808
+ items: null,
1809
+ },
1810
+ {
1811
+ count: 1,
1812
+ key: 'Item 49',
1813
+ items: null,
1814
+ },
1815
+ {
1816
+ count: 1,
1817
+ key: 'Item 59',
1818
+ items: null,
1819
+ },
1820
+ {
1821
+ count: 1,
1822
+ key: 'Item 69',
1823
+ items: null,
1824
+ },
1825
+ {
1826
+ count: 1,
1827
+ key: 'Item 79',
1828
+ items: null,
1829
+ },
1830
+ {
1831
+ count: 1,
1832
+ key: 'Item 89',
1833
+ items: null,
1834
+ },
1835
+ {
1836
+ count: 1,
1837
+ key: 'Item 9',
1838
+ items: null,
1839
+ },
1840
+ {
1841
+ count: 1,
1842
+ key: 'Item 99',
1843
+ items: null,
1844
+ },
1845
+ ],
1846
+ count: 10,
1847
+ },
1848
+ ],
1849
+ count: 1,
1850
+ },
1851
+ ],
1852
+ groupCount: 10,
1853
+ totalCount: 100,
1854
+ });
1855
+ }
1856
+ );
1857
+ });
1858
+
1859
+ test('list should calculate total summaries group query', function (tdone) {
1860
+ testQueryValues(
1861
+ tdone,
1862
+ {
1863
+ filter: [
1864
+ [['int1', '=', 3], 'or', ['int1', '=', 6]],
1865
+ 'and',
1866
+ [['int2', '=', 3], 'or', ['int2', '=', 1]],
1867
+ ],
1868
+ group: [
1869
+ {
1870
+ selector: 'int1',
1871
+ desc: false,
1872
+ isExpanded: false,
1873
+ },
1874
+ {
1875
+ selector: 'int2',
1876
+ desc: false,
1877
+ isExpanded: false,
1878
+ },
1879
+ ],
1880
+ totalSummary: [
1881
+ {
1882
+ selector: 'int1',
1883
+ summaryType: 'sum',
1884
+ },
1885
+ {
1886
+ selector: 'int2',
1887
+ summaryType: 'max',
1888
+ },
1889
+ ],
1890
+ requireTotalCount: true,
1891
+ requireGroupCount: true,
1892
+ },
1893
+ function (res) {
1894
+ //console.log("Result is ", JSON.stringify(res, null, 2));
1895
+
1896
+ expect(res.totalCount, 'totalCount').to.eql(20);
1897
+ expect(res.groupCount, 'groupCount').to.eql(2);
1898
+
1899
+ expect(res.summary, 'res.summary').to.be.instanceof(Array);
1900
+ expect(res.summary, 'res.summary').to.have.lengthOf(2);
1901
+ expect(res.summary[0], 'sum(int1)').to.eql(90);
1902
+ expect(res.summary[1], 'max(int2)').to.eql(3);
1903
+ }
1904
+ );
1905
+ });
1906
+
1907
+ test('list should calculate group summaries', function (tdone) {
1908
+ testQueryValues(
1909
+ tdone,
1910
+ {
1911
+ filter: [['int1', '=', 3], 'or', ['int1', '=', 6]],
1912
+ group: [
1913
+ {
1914
+ selector: 'int1',
1915
+ desc: false,
1916
+ isExpanded: false,
1917
+ },
1918
+ ],
1919
+ groupSummary: [
1920
+ {
1921
+ selector: 'int1',
1922
+ summaryType: 'sum',
1923
+ },
1924
+ {
1925
+ selector: 'int2',
1926
+ summaryType: 'max',
1927
+ },
1928
+ ],
1929
+ requireTotalCount: true,
1930
+ requireGroupCount: true,
1931
+ },
1932
+ function (res) {
1933
+ //console.log("Result is ", JSON.stringify(res, null, 2));
1934
+
1935
+ expect(res.totalCount, 'totalCount').to.eql(20);
1936
+ expect(res.groupCount, 'groupCount').to.eql(2);
1937
+
1938
+ expect(res.data, 'res.data').to.be.instanceof(Array);
1939
+ expect(res.data, 'group list length').to.have.lengthOf(2);
1940
+
1941
+ expect(res.data[0].summary, 'group1.summary').to.be.instanceof(Array);
1942
+ expect(res.data[0].summary, 'group1.summary').to.have.lengthOf(2);
1943
+ expect(res.data[0].summary[0], 'group1.sum(int1)').to.eql(30);
1944
+ expect(res.data[0].summary[1], 'group1.max(int2)').to.eql(3);
1945
+
1946
+ expect(res.data[1].summary, 'group2.summary').to.be.instanceof(Array);
1947
+ expect(res.data[1].summary, 'group2.summary').to.have.lengthOf(2);
1948
+ expect(res.data[1].summary[0], 'group2.sum(int1)').to.eql(60);
1949
+ expect(res.data[1].summary[1], 'group2.max(int2)').to.eql(1);
1950
+ }
1951
+ );
1952
+ });
1953
+
1954
+ test('list should group with groupInterval quarter', function (tdone) {
1955
+ testQueryValues(
1956
+ tdone,
1957
+ {
1958
+ group: [
1959
+ {
1960
+ selector: 'date1',
1961
+ groupInterval: 'quarter',
1962
+ },
1963
+ ],
1964
+ requireTotalCount: true,
1965
+ requireGroupCount: true,
1966
+ },
1967
+ function (res) {
1968
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
1969
+ expect(res.groupCount, 'groupCount').to.eql(2);
1970
+
1971
+ expect(res.data, 'res.data').to.be.instanceof(Array);
1972
+ expect(res.data, 'group list length').to.have.lengthOf(2);
1973
+
1974
+ expect(res.data[0].key, 'group 1.key').to.not.be.undefined;
1975
+ expect(res.data[0].items, `group 1.items`).to.be.null;
1976
+ expect(res.data[0].count, `group 1.count`).to.eql(90);
1977
+ expect(res.data[1].key, 'group 2.key').to.not.be.undefined;
1978
+ expect(res.data[1].items, `group 2.items`).to.be.null;
1979
+ expect(res.data[1].count, `group 2.count`).to.eql(10);
1980
+ }
1981
+ );
1982
+ });
1983
+
1984
+ test('list should group with groupInterval month', function (tdone) {
1985
+ testQueryValues(
1986
+ tdone,
1987
+ {
1988
+ group: [
1989
+ {
1990
+ selector: 'date1',
1991
+ groupInterval: 'month',
1992
+ },
1993
+ ],
1994
+ requireTotalCount: true,
1995
+ requireGroupCount: true,
1996
+ },
1997
+ function (res) {
1998
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
1999
+ expect(res.groupCount, 'groupCount').to.eql(4);
2000
+
2001
+ expect(res.data, 'res.data').to.be.instanceof(Array);
2002
+ expect(res.data, 'group list length').to.have.lengthOf(4);
2003
+
2004
+ expect(res.data[0].key, 'group 1.key').to.eql(1);
2005
+ expect(res.data[0].items, `group 1.items`).to.be.null;
2006
+ expect(res.data[0].count, `group 1.count`).to.eql(31);
2007
+ expect(res.data[1].key, 'group 2.key').to.eql(2);
2008
+ expect(res.data[1].items, `group 2.items`).to.be.null;
2009
+ expect(res.data[1].count, `group 2.count`).to.eql(28);
2010
+ expect(res.data[2].key, 'group 3.key').to.eql(3);
2011
+ expect(res.data[2].items, `group 3.items`).to.be.null;
2012
+ expect(res.data[2].count, `group 3.count`).to.eql(31);
2013
+ expect(res.data[3].key, 'group 4.key').to.eql(4);
2014
+ expect(res.data[3].items, `group 4.items`).to.be.null;
2015
+ expect(res.data[3].count, `group 4.count`).to.eql(10);
2016
+ }
2017
+ );
2018
+ });
2019
+
2020
+ test('list should group with groupInterval dayOfWeek', function (tdone) {
2021
+ testQueryValues(
2022
+ tdone,
2023
+ {
2024
+ group: [
2025
+ {
2026
+ selector: 'date1',
2027
+ groupInterval: 'dayOfWeek',
2028
+ },
2029
+ ],
2030
+ requireTotalCount: true,
2031
+ requireGroupCount: true,
2032
+ },
2033
+ function (res) {
2034
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
2035
+ expect(res.groupCount, 'groupCount').to.eql(7);
2036
+
2037
+ expect(res.data, 'res.data').to.be.instanceof(Array);
2038
+ expect(res.data, 'group list length').to.have.lengthOf(7);
2039
+ }
2040
+ );
2041
+ });
2042
+
2043
+ test('list should group with groupInterval 2', function (tdone) {
2044
+ testQueryValues(
2045
+ tdone,
2046
+ {
2047
+ group: [
2048
+ {
2049
+ selector: 'int1',
2050
+ groupInterval: 2,
2051
+ },
2052
+ ],
2053
+ requireTotalCount: true,
2054
+ requireGroupCount: true,
2055
+ },
2056
+ function (res) {
2057
+ //console.log("Result is ", JSON.stringify(res, null, 2));
2058
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
2059
+ expect(res.groupCount, 'groupCount').to.eql(5);
2060
+
2061
+ expect(res.data, 'res.data').to.be.instanceof(Array);
2062
+ expect(res.data, 'group list length').to.have.lengthOf(5);
2063
+
2064
+ expect(res.data[0].key, 'group 1 key').to.eql(0);
2065
+ expect(res.data[0].count, 'group 1 count').to.eql(20);
2066
+ expect(res.data[1].key, 'group 2 key').to.eql(2);
2067
+ expect(res.data[1].count, 'group 2 count').to.eql(20);
2068
+ expect(res.data[2].key, 'group 3 key').to.eql(4);
2069
+ expect(res.data[2].count, 'group 3 count').to.eql(20);
2070
+ expect(res.data[3].key, 'group 4 key').to.eql(6);
2071
+ expect(res.data[3].count, 'group 4 count').to.eql(20);
2072
+ expect(res.data[4].key, 'group 5 key').to.eql(8);
2073
+ expect(res.data[4].count, 'group 5 count').to.eql(20);
2074
+ }
2075
+ );
2076
+ });
2077
+
2078
+ test('list should group with groupInterval quarter and summaries', function (tdone) {
2079
+ testQueryValues(
2080
+ tdone,
2081
+ {
2082
+ group: [
2083
+ {
2084
+ selector: 'date1',
2085
+ groupInterval: 'quarter',
2086
+ },
2087
+ ],
2088
+ groupSummary: [
2089
+ {
2090
+ selector: 'int1',
2091
+ summaryType: 'count',
2092
+ },
2093
+ ],
2094
+ totalSummary: [
2095
+ {
2096
+ selector: 'int1',
2097
+ summaryType: 'count',
2098
+ },
2099
+ ],
2100
+ requireTotalCount: true,
2101
+ requireGroupCount: true,
2102
+ },
2103
+ function (res) {
2104
+ expect(res.totalCount, 'totalCount').to.eql(TESTRECORD_COUNT);
2105
+ expect(res.groupCount, 'groupCount').to.eql(2);
2106
+
2107
+ expect(res.data, 'res.data').to.be.instanceof(Array);
2108
+ expect(res.data, 'group list length').to.have.lengthOf(2);
2109
+
2110
+ expect(res.summary, 'res.summary').to.be.instanceof(Array);
2111
+ expect(res.summary, 'res.summary length').to.have.lengthOf(1);
2112
+
2113
+ expect(res.data[0].key, 'group 1.key').to.not.be.undefined;
2114
+ expect(res.data[0].items, `group 1.items`).to.be.null;
2115
+ expect(res.data[0].count, `group 1.count`).to.eql(90);
2116
+ expect(res.data[0].summary, 'group 1 summary').to.be.instanceof(
2117
+ Array
2118
+ );
2119
+ expect(
2120
+ res.data[0].summary,
2121
+ 'group 1 summary length'
2122
+ ).to.have.lengthOf(1);
2123
+
2124
+ expect(res.data[1].key, 'group 2.key').to.not.be.undefined;
2125
+ expect(res.data[1].items, `group 2.items`).to.be.null;
2126
+ expect(res.data[1].count, `group 2.count`).to.eql(10);
2127
+ expect(res.data[1].summary, 'group 2 summary').to.be.instanceof(
2128
+ Array
2129
+ );
2130
+ expect(
2131
+ res.data[1].summary,
2132
+ 'group 2 summary length'
2133
+ ).to.have.lengthOf(1);
2134
+ }
2135
+ );
2136
+ });
2137
+
2138
+ // The following two tests are meant to test the timezoneOffset correction.
2139
+ // However, since the mechanism depends on the server to use the correct
2140
+ // time, it's hard to remote-control this so that the tests don't fail
2141
+ // on occasion. I'm commenting them - as far as I'm aware, the mechanism
2142
+ // works correctly in reality and I'll debug if necessary.
2143
+
2144
+ // test('month and dow should work correctly for May 1st 2017', function (tdone) {
2145
+ // // mongodb aggregation operators that extract Date details work on
2146
+ // // UTC only - so they need to have a timezone offset to work with
2147
+ // // in order to deliver the correct results if the local timezone
2148
+ // // is not UTC.
2149
+ // // The test is only meaningful if there's a difference between local timezone
2150
+ // // and UTC. Unfortunately mongodb seems to use the server time to handle
2151
+ // // its persistence, so mocking a timezone from JS doesn't make any
2152
+ // // difference.
2153
+
2154
+ // // I have noticed that this test fails right now (2017-12-11) because the Docker
2155
+ // // image I run for Mongo doesn't seem to know what the correct time zone is...
2156
+ // // This wouldn't be an issue in real life since we can assume that server
2157
+ // // time zones and dst are going to change according to the real world, but it
2158
+ // // does make it clear that it's not easy passing the "correct" timezoneOffset
2159
+ // // from the client.
2160
+
2161
+ // testQueryValues(
2162
+ // tdone,
2163
+ // {
2164
+ // filter: [['date1.Month', '=', 5], 'and', ['date1.DayOfWeek', '=', 1]],
2165
+ // requireTotalCount: true,
2166
+ // },
2167
+ // function (res) {
2168
+ // //console.log('Result is ', JSON.stringify(res, null, 2));
2169
+ // expect(res.totalCount, 'totalCount').to.eql(1);
2170
+ // expect(res.data).to.have.lengthOf(1);
2171
+ // },
2172
+ // function (collection) {
2173
+ // return [
2174
+ // collection.insertOne({
2175
+ // // forgive JavaScript - this is the 1st of May
2176
+ // date1: new Date(2017, 4, 1),
2177
+ // date2: new Date(2017, 4, 1),
2178
+ // int1: 10,
2179
+ // int2: 10,
2180
+ // string: 'something',
2181
+ // }),
2182
+ // ];
2183
+ // },
2184
+ // {
2185
+ // timezoneOffset: new Date().getTimezoneOffset(),
2186
+ // }
2187
+ // );
2188
+ // });
2189
+
2190
+ // test('month grouping should work correctly for May 1st 2017', function (tdone) {
2191
+ // // mongodb aggregation operators that extract Date details work on
2192
+ // // UTC only - so they need to have a timezone offset to work with
2193
+ // // in order to deliver the correct results if the local timezone
2194
+ // // is not UTC.
2195
+ // // The test is only meaningful if there's a difference between local timezone
2196
+ // // and UTC. Unfortunately mongodb seems to use the server time to handle
2197
+ // // its persistence, so mocking a timezone from JS doesn't make any
2198
+ // // difference.
2199
+
2200
+ // // I have noticed that this test fails right now (2017-12-11) because the Docker
2201
+ // // image I run for Mongo doesn't seem to know what the correct time zone is...
2202
+ // // This wouldn't be an issue in real life since we can assume that server
2203
+ // // time zones and dst are going to change according to the real world, but it
2204
+ // // does make it clear that it's not easy passing the "correct" timezoneOffset
2205
+ // // from the client.
2206
+
2207
+ // testQueryValues(
2208
+ // tdone,
2209
+ // {
2210
+ // group: [
2211
+ // {
2212
+ // selector: 'date1',
2213
+ // groupInterval: 'month',
2214
+ // },
2215
+ // ],
2216
+ // requireGroupCount: true,
2217
+ // requireTotalCount: true,
2218
+ // },
2219
+ // function (res) {
2220
+ // //console.log('Result is ', JSON.stringify(res, null, 2));
2221
+ // expect(res.totalCount, 'totalCount').to.eql(1);
2222
+ // expect(res.groupCount).to.eql(1);
2223
+ // expect(res.data).to.have.lengthOf(1);
2224
+ // expect(res.data[0].key).to.eql(5); // month May after mongo $month
2225
+ // },
2226
+ // function (collection) {
2227
+ // return [
2228
+ // collection.insertOne({
2229
+ // // forgive JavaScript - this is the 1st of May
2230
+ // date1: new Date(2017, 4, 1),
2231
+ // date2: new Date(2017, 4, 1),
2232
+ // int1: 10,
2233
+ // int2: 10,
2234
+ // string: 'something',
2235
+ // }),
2236
+ // ];
2237
+ // },
2238
+ // {
2239
+ // timezoneOffset: new Date().getTimezoneOffset(),
2240
+ // }
2241
+ // );
2242
+ // });
2243
+
2244
+ test('query should work correctly for May 1st 2017', function (tdone) {
2245
+ // see comment above - this test is meaningless if there's no difference
2246
+ // between local timezone and UTC. If there is a difference, the test
2247
+ // makes sure that data persistence and querying work together the way
2248
+ // they should, even if the mongodb level date is stored in UTC.
2249
+ // This is mainly for documentation purposes, it happens automatically.
2250
+ testQueryValues(
2251
+ tdone,
2252
+ {
2253
+ filter: ['date1', '=', new Date(2017, 4, 1)],
2254
+ requireTotalCount: true,
2255
+ },
2256
+ function (res) {
2257
+ //console.log('Result is ', JSON.stringify(res, null, 2));
2258
+ expect(res.totalCount, 'totalCount').to.eql(1);
2259
+ expect(res.data).to.have.lengthOf(1);
2260
+
2261
+ expect(new Date(res.data[0].date1)).to.eql(new Date(2017, 4, 1));
2262
+ },
2263
+ function (collection) {
2264
+ return [
2265
+ collection.insertOne({
2266
+ // forgive JavaScript - this is the 1st of May
2267
+ date1: new Date(2017, 4, 1),
2268
+ date2: new Date(2017, 4, 1),
2269
+ int1: 10,
2270
+ int2: 10,
2271
+ string: 'something',
2272
+ }),
2273
+ ];
2274
+ }
2275
+ );
2276
+ });
2277
+
2278
+ test('equalsObjectId operator with ObjectId value', function (tdone) {
2279
+ // this query also works with the standard '=' operator
2280
+ const testId = new ObjectId('0123456789abcdef01234567');
2281
+ testQueryValues(
2282
+ tdone,
2283
+ {
2284
+ filter: ['idField', 'equalsObjectId', testId],
2285
+ requireTotalCount: true,
2286
+ },
2287
+ function (res) {
2288
+ expect(res.totalCount, 'totalCount').to.eql(1);
2289
+ },
2290
+ function (collection) {
2291
+ return [collection.insertOne({ idField: testId })];
2292
+ }
2293
+ );
2294
+ });
2295
+
2296
+ test('equalsObjectId operator with string value', function (tdone) {
2297
+ // this query works only with the equalsObjectId operator
2298
+ const testId = new ObjectId('0123456789abcdef01234567');
2299
+ testQueryValues(
2300
+ tdone,
2301
+ {
2302
+ filter: ['idField', 'equalsObjectId', testId.toString()],
2303
+ requireTotalCount: true,
2304
+ },
2305
+ function (res) {
2306
+ expect(res.totalCount, 'totalCount').to.eql(1);
2307
+ },
2308
+ function (collection) {
2309
+ return [collection.insertOne({ idField: testId })];
2310
+ }
2311
+ );
2312
+ });
2313
+
2314
+ test('issue #40', function (tdone) {
2315
+ testQueryValues(
2316
+ tdone,
2317
+ {
2318
+ filter: [
2319
+ ['date1', '>=', new Date(2017, 0, 15)],
2320
+ 'and',
2321
+ ['date1', '<', new Date(2017, 0, 16)],
2322
+ ],
2323
+ requireTotalCount: true,
2324
+ },
2325
+ function (res) {
2326
+ expect(res.totalCount, 'totalCount').to.eql(1);
2327
+ expect(res.data).to.have.lengthOf(1);
2328
+ expect(new Date(res.data[0].date1)).to.eql(new Date(2017, 0, 15));
2329
+ }
2330
+ );
2331
+ });
2332
+ });
2333
+ });