summaryrefslogtreecommitdiffstats
path: root/node_modules/sift/test
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/sift/test')
-rw-r--r--node_modules/sift/test/basic-test.js237
-rw-r--r--node_modules/sift/test/immutable-test.js20
-rwxr-xr-xnode_modules/sift/test/objects-test.js409
-rw-r--r--node_modules/sift/test/operations-test.js203
4 files changed, 869 insertions, 0 deletions
diff --git a/node_modules/sift/test/basic-test.js b/node_modules/sift/test/basic-test.js
new file mode 100644
index 0000000..799f0d0
--- /dev/null
+++ b/node_modules/sift/test/basic-test.js
@@ -0,0 +1,237 @@
+import * as assert from 'assert';
+import sift, {indexOf as siftIndexOf} from '..';
+
+describe(__filename + '#', function() {
+
+ it('doesn\'t sort arrays', function () {
+ var values = sift({
+ $or: [3, 2, 1]
+ }, [9,8,7,6,5,4,3,2,1]);
+
+
+ assert.equal(values.length, 3);
+ assert.equal(values[0], 3);
+ assert.equal(values[1], 2);
+ assert.equal(values[2], 1);
+ });
+
+ it('can create a custom selector, and use it', function () {
+ var sifter = sift({ age: { $gt: 5}}, function (item) {
+ return item.person;
+ });
+
+ var people = [{ person: { age: 6 }}],
+ filtered = people.filter(sifter);
+
+
+ assert.equal(filtered.length, 1);
+ assert.equal(filtered[0], people[0]);
+ });
+
+ it('throws an error if the operation is invalid', function () {
+
+ var err;
+ try {
+ sift({$aaa:1})('b');
+ } catch (e) {
+ err = e;
+ }
+
+ assert.equal(err.message, 'Unknown operation $aaa');
+
+ });
+
+ it('can use a custom selector as the 3rd param', function () {
+
+ var people = [{ person: { age: 6 }}];
+
+ var filtered = sift({ age: { $gt: 5}}, people, function (item) {
+ return item.person;
+ });
+
+ assert.equal(filtered.length, 1);
+ assert.equal(filtered[0], people[0]);
+ });
+
+ it('can get the first index of a matching element', function () {
+ var index = siftIndexOf({ val: { $gt: 5}}, [{val: 4}, {val: 3}, {val: 6}, {val: 7}]);
+
+ assert.equal(index, 2);
+ });
+
+ it('returns -1 as index if no matching element is found', function () {
+ var index = siftIndexOf({ val: { $gt: 7}}, [{val: 4}, {val: 3}, {val: 6}, {val: 7}]);
+
+ assert.equal(index, -1);
+ });
+
+ it('can match empty arrays', function () {
+ var statusQuery = {$or: [{status: {$exists: false}},
+ {status: []},
+ {status: {$in: ['urgent', 'completed', 'today']}}
+ ]};
+
+ var filtered = sift(statusQuery, [{ status: [] },
+ { status: ['urgent'] },
+ { status: ['nope'] }
+ ]);
+
+ assert.equal(filtered.length, 2);
+ });
+
+ it('$ne: null does not hit when field is present', function(){
+ var sifter = sift({age: {$ne: null}});
+
+ var people = [
+ {age: 'matched'},
+ {missed: 1}
+ ];
+ var filtered = people.filter(sifter);
+
+ assert.equal(filtered.length, 1);
+ assert.equal(filtered[0].age, 'matched');
+ });
+
+ it('$ne does not hit when field is different', function () {
+ var sifter = sift({ age: { $ne: 5 }});
+
+ var people = [{ age: 5 }],
+ filtered = people.filter(sifter);
+
+ assert.equal(filtered.length, 0);
+ });
+
+ it('$ne does hit when field exists with different value', function () {
+ var sifter = sift({ age: { $ne: 4 }});
+
+ var people = [{ age: 5 }],
+ filtered = people.filter(sifter);
+
+ assert.equal(filtered.length, 1);
+ });
+
+ it('$ne does hit when field does not exist', function(){
+ var sifter = sift({ age: { $ne: 5 }});
+
+ var people = [{}],
+ filtered = people.filter(sifter);
+
+ assert.equal(filtered.length, 1);
+ });
+
+ it('$eq matches objects that serialize to the same value', function() {
+ var counter = 0;
+ function Book(name) {
+ this.name = name;
+ this.copyNumber = counter;
+ this.toJSON = function() {
+ return this.name; // discard the copy when serializing.
+ };
+ counter += 1;
+ }
+
+ var warAndPeace = new Book('War and Peace');
+
+ var sifter = sift({ $eq: warAndPeace});
+
+ var books = [ new Book('War and Peace')];
+ var filtered = books.filter(sifter);
+
+ assert.equal(filtered.length, 1);
+ });
+
+ it('$neq does not match objects that serialize to the same value', function() {
+ var counter = 0;
+ function Book(name) {
+ this.name = name;
+ this.copyNumber = counter;
+ this.toJSON = function() {
+ return this.name; // discard the copy when serializing.
+ };
+ counter += 1;
+ }
+
+ var warAndPeace = new Book('War and Peace');
+
+ var sifter = sift({ $ne: warAndPeace});
+
+ var books = [ new Book('War and Peace')];
+ var filtered = books.filter(sifter);
+
+ assert.equal(filtered.length, 0);
+ });
+
+ // https://gist.github.com/jdnichollsc/00ea8cf1204b17d9fb9a991fbd1dfee6
+ it('returns a period between start and end dates', function() {
+
+ var product = {
+ 'productTypeCode': 'productTypeEnergy',
+ 'quantities': [
+ {
+ 'period': {
+ 'startDate': new Date('2017-01-13T05:00:00.000Z'),
+ 'endDate': new Date('2017-01-31T05:00:00.000Z'),
+ 'dayType': {
+ 'normal': true,
+ 'holiday': true
+ },
+ 'specificDays': [
+ 'monday',
+ 'wednesday',
+ 'friday'
+ ],
+ 'loadType': {
+ 'high': true,
+ 'medium': false,
+ 'low': false
+ }
+ },
+ 'type': 'DemandPercentage',
+ 'quantityValue': '44'
+ },
+ {
+ 'period': {
+ 'startDate': new Date('2017-01-13T05:00:00.000Z'),
+ 'endDate': new Date('2017-01-31T05:00:00.000Z'),
+ 'dayType': {
+ 'normal': true,
+ 'holiday': true
+ },
+ 'loadType': {
+ 'high': false,
+ 'medium': true,
+ 'low': false
+ }
+ },
+ 'type': 'Value',
+ 'quantityValue': '22'
+ }
+ ]
+ };
+
+ var period = {
+ 'startDate': new Date('2017-01-08T05:00:00.000Z'),
+ 'endDate': new Date('2017-01-29T05:00:00.000Z'),
+ 'dayType': {
+ 'normal': true,
+ 'holiday': true
+ },
+ 'loadType': {
+ 'high': true,
+ 'medium': false,
+ 'low': true
+ },
+ specificPeriods : ['3', '4', '5-10']
+ };
+
+
+ var results = sift({
+ $and: [
+ { 'period.startDate': { $lte : period.endDate } },
+ { 'period.endDate': { $gte : period.startDate } }
+ ]
+ }, product.quantities);
+
+ assert.equal(results.length, 2);
+ });
+});
diff --git a/node_modules/sift/test/immutable-test.js b/node_modules/sift/test/immutable-test.js
new file mode 100644
index 0000000..8685d30
--- /dev/null
+++ b/node_modules/sift/test/immutable-test.js
@@ -0,0 +1,20 @@
+import * as assert from 'assert';
+import * as Immutable from 'immutable';
+
+import sift from '..';
+const ObjectID = require('bson').ObjectID;
+
+describe(__filename + '#', function() {
+
+
+
+ var topic = Immutable.List([1, 2, 3, 4, 5, 6, 6, 4, 3]);
+
+
+ var persons = Immutable.fromJS([{ person: {age: 3} }, { person: {age: 5} }, { person: {age: 8} }]);
+
+ it('works with Immutable.Map in a Immutable.List', function() {
+ assert.equal(sift({ 'person.age' : { $gt: 4 } }, persons).size, 2);
+ assert.equal(persons.filter(sift({ 'person.age' : { $gt: 4 } })).size, 2);
+ });
+});
diff --git a/node_modules/sift/test/objects-test.js b/node_modules/sift/test/objects-test.js
new file mode 100755
index 0000000..951349b
--- /dev/null
+++ b/node_modules/sift/test/objects-test.js
@@ -0,0 +1,409 @@
+import assert from 'assert';
+import sift from '..';
+
+describe(__filename + '#', function () {
+
+
+ var topic = [
+ {
+ name: 'craig',
+ age: 90001,
+ tags: ['coder', 'programmer', 'traveler', 'photographer'],
+ address: {
+ city: 'Minneapolis',
+ state: 'MN',
+ phone: '9999999999'
+ },
+ tags: ['photos', 'cook'],
+ hobbies: [
+ {
+ name: 'programming',
+ description: 'some desc'
+ },
+ {
+ name: 'cooking'
+ },
+ {
+ name: 'photography',
+ places: ['haiti', 'brazil', 'costa rica']
+ },
+ {
+ name: 'backpacking'
+ }
+ ]
+ },
+ {
+ name: 'tim',
+ age: 90001,
+ tags: ['traveler', 'photographer'],
+ address: {
+ city: 'St. Paul',
+ state: 'MN',
+ phone: '765765756765'
+ },
+ tags: ['dj'],
+ hobbies: [
+ {
+ name: 'biking',
+ description: 'some desc'
+ },
+ {
+ name: 'DJ'
+ },
+ {
+ name: 'photography',
+ places: ['costa rica']
+ }
+ ]
+ }
+ ];
+ xit('throws error if $not is incorrect', function () {
+ assert.throws(function () {
+ sift({
+ $not: ['abc']
+ }, topic);
+ }, Error);
+ });
+ it('has sifted through photography in brazil count of 1', function () {
+ var sifted = sift({
+ hobbies: {
+ name: 'photography',
+ places: {
+ $in: ['brazil']
+ }
+ }
+ }, topic);
+ assert.equal(sifted.length, 1);
+ });
+ it('has sifted through photography in brazil, haiti, and costa rica count of 1', function () {
+ var sifted = sift({
+ hobbies: {
+ name: 'photography',
+ places: {
+ $all: ['brazil', 'haiti', 'costa rica']
+ }
+ }
+ }, topic);
+ assert.equal(sifted.length, 1);
+ assert.equal(sifted[0], topic[0]);
+ });
+ it('has a sifted hobbies of photography, cooking, or biking count of 2', function () {
+ var sifted = sift({
+ hobbies: {
+ name: {
+ $in: ['photography', 'cooking', 'biking']
+ }
+ }
+ }, topic);
+ assert.equal(sifted.length, 2);
+ });
+ it('has sifted to complex count of 2', function () {
+ var sifted = sift({
+ hobbies: {
+ name: 'photography',
+ places: {
+ $in: ['costa rica']
+ }
+ },
+ address: {
+ state: 'MN',
+ phone: {
+ $exists: true
+ }
+ }
+ }, topic);
+
+ assert.equal(sifted.length, 2);
+ });
+ it('has sifted to complex count of 0', function () {
+ var sifted = sift({
+ hobbies: {
+ name: 'photos',
+ places: {
+ $in: ['costa rica']
+ }
+ }
+ }, topic);
+ assert.equal(sifted.length, 0);
+ });
+ it('has sifted subobject hobbies count of 3', function () {
+ var sifted = sift({
+ 'hobbies.name': 'photography'
+ }, topic);
+ assert.equal(sifted.length, 2);
+ });
+ it('has sifted dot-notation hobbies of photography, cooking, and biking count of 3', function () {
+ var sifted = sift({
+ 'hobbies.name': {
+ $in: ['photography', 'cooking', 'biking']
+ }
+ }, topic);
+ assert.equal(sifted.length, 2);
+ });
+ it('has sifted to complex dot-search count of 2', function () {
+ var sifted = sift({
+ 'hobbies.name': 'photography',
+ 'hobbies.places': {
+ $in: ['costa rica']
+ },
+ 'address.state': 'MN',
+ 'address.phone': {
+ $exists: true
+ }
+ }, topic);
+ assert.equal(sifted.length, 2);
+ });
+ it('has sifted with selector function count of 2', function () {
+ var sifted = sift({
+ 'name': 'photography',
+ 'places': {
+ $in: ['costa rica']
+ }
+ }, topic, function (item) {
+ return item.hobbies;
+ });
+ assert.equal(sifted.length, 2);
+ });
+
+ describe('nesting', function () {
+ it('$eq for nested object', function () {
+ var sifted = sift({'sub.num': {'$eq': 10}}, loremArr);
+ assert(sifted.length > 0);
+ sifted.forEach(function (v) {
+ assert.equal(10, v.sub.num);
+ });
+ });
+
+ it('$ne for nested object', function () {
+ var sifted = sift({'sub.num': {'$ne': 10}}, loremArr);
+ assert(sifted.length > 0);
+ sifted.forEach(function (v) {
+ assert.notEqual(10, v.sub.num);
+ });
+ });
+
+ it('$regex for nested object (one missing key)', function () {
+ var persons = [{
+ id: 1,
+ prof: 'Mr. Moriarty'
+ }, {
+ id: 2,
+ prof: 'Mycroft Holmes'
+ }, {
+ id: 3,
+ name: 'Dr. Watson',
+ prof: 'Doctor'
+ }, {
+ id: 4,
+ name: 'Mr. Holmes',
+ prof: 'Detective'
+ }];
+ var q = { 'name': { '$regex': 'n' } };
+ var sifted = sift(q, persons);
+ assert.deepEqual(sifted, [{
+ id: 3,
+ name: 'Dr. Watson',
+ prof: 'Doctor'
+ }]);
+ });
+ });
+
+ describe('arrays of objects', function () {
+ var objects = [
+ {
+ things: [
+ {
+ id: 123
+ }, {
+ id: 456
+ }
+ ]
+ }, {
+ things: [
+ {
+ id: 123
+ },
+ {
+ id: 789
+ }
+ ]
+ }
+ ];
+ it('$eq for array of objects, matches if at least one exists', function () {
+ let q = {
+ 'things.id': 123
+ }
+ var sifted = sift(q, objects)
+ assert.deepEqual(sifted, objects)
+ let q2 = {
+ 'things.id': 789
+ }
+ var sifted2 = sift(q2, objects)
+ assert.deepEqual(sifted2, [objects[1]])
+ })
+ it('$ne for array of objects, returns if none of the array elements match the query', function () {
+ let q = {
+ 'things.id': {
+ $ne: 123
+ }
+ }
+ var sifted = sift(q, objects)
+ assert.deepEqual(sifted, [])
+ let q2 = {
+ 'things.id': {
+ $ne: 789
+ }
+ }
+ var sifted2 = sift(q2, objects)
+ assert.deepEqual(sifted2, [objects[0]])
+ })
+ })
+
+ describe('$where', function() {
+
+ var couples = [{
+ name: 'SMITH',
+ person: [{
+ firstName: 'craig',
+ gender: 'female',
+ age: 29
+ }, {
+ firstName: 'tim',
+ gender: 'male',
+ age: 32
+ }
+
+ ]
+ }, {
+ name: 'JOHNSON',
+ person: [{
+ firstName: 'emily',
+ gender: 'female',
+ age: 35
+ }, {
+ firstName: 'jacob',
+ gender: 'male',
+ age: 32
+ }
+
+ ]
+ }];
+
+ it('can filter people', function() {
+ var results = sift({'person': {$elemMatch: { 'gender': 'female', 'age': {'$lt': 30}}}}, couples);
+ assert.equal(results[0].name, 'SMITH');
+
+ var results = sift({'person': {$elemMatch: { 'gender': 'male', 'age': {'$lt': 30}}}}, [couples[0]]);
+ assert.equal(results.length, 0);
+ });
+ });
+
+ describe('keypath', function () {
+
+ var arr = [
+ {
+ a: {
+ b: {
+ c: 1,
+ c2: 1
+ }
+ }
+ }
+ ]
+ it('can be used', function () {
+ assert.equal(sift({'a.b.c':1})(arr[0]), true);
+ });
+ });
+});
+
+
+var loremArr = [
+ {
+ 'num': 1,
+ 'pum': 1,
+ 'sub': {
+ 'num': 1,
+ 'pum': 1
+ }
+ },
+ {
+ 'num': 2,
+ 'pum': 2,
+ 'sub': {
+ 'num': 2,
+ 'pum': 2
+ }
+ },
+ {
+ 'num': 3,
+ 'pum': 3,
+ 'sub': {
+ 'num': 3,
+ 'pum': 3
+ }
+ },
+ {
+ 'num': 4,
+ 'pum': 4,
+ 'sub': {
+ 'num': 4,
+ 'pum': 4
+ }
+ },
+ {
+ 'num': 5,
+ 'pum': 5,
+ 'sub': {
+ 'num': 5,
+ 'pum': 5
+ }
+ },
+ {
+ 'num': 6,
+ 'pum': 6,
+ 'sub': {
+ 'num': 6,
+ 'pum': 6
+ }
+ },
+ {
+ 'num': 7,
+ 'pum': 7,
+ 'sub': {
+ 'num': 7,
+ 'pum': 7
+ }
+ },
+ {
+ 'num': 8,
+ 'pum': 8,
+ 'sub': {
+ 'num': 8,
+ 'pum': 8
+ }
+ },
+ {
+ 'num': 9,
+ 'pum': 9,
+ 'sub': {
+ 'num': 9,
+ 'pum': 9
+ }
+ },
+ {
+ 'num': 10,
+ 'pum': 10,
+ 'sub': {
+ 'num': 10,
+ 'pum': 10
+ }
+ },
+ {
+ 'num': 11,
+ 'pum': 11,
+ 'sub': {
+ 'num': 10,
+ 'pum': 10
+ }
+ }
+];
diff --git a/node_modules/sift/test/operations-test.js b/node_modules/sift/test/operations-test.js
new file mode 100644
index 0000000..337600e
--- /dev/null
+++ b/node_modules/sift/test/operations-test.js
@@ -0,0 +1,203 @@
+import * as assert from 'assert';
+import sift from '..';
+var ObjectID = require('bson').ObjectID;
+
+describe(__filename + '#', function () {
+
+
+ [
+ // $eq
+ [{$eq:5}, [5,'5', 6], [5]],
+ ['5', [5,'5', 6], ['5']],
+ [false, [false,'false', true], [false]],
+ [true, [1, true], [true]],
+ [0, [0,'0'], [0]],
+ [null, [null], [null]],
+ [void 0, [void 0, null], [void 0]],
+ [1, [2,3,4,5], []],
+ [1, [[1]], [[1]]],
+ [new Date(1), [new Date(), new Date(1), new Date(2), new Date(3)], [new Date(1)]],
+ [/^a/, ['a','ab','abc','b','bc'], ['a','ab','abc']],
+
+ [function(b) { return b === 1; }, [1,2,3],[1]],
+
+ [ObjectID('54dd5546b1d296a54d152e84'),[ObjectID(),ObjectID('54dd5546b1d296a54d152e84')],[ObjectID('54dd5546b1d296a54d152e84')]],
+
+ // $ne
+ [{$ne:5}, [5, '5', 6], ['5', 6]],
+ [{$ne:'5'}, ['5', 6], [6]],
+ [{$ne:false}, [false], []],
+ [{$ne:void 0}, [false, 0, '0', void 0], [false, 0, '0']],
+ [{$ne:/^a/}, ['a','ab','abc','b','bc'], ['b','bc']],
+ [{$ne:1}, [[2],[1]], [[2]]],
+ [{groups:{$ne:111}}, [{groups:[111,222,333,444]},{groups:[222,333,444]}],[{groups:[222,333,444]}]],
+
+ // $lt
+ [{$lt:5}, [3,4,5,6],[3,4]],
+ [{$lt:'c'}, ['a','b','c'],['a','b']],
+ [{$lt:null}, [-3,-4], []],
+ [{$lt:new Date(3)}, [new Date(1), new Date(2), new Date(3)],[new Date(1), new Date(2)]],
+
+ // $lte
+ [{$lte:5}, [3,4,5,6],[3,4,5]],
+ [{groups:{$lt:5}}, [{groups:[1,2,3,4]}, {groups:[7,8]}], [{groups:[1,2,3,4]}]],
+
+ // $gt
+ [{$gt:5}, [3,4,5,6],[6]],
+ [{$gt:null}, [3,4], []],
+ [{groups:{$gt:5}}, [{groups:[1,2,3,4]}, {groups:[7,8]}], [{groups:[7,8]}]],
+
+ // $gte
+ [{$gte:5}, [3,4,5,6],[5, 6]],
+ [{groups:{$gte:5}}, [{groups:[1,2,3,4]}, {groups:[7,8]}], [{groups:[7,8]}]],
+
+ // $mod
+ [{$mod:[2,1]}, [1,2,3,4,5,6],[1,3,5]],
+ [{groups:{$mod:[2,0]}}, [{groups:[1,2,3,4]}, {groups:[7,9]}], [{groups:[1,2,3,4]}]],
+
+ // $exists
+ [{$exists:false}, [0,false,void 0, null],[]],
+ [{$exists:true}, [0,false,void 0, 1, {}],[0, false, void 0, 1, {}]],
+ [{'a.b': {$exists: true}}, [{a: {b: 'exists'}}, {a: {c: 'does not exist'}}], [{a: {b: 'exists'}}]],
+ [{field: { $exists: false }}, [{a: 1}, {a: 2, field: 5}, {a: 3, field: 0}, {a: 4, field: undefined}, {a: 5}],[{a: 1}, {a: 5}]],
+
+ // $in
+ // TODO - {$in:[Date]} doesn't work - make it work?
+ [{$in:[0,false,1,'1']},[0,1,2,3,4,false],[0,1,false]],
+ [{$in:[1,'1','2']},['1','2','3'],['1','2']],
+ [{$in:[new Date(1)]},[new Date(1), new Date(2)],[new Date(1)]],
+ [{'a.b.status':{'$in': [0]}}, [{'a':{'b':[{'status':0}]}},{'a':{'b':[{'status':2}]}}],[{'a':{'b':[{'status':0}]}}]],
+ [{'a.b.status':{'$in': [0, 2]}}, [{'a':{'b':[{'status':0}]}},{'a':{'b':[{'status':2}]}}], [{'a':{'b':[{'status':0}]}},{'a':{'b':[{'status':2}]}}]],
+ [{'x': {$in: [{$regex: '.*aaa.*'}, {$regex: '.*bbb.*'}]}}, [{'x': {'b': 'aaa'}}, {'x': 'bbb'}, {'x': 'ccc'}, {'x': 'aaa'}], [{'x': 'bbb'}, {'x': 'aaa'}]],
+ [{'x': {$in: [/.*aaa.*/, /.*bbb.*/]}}, [{'x': {'b': 'aaa'}}, {'x': 'bbb'}, {'x': 'ccc'}, {'x': 'aaa'}], [{'x': 'bbb'}, {'x': 'aaa'}]],
+
+ // $nin
+ [{$nin:[0,false,1,'1']},[0,1,2,3,4,false],[2,3,4]],
+ [{$nin:[1,'1','2']},['1','2','3'],['3']],
+ [{$nin:[new Date(1)]},[new Date(1), new Date(2)],[new Date(2)]],
+ [{'root.notDefined': {$nin: [1, 2, 3]}}, [{'root': {'defined': 1337}}], [{'root': {'defined': 1337}}]],
+ [{'root.notDefined': {$nin: [1, 2, 3, null]}}, [{'root': {'defined': 1337}}], []],
+ [{'x': {$nin: [{$regex: '.*aaa.*'}, {$regex: '.*bbb.*'}]}}, [{'x': {'b': 'aaa'}}, {'x': 'bbb'}, {'x': 'ccc'}, {'x': 'aaa'}], [{'x': {'b': 'aaa'}},{'x': 'ccc'}]],
+ [{'x': {$nin: [/.*aaa.*/, /.*bbb.*/]}}, [{'x': {'b': 'aaa'}}, {'x': 'bbb'}, {'x': 'ccc'}, {'x': 'aaa'}], [{'x': {'b': 'aaa'}},{'x': 'ccc'}]],
+
+ // $not
+ [{$not:false},[0,false],[0]],
+ [{$not:0},[0, false, 1, 2, 3],[false, 1, 2, 3]],
+ [{$not:{$in:[1,2,3]}},[1,2,3,4,5,6],[4,5,6]], // with expressions
+
+ // $type
+ [{$type:Date}, [0,new Date(1)],[new Date(1)]],
+ [{$type:Number}, [0,false,1],[0,1]],
+ [{$type:Boolean}, [0,false, void 0],[false]],
+ [{$type:String}, ['1',1,false],['1']],
+
+ // $all
+ [{$all:[1,2,3]},[[1,2,3,4],[1,2,4]],[[1,2,3,4]]],
+ [{$all:[0,false]},[[0,1,2],[0,false],['0','false'],void 0],[[0,false]]],
+ [{$all:['1']},[[1]],[]],
+ [{$all:[new Date(1),new Date(2)]},[[new Date(1), new Date(2)],[new Date(1)]],[[new Date(1), new Date(2)]]],
+
+ // $size
+ [{$size:3},['123',[1,2,3],'1'],['123',[1,2,3]]],
+ [{$size:1},['123',[1,2,3],'1', void 0],['1']],
+
+ // $or
+ [{$or:[1,2,3]},[1,2,3,4],[1,2,3]],
+ [{$or:[{$ne:1},2]},[1,2,3,4,5,6],[2,3,4,5,6]],
+
+ // $nor
+ [{$nor:[1,2,3]},[1,2,3,4],[4]],
+ [{$nor:[{$ne:1},2]},[1,2,3,4,5,6],[1]],
+
+ // $and
+ [{$and:[{$gt:1},{$lt:4}]},[1,2,3,4],[2,3]],
+ [{$and: [{field: {$not: {$type: String}}}, {field: {$ne: null}}]}, [{a: 1, field: 1}, {a: 2, field: '2'}], [{a: 1, field: 1}]],
+
+ // $regex
+ [{$regex:'^a'},['a','ab','abc','bc','bcd'],['a','ab','abc']],
+ [{a:{$regex:'b|c'}}, [{a:['b']},{a:['c']},{a:'c'},{a:'d'}], [{a:['b']},{a:['c']},{a:'c'}]],
+ [{ folder: { $regex:'^[0-9]{4}$' }}, [{ folder:['1234','3212'] }], [{ folder:['1234','3212'] }]],
+
+ // $options
+ [{$regex:'^a', $options: 'i'},['a','Ab','abc','bc','bcd'],['a','Ab','abc']],
+ [{'text':{'$regex':'.*lis.*','$options':'i'}}, [{text:['Bob','Melissa','Joe','Sherry']}], [{text:['Bob','Melissa','Joe','Sherry']}]],
+
+ // undefined
+ [{$regex:'a'},[undefined, null, true, false, 0, 'aa'],['aa']],
+ [/a/,[undefined, null, true, false, 0, 'aa'],['aa']],
+ [/.+/,[undefined, null, true, false, 0, 'aa', {}],['aa']],
+
+ // Multiple conditions on an undefined root
+ [{'a.b': {$exists: true, $nin: [null]}}, [{a: {b: 'exists'}}, {a: {c: 'does not exist'}}], [{a: {b: 'exists'}}]],
+
+ // $where
+ [{$where:function () { return this.v === 1 }}, [{v:1},{v:2}],[{v:1}]],
+ [{$where:'this.v === 1'}, [{v:1},{v:2}],[{v:1}]],
+ [{$where:'obj.v === 1'}, [{v:1},{v:2}],[{v:1}]],
+
+ // $elemMatch
+ //{'person': {'$elemMatch': {'gender': 'male', 'age': {'$lt': 30}}}}
+ [
+ {a:{$elemMatch:{b:1,c:2}}},
+ [{a:{b:1,c:2}},{a:[{b:1,c:2,d:3}]},{a:{b:2,c:3}}], [{a:{b:1,c:2}},{a:[{b:1,c:2,d:3}]}]
+ ],
+ [{a:{$elemMatch:{b:2,c:{$gt:2}}}}, [{a:{b:1,c:2}},{a:{b:1,c:2,d:3}},[{a:{b:2,c:3}}]], [[{a:{b:2,c:3}}]]],
+ [
+ {tags: {$all: [{$elemMatch: {a: 1}}]}},
+ [{tags: [{a: 1}]}, {tags: [{a: 1}, {b: 1}]}], [{tags: [{a: 1}]}, {tags: [{a: 1}, {b: 1}]}]
+ ],
+
+ // dot-notation
+ [
+ {'a.b': /c/ },
+ [{a:{b:'c'}}, {a:{b:'cd'}}, {'a.b':'c'},{a:{b:'e'}}],
+ [{a:{b:'c'}}, {a:{b:'cd'}}]
+ ],
+ [
+ {'foo.0': 'baz' },
+ [{foo:['bar', 'baz']}, {foo:['baz', 'bar']}],
+ [{foo:['baz', 'bar']}]
+ ],
+ [
+ {'foo.0.name': 'baz' },
+ [{foo:[{ name: 'bar' }, { name: 'baz' }]}, {foo:[{ name: 'baz' }, { name: 'bar' }]}],
+ [{foo:[{ name: 'baz' }, { name: 'bar' }]}]
+ ],
+
+ // object.toString() tests
+ [
+ { $in: [{ toString: function(){ return 'a'; }}]},
+ [{toString: function(){ return 'a'; }}, {toString: function(){ return 'b' }}],
+ [{toString: function(){ return 'a'; }}]
+ ],
+ [
+ { $in: [{}]},
+ [{}, {}],
+ []
+ ],
+
+ // various comparisons
+ [
+ { c: { d: 'd' }},
+ [{ a: 'b', b: 'c', c: { d: 'd', e: 'e' }}, { c: { d: 'e' }}],
+ [{ a: 'b', b: 'c', c: { d: 'd', e: 'e' }}]
+ ],
+
+ // based on https://gist.github.com/jdnichollsc/00ea8cf1204b17d9fb9a991fbd1dfee6
+ [
+ { $and: [{ 'a.s': { $lte: new Date('2017-01-29T05:00:00.000Z') }}, {'a.e': { $gte: new Date('2017-01-08T05:00:00.000Z') }}]},
+ [{ a: { s: new Date('2017-01-13T05:00:00.000Z'), e: new Date('2017-01-31T05:00:00.000Z') }}],
+ [{ a: { s: new Date('2017-01-13T05:00:00.000Z'), e: new Date('2017-01-31T05:00:00.000Z') }}]
+ ],
+
+ ].forEach(function (operation, i) {
+
+ var filter = operation[0];
+ var array = operation[1];
+ var matchArray = operation[2];
+
+ it(i + ': ' + JSON.stringify(filter), function() {
+ assert.equal(JSON.stringify(array.filter(sift(filter))), JSON.stringify(matchArray));
+ });
+ });
+});