Last active
December 25, 2017 19:29
-
-
Save qfox/c2ee796969629df53505041f4c58f2b0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const filtr = require('filterable'); | |
module.exports = toJSFunction; | |
function toJSFunction(conditions) { | |
const keys = []; | |
const includes = ($v, v) => typeof v === 'string' ? | |
$v.toLowerCase().indexOf(v.toLowerCase()) !== -1 : | |
v.some((_v) => $v.toLowerCase() === _v.toLowerCase()); | |
const groups = conditions.groups.reduce((res, originalGroup) => { | |
if (['in', 'nin'].indexOf(originalGroup.type) !== -1) { | |
let group = res.find((g) => g.type === originalGroup.type && g.field === originalGroup.field); | |
if (!group) { | |
group = Object.assign({}, originalGroup, { value: [] }); | |
keys.push(originalGroup.field); | |
res.push(group); | |
} | |
group.value.push(originalGroup.value); | |
return res; | |
} | |
keys.push(originalGroup.field); | |
res.push(Object.assign({}, originalGroup)); | |
return res; | |
}, []); | |
const fns = groups.map((g) => { | |
switch (g.type) { | |
case '=': return (v) => v === g.value; | |
case '!=': return (v) => v !== g.value; | |
case 'in': return (v) => v && g.value.some(($v) => includes($v, v)); | |
case 'nin': return (v) => !v || g.value.every(($v) => !includes($v, v)); | |
case '<': return (v) => v < g.value; | |
case '<=': return (v) => v <= g.value; | |
case '>': return (v) => v > g.value; | |
case '>=': return (v) => v >= g.value; | |
} | |
// throw 'I DONT KNOW'; | |
return () => true; | |
}); | |
// console.log(fns.map(f => f.toString())) | |
return (obj) => keys.every((k, i) => fns[i](obj[k])); | |
} | |
if (typeof describe === 'undefined') { | |
return; | |
} | |
function assert(t) { | |
if(!t) { throw new Error('Assertion error'); } | |
} | |
check('Query for tags', | |
['cat', {}], [{ tags: 'cat' }], [{ tags: 'dog' }, { tags: null }]); | |
check('Query for description', | |
['cat', { textField: 'description' }], [{ description: 'cat' }], [{ description: 'dog' }, { description: null }]); | |
check('Query for multiple tags', | |
['cat dog "Hello World"', {}], | |
[{ tags: ['Hello world'] }, { tags: ['cat'] }, { tags: ['dog'] }], | |
[{}/*, { tags: ['lolka'] }*/]); | |
check('Exclude results containing a certain word', | |
['cat NOT dog', {}], [{ tags: 'cat' }], [{ tags: 'cat dog' }, { tags: 'dog' }, { tags: '' }]); | |
check('Query for equality', | |
['name:"Samy Pesse"', {}], [{ name: 'Samy Pesse' }], [{ name: 'Pamy Sesse' }]); | |
check('Query for values greater than another value', | |
['stars:>10 stars:>=10', {}], [{ stars: 11 }, { stars: 100 }], [/*{ stars: 11 }, */{ stars: 0 }]); | |
check('Query for values less than another value', | |
['stars:<100 stars:<=100', {}], [{ stars: 99 }, { stars: 0 }], [{ stars: 1000 }/*, { stars: 100 }*/]); | |
check('Mix query for tags and condition', | |
['cat stars:>10 stars:<100', {}], | |
[{ tags: 'cat', stars: 11 }, { tags: 'cat', stars: 99 }], | |
[{ tags: 'cat', stars: 10 }, { stars: 100 }]); | |
check('Filter qualifiers based on exclusion', | |
['cats stars:>10 NOT language:javascript', {}], | |
[{ tags: 'cats', stars: 100, language: 'ruby' }], | |
[ | |
{ tags: 'cats', stars: 100, language: 'javascript' }, | |
{ tags: 'cats', stars: 0, language: 'ruby' }, | |
{ tags: 'dogs', stars: 100, language: 'ruby' } | |
]); | |
function check(name, input, valid, invalid) { | |
describe(name + ': `' + input[0] + '`', () => { | |
let fn; | |
before(() => { | |
fn = toJSFunction(filtr.Query(input[0], input[1]).parse(), input[1]); | |
}); | |
for (const f of valid) { | |
it('should match ' + JSON.stringify(f), () => { | |
assert(fn(f)); | |
}); | |
} | |
for (const f of invalid) { | |
it('should NOT match ' + JSON.stringify(f), () => { | |
assert(!fn(f)); | |
}); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment