UNPKG

pursuit-core

Version:

A framework for building Fast JavaScript Object Property Matching Languages

350 lines (288 loc) 10.8 kB
/*jslint maxlen:140*/ /* global require */ 'use strict'; var buster = require('buster'), engine = require('../lib/pursuit-core'), // mocks mockDictionary2 = require('./mocks/mockDictionary2') ; var assert = buster.assert; var refute = buster.refute; var mockDictionary = { 'equals': function (value) { return this.getScope() + ' === ' + value; } }; buster.testCase('Pursuit Core', { 'should return a function': function () { assert.isFunction(engine({ dictionary: {}})); }, 'should return a function that compile a query language into a JavaScript function': function () { assert.isFunction(engine({ dictionary: {}})({})); }, 'should throw an exception if no dictionary object is given function': function () { assert.exception(function() { engine({}); }); }, 'should default to optimization if no optimization flag is set': function () { var config = {dictionary: {}}; engine(config); assert.isTrue(config.optimize); }, 'should be able to disable optimization': function () { var config = {dictionary: {}, optimize: false}; engine(config); assert.isFalse(config.optimize); }, 'should be able to return source as a string': function () { var query = engine({dictionary: {}}, 'string')({}); assert.isString(query); assert.equals(query, 'function anonymous(entry) { return true }'); }, 'should be able to return source as a function': function () { var pursuit = engine({dictionary: {}}, 'function'); assert.isFunction(engine({dictionary: {}})({})); }, 'should be able to use a dictionary': function () { refute.exception(function () { var dictionary = { '$eq': function (value) { return this.getScope() + ' === ' + value; }, '$lt': function (value) { return this.getScope() + ' > ' + value; } }; var pursuit = engine({ dictionary: dictionary }); var match = pursuit({ foo: { '$eq': 'bar' }, bar: { '$lt': 5 } }); var obj = [ {foo: 'bar', bar: 2}, {foo: 'bar', bar: 6}, {foo: 'baz', bar: 2} ]; assert.equals(obj.filter(match).length, 1); }); } }); buster.testCase('Pursuit Core Output', { 'should not throw an error when checking on a property and the input is undefined': function () { var pursuit = engine({dictionary: mockDictionary}); refute.exception(function() { pursuit({equals: 'bar'})(undefined); }); }, 'should be able to check values at root level': function () { var pursuit = engine({dictionary: mockDictionary}); var query = pursuit({ equals: 'foo' }); assert.isTrue(query('foo')); assert.isFalse(query('bar')); }, 'should not throw an error when checking on a nested property and the input is undefined': function () { var pursuit = engine({dictionary: mockDictionary}); refute.exception(function() { pursuit({foo: {equals: 'bar'}})(undefined); pursuit({foo: { bar: {equals: 'bar'}}})(undefined); pursuit({foo: { bar: { baz: {equals: 'bar'}}}})({ foo: { bar: undefined }}); }); }, 'should not throw an error when checking on a property and the input is null': function () { var pursuit = engine({dictionary: mockDictionary}); refute.exception(function() { pursuit({equals: 'bar'})(null); }); }, 'should not throw an error when checking on a nested property and the input is null': function () { var pursuit = engine({dictionary: mockDictionary}); refute.exception(function() { pursuit({foo: {equals: 'bar'}})(null); pursuit({foo: { bar: {equals: 'bar'}}})({ foo: null }); pursuit({foo: { bar: { baz: {equals: 'bar'}}}})({ foo: { bar: null }}); }); }, 'should throw an error if a key is not in the dictionary': function () { var pursuit = engine({dictionary: mockDictionary}); assert.exception(function() { pursuit({ foo: { bar: 'test' }}); }); } }); buster.testCase('Pursuit Core Output nesting', { 'setUp': function () { this.pursuit = engine({dictionary: mockDictionary}); }, 'should be able check on values nested two levels deep': function () { var pursuit = this.pursuit; refute.exception(function () { var query = pursuit({ foo: { bar: { equals: 'baz' }} }); assert.isTrue(query({ foo: { bar: 'baz' }})); refute.isTrue(query({ foo: { bar: 'bar' }})); }); }, 'should be able check on values nested three (or more) levels deep': function () { var pursuit = this.pursuit; refute.exception(function () { var query = pursuit({ foo: { bar: { baz: { equals: 'toto' }}} }); assert.isTrue(query({ foo: { bar: { baz: 'toto' }}})); refute.isTrue(query({ foo: { bar: { baz: 'tata' }}})); }); } }); buster.testCase('Pursuit Core Generated OR-blocks', { 'setUp': function () { this.pursuit = engine({dictionary: mockDictionary}); }, 'should be able to do OR blocks on keys': function () { var query = this.pursuit({ foo: [ { equals: 'toto' }, { equals: 'titi' } ] }); assert.isTrue(query({foo: 'toto'})); assert.isTrue(query({foo: 'titi'})); refute.isTrue(query({foo: 'tata'})); }, 'should keep its local scope': function () { var query = this.pursuit([ { foo: { equals: 'bar' }}, { foo: { equals: 'baz' }} ]); var test = [{foo: 'bar'}, {foo: 'baz'}, {foo: 'bar'}]; assert.equals(test.filter(query).length, 3); }, 'should keep the scope within a sub-scope': function () { var query = this.pursuit({ foo: { bar: [ { baz: { equals: 'toto' }}, { baz: { equals: 'titi' }} ] } }); assert.isTrue(query({foo: { bar: { baz: 'toto' }}})); assert.isTrue(query({foo: { bar: { baz: 'titi' }}})); refute.isTrue(query({foo: { bar: { baz: 'tata' }}})); }, 'should keep its scope after visiting a nested property': function () { var query = this.pursuit({ foo: { bar: [{equals: 'titi'}, {equals: 'tata'}], baz: {equals: 'toto'} } }); var test = [ {foo: {bar: 'titi', baz: 'toto'}}, {foo: {bar: 'tata', baz: 'toto'}}, {foo: {bar: 'titi'}} ]; assert.equals(test.filter(query).length, 2); }, 'should keep the scope when inverting the result within a sub-scope': function () { var query = this.pursuit({ foo: { bar: { '!not': [ {baz: {equals: 'toto'}}, {baz: {equals: 'titi'}} ]}} }); assert.isTrue(query({foo: { bar: { baz: 'tata' }}})); refute.isTrue(query({foo: { bar: { baz: 'toto' }}})); refute.isTrue(query({foo: { bar: { baz: 'titi' }}})); } }); buster.testCase('Pursuit Core Generated Output: negation', { setUp: function () { this.pursuit = engine({dictionary: mockDictionary}); }, 'should work in root level': function () { var query = this.pursuit({ '!not': { foo: { equals: 'tata' }} }); refute.isTrue(query({ foo: 'tata' })); assert.isTrue(query({ foo: 'titi' })); assert.isTrue(query({ foo: 'toto' })); }, 'should work in root level with OR-statements': function () { var query = this.pursuit({ '!not': [ { foo: { equals: 'toto' }}, { foo: { equals: 'tata' }} ] }); assert.isTrue(query({ foo: 'titi' })); refute.isTrue(query({ foo: 'toto' })); refute.isTrue(query({ foo: 'tata' })); }, 'should work with double negation': function () { var query = this.pursuit({ '!not': { '!not': { foo: { equals: 'tata' }}} }); assert.isTrue(query({ foo: 'tata' })); refute.isTrue(query({ foo: 'titi' })); refute.isTrue(query({ foo: 'toto' })); } }); buster.testCase('Pursuit Core Generated Output: optimization', { // We might need to rephrase the name of this test... 'should handle empty checks along with non-empty': function () { refute.exception(function() { var pursuit = engine({dictionary: mockDictionary2}); pursuit({ foo: { bar: [ {beginsWith: 'tata' }, {isSet: true }, {endsWith: 'titi' }, {equals: 'toto' } ] } }); }); } }); buster.testCase('Pursuit Core Generated Output: run time scope', { 'should be able to access the given scope with `this`': function () { var scope = { foo: 'bar' }; var pursuit = engine({ dictionary: { _: function () { return 'this.foo'; } } }); var matcher = pursuit.call(scope, { _: ''}); assert.equals(matcher({}), 'bar'); }, 'should be able to manipulate the given scope': function () { // this might have little to none real-life usage var scope = { foo: 0 }; var pursuit = engine({ dictionary: { _: function (value) { return this.getScope()+' === (this.foo+=1);'; } } }); var query = pursuit.call(scope, { _: ''}); var test = [1, 1, 3, 4, 5, 7, 6, 8]; assert.equals(test.filter(query), [1, 3, 4, 5, 8]); }, '// should be able to implement an instanceof function': function () { var MyObj = function () {}; var scope = { MyObj: MyObj }; var pursuit = engine.call({foo: 'baz'}, { dictionary: { instanceOf: function (value) { return this.getScope() + ' instanceof this.' + JSON.parse(value); } } }); var matcher = pursuit.call(scope, { instanceOf: 'MyObj' }); console.log(matcher((new MyObj()))); } });