UNPKG

@kineticdata/react

Version:
1,523 lines (1,515 loc) 47.1 kB
"use strict"; var _SearchBuilder = require("./SearchBuilder"); var _immutable = require("immutable"); describe('defineFilter', function () { var person = { firstName: 'Alex', lastName: 'Zen' }; test('equals', function () { var fn = (0, _SearchBuilder.defineFilter)().equals('firstName', 'name').end(); expect(fn(person, { name: 'Alex' })).toBe(true); expect(fn(person, { name: 'ALEX' })).toBe(false); expect(fn(person, { name: 'Ale' })).toBe(false); expect(fn({ firstName: "\xC5af" }, { name: "\xE5af" })).toBe(false); expect(fn(person, (0, _immutable.fromJS)({ name: 'Alex' }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ name: 'ALEX' }))).toBe(false); }); // With non-empty filter values and object values it should behave the same // as the `equals` without strict. test('equals strict', function () { var fn = (0, _SearchBuilder.defineFilter)().equals('firstName', 'name', true).end(); expect(fn(person, { name: 'Alex' })).toBe(true); expect(fn(person, { name: 'ALEX' })).toBe(false); expect(fn(person, { name: 'Ale' })).toBe(false); expect(fn({ firstName: "\xC5af" }, { name: "\xE5af" })).toBe(false); }); test('equals coerces', function () { var fn = (0, _SearchBuilder.defineFilter)().equals('value', 'filterValue', true).end(); expect(fn({ value: 2 }, { filterValue: '2' })).toBe(true); expect(fn({ value: true }, { filterValue: 'true' })).toBe(true); }); test('equals caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).equals('firstName', 'name').end(); expect(fn(person, { name: 'Alex' })).toBe(true); expect(fn(person, { name: 'ALEX' })).toBe(true); expect(fn(person, { name: 'Ale' })).toBe(false); expect(fn({ firstName: "\xC5af" }, { name: "\xE5af" })).toBe(true); }); test('multiple equals', function () { var fn = (0, _SearchBuilder.defineFilter)().equals('firstName', 'fname').equals('lastName', 'lname').end(); expect(fn(person, { fname: 'Alex', lname: 'Zen' })).toBe(true); expect(fn(person, { fname: 'Ale', lname: 'Zen' })).toBe(false); }); test('startsWith', function () { var fn = (0, _SearchBuilder.defineFilter)().startsWith('firstName', 'name').end(); expect(fn(person, { name: 'Alex' })).toBe(true); expect(fn(person, { name: 'Ale' })).toBe(true); expect(fn(person, { name: 'ALE' })).toBe(false); expect(fn(person, { name: 'Alexa' })).toBe(false); expect(fn(person, (0, _immutable.fromJS)({ name: 'Ale' }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ name: 'ALE' }))).toBe(false); }); test('startsWith caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).startsWith('firstName', 'name').end(); expect(fn(person, { name: 'Alex' })).toBe(true); expect(fn(person, { name: 'Ale' })).toBe(true); expect(fn(person, { name: 'ALE' })).toBe(true); expect(fn(person, { name: 'Alexa' })).toBe(false); }); test('in', function () { var fn = (0, _SearchBuilder.defineFilter)()["in"]('firstName', 'names').end(); expect(fn(person, { names: ['Alex', 'Sam'] })).toBe(true); expect(fn(person, { names: ['ALEX', 'Same'] })).toBe(false); expect(fn(person, { names: ['Ale', 'Same'] })).toBe(false); expect(fn(person, (0, _immutable.fromJS)({ names: ['Alex', 'Sam'] }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ names: ['ALEX', 'Same'] }))).toBe(false); }); // With non-empty filter values and object values it should behave the same // as the `in` without strict. test('in strict', function () { var fn = (0, _SearchBuilder.defineFilter)()["in"]('firstName', 'names', true).end(); expect(fn(person, { names: ['Alex', 'Sam'] })).toBe(true); expect(fn(person, { names: ['ALEX', 'Same'] })).toBe(false); expect(fn(person, { names: ['Ale', 'Same'] })).toBe(false); }); test('in coerces', function () { var fn = (0, _SearchBuilder.defineFilter)()["in"]('value', 'filterValue').end(); expect(fn({ value: 2 }, { filterValue: ['2'] })).toBe(true); expect(fn({ value: true }, { filterValue: ['true'] })).toBe(true); }); test('in caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true)["in"]('firstName', 'names').end(); expect(fn(person, { names: ['Alex', 'Sam'] })).toBe(true); expect(fn(person, { names: ['ALEX', 'Same'] })).toBe(true); expect(fn(person, { names: ['Ale', 'Same'] })).toBe(false); }); test('in invalid filter value type', function () { var fn = (0, _SearchBuilder.defineFilter)()["in"]('firstName', 'names').end(); expect(function () { fn(person, { names: 'Invalid' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter value for in operation of names filter. Got \\\"Invalid\\\". Require an array.\""); expect(function () { fn(person, { names: '' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter value for in operation of names filter. Got \\\"\\\". Require an array.\""); }); test('greaterThan', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThan('firstName', 'min').end(); expect(fn(person, { min: 'Aa' })).toBe(true); // "aa" > "Alex" expect(fn(person, { min: 'aa' })).toBe(false); expect(fn(person, { min: 'Alex' })).toBe(false); expect(fn(person, { min: 'Az' })).toBe(false); expect(fn(person, (0, _immutable.fromJS)({ min: 'Aa' }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ min: 'aa' }))).toBe(false); }); // With non-empty filter values and object values it should behave the same // as the `greaterThan` without strict. test('greaterThan strict', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThan('firstName', 'min', true).end(); expect(fn(person, { min: 'Aa' })).toBe(true); // "aa" > "Alex" expect(fn(person, { min: 'aa' })).toBe(false); expect(fn(person, { min: 'Alex' })).toBe(false); expect(fn(person, { min: 'Az' })).toBe(false); }); test('greaterThan coerces', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThan('value', 'filterValue').end(); expect(fn({ value: 2 }, { filterValue: '1' })).toBe(true); expect(fn({ value: 2 }, { filterValue: '2' })).toBe(false); expect(fn({ value: true }, { filterValue: 'false' })).toBe(true); expect(fn({ value: false }, { filterValue: 'false' })).toBe(false); }); test('greaterThan caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).greaterThan('firstName', 'min').end(); expect(fn(person, { min: 'Aa' })).toBe(true); // "aa" > "Alex" but "alex" > "aa" expect(fn(person, { min: 'aa' })).toBe(true); expect(fn(person, { min: 'Alex' })).toBe(false); expect(fn(person, { min: 'Az' })).toBe(false); }); test('greaterThanOrEquals', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThanOrEquals('firstName', 'min').end(); expect(fn(person, { min: 'Aa' })).toBe(true); // "aa" > "Alex" expect(fn(person, { min: 'aa' })).toBe(false); expect(fn(person, { min: 'Alex' })).toBe(true); expect(fn(person, { min: 'alex' })).toBe(false); expect(fn(person, { min: 'Az' })).toBe(false); expect(fn(person, (0, _immutable.fromJS)({ min: 'Aa' }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ min: 'aa' }))).toBe(false); }); // With non-empty filter values and object values it should behave the same // as the `greaterThanOrEquals` without strict. test('greaterThanOrEquals strict', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThanOrEquals('firstName', 'min', true).end(); expect(fn(person, { min: 'Aa' })).toBe(true); // "aa" > "Alex" expect(fn(person, { min: 'aa' })).toBe(false); expect(fn(person, { min: 'Alex' })).toBe(true); expect(fn(person, { min: 'alex' })).toBe(false); expect(fn(person, { min: 'Az' })).toBe(false); }); test('greaterThanOrEquals coerces', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThanOrEquals('value', 'filterValue').end(); expect(fn({ value: 2 }, { filterValue: '1' })).toBe(true); expect(fn({ value: 2 }, { filterValue: '2' })).toBe(true); expect(fn({ value: 2 }, { filterValue: '3' })).toBe(false); expect(fn({ value: true }, { filterValue: 'false' })).toBe(true); expect(fn({ value: true }, { filterValue: 'true' })).toBe(true); expect(fn({ value: false }, { filterValue: 'true' })).toBe(false); }); test('greaterThanOrEquals caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).greaterThanOrEquals('firstName', 'min').end(); expect(fn(person, { min: 'Aa' })).toBe(true); // "aa" > "Alex" but "alex" > "aa" expect(fn(person, { min: 'aa' })).toBe(true); expect(fn(person, { min: 'Alex' })).toBe(true); expect(fn(person, { min: 'alex' })).toBe(true); expect(fn(person, { min: 'Az' })).toBe(false); }); test('lessThan', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThan('firstName', 'max').end(); expect(fn(person, { max: 'Az' })).toBe(true); // "AZ" < "Alex" expect(fn(person, { max: 'AZ' })).toBe(false); expect(fn(person, { max: 'Alex' })).toBe(false); expect(fn(person, { max: 'Aa' })).toBe(false); expect(fn(person, (0, _immutable.fromJS)({ max: 'Az' }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ max: 'AZ' }))).toBe(false); }); // With non-empty filter values and object values it should behave the same // as the `lessThan` without strict. test('lessThan strict', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThan('firstName', 'max', true).end(); expect(fn(person, { max: 'Az' })).toBe(true); // "AZ" < "Alex" expect(fn(person, { max: 'AZ' })).toBe(false); expect(fn(person, { max: 'Alex' })).toBe(false); expect(fn(person, { max: 'Aa' })).toBe(false); }); test('lessThan coerces', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThan('value', 'filterValue').end(); expect(fn({ value: 2 }, { filterValue: '3' })).toBe(true); expect(fn({ value: 2 }, { filterValue: '2' })).toBe(false); expect(fn({ value: 2 }, { filterValue: '1' })).toBe(false); expect(fn({ value: true }, { filterValue: 'false' })).toBe(false); expect(fn({ value: true }, { filterValue: 'true' })).toBe(false); expect(fn({ value: false }, { filterValue: 'true' })).toBe(true); }); test('lessThan caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).lessThan('firstName', 'max').end(); expect(fn(person, { max: 'Az' })).toBe(true); // "AZ" < "Alex" expect(fn(person, { max: 'AZ' })).toBe(true); expect(fn(person, { max: 'Alex' })).toBe(false); expect(fn(person, { max: 'Aa' })).toBe(false); }); test('lessThanOrEquals', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThanOrEquals('firstName', 'max').end(); expect(fn(person, { max: 'Az' })).toBe(true); // "aa" > "Alex" expect(fn(person, { max: 'aa' })).toBe(true); expect(fn(person, { max: 'Alex' })).toBe(true); expect(fn(person, { max: 'Aa' })).toBe(false); expect(fn(person, (0, _immutable.fromJS)({ max: 'Alex' }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ max: 'Aa' }))).toBe(false); }); // With non-empty filter values and object values it should behave the same // as the `lessThanOrEquals` without strict. test('lessThanOrEquals strict', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThanOrEquals('firstName', 'max', true).end(); expect(fn(person, { max: 'Az' })).toBe(true); // "aa" > "Alex" expect(fn(person, { max: 'aa' })).toBe(true); expect(fn(person, { max: 'Alex' })).toBe(true); expect(fn(person, { max: 'Aa' })).toBe(false); }); test('lessThanOrEquals coerces', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThanOrEquals('value', 'filterValue').end(); expect(fn({ value: 2 }, { filterValue: '3' })).toBe(true); expect(fn({ value: 2 }, { filterValue: '2' })).toBe(true); expect(fn({ value: 2 }, { filterValue: '1' })).toBe(false); expect(fn({ value: true }, { filterValue: 'false' })).toBe(false); expect(fn({ value: true }, { filterValue: 'true' })).toBe(true); expect(fn({ value: false }, { filterValue: 'true' })).toBe(true); }); test('lessThanOrEquals caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).lessThanOrEquals('firstName', 'max').end(); expect(fn(person, { max: 'Az' })).toBe(true); // "aa" < "alex" expect(fn(person, { max: 'aa' })).toBe(false); expect(fn(person, { max: 'Alex' })).toBe(true); expect(fn(person, { max: 'Aa' })).toBe(false); }); test('between', function () { var fn = (0, _SearchBuilder.defineFilter)().between('firstName', 'min', 'max').end(); expect(fn(person, { min: 'Aa', max: 'Az' })).toBe(true); // min inclusive expect(fn(person, { min: 'Alex', max: 'Az' })).toBe(true); // max exclusive expect(fn(person, { min: 'Aa', max: 'Alex' })).toBe(false); // case sensitive expect(fn(person, { min: 'aa', max: 'az' })).toBe(false); expect(fn(person, { min: 'Aa', max: 'Ab' })).toBe(false); // tests a min - max range that relies on case sensitivity expect(fn(person, { min: 'A', max: 'a' })).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ min: 'Aa', max: 'Az' }))).toBe(true); expect(fn(person, (0, _immutable.fromJS)({ min: 'Aa', max: 'Alex' }))).toBe(false); }); // With non-empty filter values and object values it should behave the same // as the `between` without strict. test('between', function () { var fn = (0, _SearchBuilder.defineFilter)().between('firstName', 'min', 'max', true).end(); expect(fn(person, { min: 'Aa', max: 'Az' })).toBe(true); // min inclusive expect(fn(person, { min: 'Alex', max: 'Az' })).toBe(true); // max exclusive expect(fn(person, { min: 'Aa', max: 'Alex' })).toBe(false); // case sensitive expect(fn(person, { min: 'aa', max: 'az' })).toBe(false); expect(fn(person, { min: 'Aa', max: 'Ab' })).toBe(false); }); test('between coerces', function () { var fn = (0, _SearchBuilder.defineFilter)().between('value', 'min', 'max').end(); expect(fn({ value: 1 }, { min: '1', max: '3' })).toBe(true); expect(fn({ value: 2 }, { min: '1', max: '3' })).toBe(true); expect(fn({ value: 3 }, { min: '1', max: '3' })).toBe(false); expect(fn({ value: false }, { min: 'false', max: 'true' })).toBe(true); expect(fn({ value: true }, { min: 'false', max: 'true' })).toBe(false); expect(function () { fn({ value: 3 }, { min: '3', max: '1' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"3\\\" not less than max \\\"1\\\"\""); }); test('between caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).between('firstName', 'min', 'max').end(); expect(fn(person, { min: 'Aa', max: 'Az' })).toBe(true); expect(fn(person, { min: 'aa', max: 'az' })).toBe(true); expect(fn(person, { min: 'Aa', max: 'Ab' })).toBe(false); expect(function () { fn(person, { min: 'A', max: 'a' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"A\\\" not less than max \\\"a\\\" (caseInsensitive)\""); }); test('between invalid', function () { var fn = (0, _SearchBuilder.defineFilter)(true).between('firstName', 'min', 'max').end(); expect(function () { fn(person, { min: 'z', max: 'a' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"z\\\" not less than max \\\"a\\\" (caseInsensitive)\""); expect(function () { fn(person, { min: 'a', max: 'a' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"a\\\" not less than max \\\"a\\\" (caseInsensitive)\""); }); test('or', function () { var fn = (0, _SearchBuilder.defineFilter)(false, 'or').equals('firstName', 'name1').equals('firstName', 'name2').end(); expect(fn(person, { name1: 'Alex', name2: 'Other' })).toBe(true); expect(fn(person, { name1: 'Other', name2: 'Alex' })).toBe(true); expect(fn(person, { name1: 'Other', name2: 'zzz' })).toBe(false); }); test('nested ands / ors', function () { var fn = (0, _SearchBuilder.defineFilter)().equals('lastName', 'lname').or().equals('firstName', 'name1').equals('firstName', 'name2').end().end(); expect(fn(person, { name1: 'Alex', name2: 'Other', lname: 'Zen' })).toBe(true); expect(fn(person, { name1: 'Other', name2: 'Alex', lname: 'Zen' })).toBe(true); expect(fn(person, { name1: 'Other', name2: 'zzz', lname: 'Zen' })).toBe(false); }); test('nested ands / ors caseInsensitive', function () { var fn = (0, _SearchBuilder.defineFilter)(true).equals('lastName', 'lname').or().equals('firstName', 'name1').equals('firstName', 'name2').end().end(); expect(fn(person, { name1: 'alex', name2: 'Other', lname: 'zen' })).toBe(true); expect(fn(person, { name1: 'Other', name2: 'alex', lname: 'zen' })).toBe(true); expect(fn(person, { name1: 'Other', name2: 'zzz', lname: 'zen' })).toBe(false); }); describe('empty values / filters', function () { var emptyPerson = { firstName: '' }; var nullPerson = { firstName: null }; var undefinedPerson = {}; var emptyFilter = { name: '' }; var nullFilter = { name: null }; var undefinedFilter = {}; var emptyInFilter = { names: [] }; var nullInFilter = { names: null }; test('equals', function () { var fn = (0, _SearchBuilder.defineFilter)().equals('firstName', 'name').end(); // No matter the object value, when the filter value is // undefined, null, or empty the filter is ignored. expect(fn(person, undefinedFilter)).toBe(true); expect(fn(emptyPerson, undefinedFilter)).toBe(true); expect(fn(nullPerson, undefinedFilter)).toBe(true); expect(fn(undefinedPerson, undefinedFilter)).toBe(true); expect(fn(person, nullFilter)).toBe(true); expect(fn(emptyPerson, nullFilter)).toBe(true); expect(fn(nullPerson, nullFilter)).toBe(true); expect(fn(undefinedPerson, nullFilter)).toBe(true); expect(fn(person, emptyFilter)).toBe(true); expect(fn(emptyPerson, emptyFilter)).toBe(true); expect(fn(nullPerson, emptyFilter)).toBe(true); expect(fn(undefinedPerson, emptyFilter)).toBe(true); // Filtering '', null, undefined by 'a' should result in false. expect(fn(emptyPerson, { name: 'a' })).toBe(false); expect(fn(nullPerson, { name: 'a' })).toBe(false); expect(fn(undefinedPerson, { name: 'a' })).toBe(false); }); test('equals strict', function () { var fn = (0, _SearchBuilder.defineFilter)().equals('firstName', 'name', true).end(); expect(fn(person, undefinedFilter)).toBe(false); expect(fn(person, nullFilter)).toBe(false); expect(fn(person, emptyFilter)).toBe(false); expect(fn(undefinedPerson, undefinedFilter)).toBe(true); expect(fn(nullPerson, nullFilter)).toBe(true); expect(fn(emptyPerson, emptyFilter)).toBe(true); }); test('in', function () { var fn = (0, _SearchBuilder.defineFilter)()["in"]('firstName', 'names').end(); // No matter the object value, when the filter value is undefined, null, // or empty array the filter is ignored expect(fn(person, emptyInFilter)).toBe(true); expect(fn(person, nullInFilter)).toBe(true); expect(fn(person, undefinedFilter)).toBe(true); expect(fn(emptyPerson, emptyInFilter)).toBe(true); expect(fn(emptyPerson, nullInFilter)).toBe(true); expect(fn(emptyPerson, undefinedFilter)).toBe(true); expect(fn(nullPerson, emptyInFilter)).toBe(true); expect(fn(nullPerson, nullInFilter)).toBe(true); expect(fn(nullPerson, undefinedFilter)).toBe(true); expect(fn(undefinedPerson, emptyInFilter)).toBe(true); expect(fn(undefinedPerson, nullInFilter)).toBe(true); expect(fn(undefinedPerson, undefinedFilter)).toBe(true); // If the filter value array contains "", null, undefined then the object // matches if its value for that field is "", null, undefined respectively expect(fn(person, { names: [''] })).toBe(false); expect(fn(emptyPerson, { names: [''] })).toBe(true); expect(fn(person, { names: [null] })).toBe(false); expect(fn(nullPerson, { names: [null] })).toBe(true); expect(fn(person, { names: [undefined] })).toBe(false); expect(fn(undefinedPerson, { names: [undefined] })).toBe(true); // Filtering '', null, undefined by ['a'] should result in false. expect(fn(emptyPerson, { names: ['a'] })).toBe(false); expect(fn(nullPerson, { names: ['a'] })).toBe(false); expect(fn(undefinedPerson, { names: ['a'] })).toBe(false); }); test('in strict', function () { var fn = (0, _SearchBuilder.defineFilter)()["in"]('firstName', 'names', true).end(); // When strict and given [], null, undefined nothing can be a member of // those empty sets so false should always be returned. expect(fn(person, emptyInFilter)).toBe(false); expect(fn(person, nullInFilter)).toBe(false); expect(fn(person, undefinedFilter)).toBe(false); expect(fn(emptyPerson, emptyInFilter)).toBe(false); expect(fn(emptyPerson, nullInFilter)).toBe(false); expect(fn(emptyPerson, undefinedFilter)).toBe(false); expect(fn(nullPerson, emptyInFilter)).toBe(false); expect(fn(nullPerson, nullInFilter)).toBe(false); expect(fn(nullPerson, undefinedFilter)).toBe(false); expect(fn(undefinedPerson, emptyInFilter)).toBe(false); expect(fn(undefinedPerson, nullInFilter)).toBe(false); expect(fn(undefinedPerson, undefinedFilter)).toBe(false); }); test('startsWith', function () { var fn = (0, _SearchBuilder.defineFilter)().startsWith('firstName', 'name').end(); expect(fn(person, {})).toBe(true); expect(fn(person, { name: '' })).toBe(true); expect(fn(person, { name: null })).toBe(true); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { name: '' })).toBe(true); expect(fn(emptyPerson, { name: null })).toBe(true); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { name: '' })).toBe(true); expect(fn(nullPerson, { name: null })).toBe(true); expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { name: '' })).toBe(true); expect(fn(undefinedPerson, { name: null })).toBe(true); // Filtering '', null, undefined by startsWith 'a' should result in false. expect(fn(emptyPerson, { name: 'a' })).toBe(false); expect(fn(nullPerson, { name: 'a' })).toBe(false); expect(fn(undefinedPerson, { name: 'a' })).toBe(false); }); test('greaterThan', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThan('firstName', 'min').end(); // No matter the object value, when the filter value is undefined, null, // or empty array the filter is ignored expect(fn(person, {})).toBe(true); expect(fn(person, { min: '' })).toBe(true); expect(fn(person, { min: null })).toBe(true); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { min: '' })).toBe(true); expect(fn(emptyPerson, { min: null })).toBe(true); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { min: '' })).toBe(true); expect(fn(nullPerson, { min: null })).toBe(true); expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { min: '' })).toBe(true); expect(fn(undefinedPerson, { min: null })).toBe(true); // 'A' > '' > null > undefined expect(fn(undefinedPerson, { min: 'A' })).toBe(false); expect(fn(nullPerson, { min: 'A' })).toBe(false); expect(fn(emptyPerson, { min: 'A' })).toBe(false); }); test('greaterThan strict', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThan('firstName', 'min', true).end(); // 'A' > '' > null > undefined expect(fn(undefinedPerson, {})).toBe(false); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { min: null })).toBe(false); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { min: null })).toBe(true); expect(fn(emptyPerson, { min: '' })).toBe(false); expect(fn(person, {})).toBe(true); expect(fn(person, { min: null })).toBe(true); expect(fn(person, { min: '' })).toBe(true); }); test('greaterThanOrEquals', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThanOrEquals('firstName', 'min').end(); // No matter the object value, when the filter value is undefined, null, // or empty array the filter is ignored expect(fn(person, {})).toBe(true); expect(fn(person, { min: '' })).toBe(true); expect(fn(person, { min: null })).toBe(true); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { min: '' })).toBe(true); expect(fn(emptyPerson, { min: null })).toBe(true); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { min: '' })).toBe(true); expect(fn(nullPerson, { min: null })).toBe(true); expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { min: '' })).toBe(true); expect(fn(undefinedPerson, { min: null })).toBe(true); // 'A' > '' > null > undefined expect(fn(undefinedPerson, { min: 'A' })).toBe(false); expect(fn(nullPerson, { min: 'A' })).toBe(false); expect(fn(emptyPerson, { min: 'A' })).toBe(false); }); test('greaterThanOrEquals strict', function () { var fn = (0, _SearchBuilder.defineFilter)().greaterThanOrEquals('firstName', 'min', true).end(); // 'A' > '' > null > undefined expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { min: null })).toBe(false); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { min: null })).toBe(true); expect(fn(nullPerson, { min: '' })).toBe(false); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { min: null })).toBe(true); expect(fn(emptyPerson, { min: '' })).toBe(true); expect(fn(emptyPerson, { min: 'A' })).toBe(false); expect(fn(person, {})).toBe(true); expect(fn(person, { min: null })).toBe(true); expect(fn(person, { min: '' })).toBe(true); }); test('lessThan', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThan('firstName', 'max').end(); // No matter the object value, when the filter value is undefined, null, // or empty array the filter is ignored expect(fn(person, {})).toBe(true); expect(fn(person, { max: '' })).toBe(true); expect(fn(person, { max: null })).toBe(true); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { max: '' })).toBe(true); expect(fn(emptyPerson, { max: null })).toBe(true); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { max: '' })).toBe(true); expect(fn(nullPerson, { max: null })).toBe(true); expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { max: '' })).toBe(true); expect(fn(undefinedPerson, { max: null })).toBe(true); // 'A' > '' > null > undefined expect(fn(undefinedPerson, { max: 'A' })).toBe(true); expect(fn(nullPerson, { max: 'A' })).toBe(true); expect(fn(emptyPerson, { max: 'A' })).toBe(true); }); test('lessThan strict', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThan('firstName', 'max', true).end(); // 'A' > '' > null > undefined expect(fn(undefinedPerson, {})).toBe(false); expect(fn(undefinedPerson, { max: null })).toBe(true); expect(fn(nullPerson, {})).toBe(false); expect(fn(nullPerson, { max: null })).toBe(false); expect(fn(nullPerson, { max: '' })).toBe(true); expect(fn(emptyPerson, {})).toBe(false); expect(fn(emptyPerson, { max: null })).toBe(false); expect(fn(emptyPerson, { max: '' })).toBe(false); expect(fn(emptyPerson, { max: 'A' })).toBe(true); expect(fn(person, {})).toBe(false); expect(fn(person, { max: null })).toBe(false); expect(fn(person, { max: '' })).toBe(false); }); test('lessThanOrEquals', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThanOrEquals('firstName', 'max').end(); // No matter the object value, when the filter value is undefined, null, // or empty array the filter is ignored expect(fn(person, {})).toBe(true); expect(fn(person, { max: '' })).toBe(true); expect(fn(person, { max: null })).toBe(true); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { max: '' })).toBe(true); expect(fn(emptyPerson, { max: null })).toBe(true); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { max: '' })).toBe(true); expect(fn(nullPerson, { max: null })).toBe(true); expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { max: '' })).toBe(true); expect(fn(undefinedPerson, { max: null })).toBe(true); // 'A' > '' > null > undefined expect(fn(undefinedPerson, { max: 'A' })).toBe(true); expect(fn(nullPerson, { max: 'A' })).toBe(true); expect(fn(emptyPerson, { max: 'A' })).toBe(true); }); test('lessThanOrEquals strict', function () { var fn = (0, _SearchBuilder.defineFilter)().lessThanOrEquals('firstName', 'max', true).end(); // 'A' > '' > null > undefined expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { max: null })).toBe(true); expect(fn(nullPerson, {})).toBe(false); expect(fn(nullPerson, { max: null })).toBe(true); expect(fn(nullPerson, { max: '' })).toBe(true); expect(fn(emptyPerson, {})).toBe(false); expect(fn(emptyPerson, { max: null })).toBe(false); expect(fn(emptyPerson, { max: '' })).toBe(true); expect(fn(emptyPerson, { max: 'A' })).toBe(true); expect(fn(person, {})).toBe(false); expect(fn(person, { max: null })).toBe(false); expect(fn(person, { max: '' })).toBe(false); }); test('between', function () { var fn = (0, _SearchBuilder.defineFilter)().between('firstName', 'min', 'max').end(); expect(fn(person, {})).toBe(true); expect(fn(person, { min: '', max: 'z' })).toBe(true); expect(fn(person, { min: null, max: 'z' })).toBe(true); expect(fn(person, { min: 'A', max: '' })).toBe(true); expect(fn(person, { min: 'A', max: null })).toBe(true); expect(fn(emptyPerson, {})).toBe(true); expect(fn(emptyPerson, { min: '', max: 'z' })).toBe(true); expect(fn(emptyPerson, { min: null, max: 'z' })).toBe(true); expect(fn(emptyPerson, { min: 'A', max: '' })).toBe(true); expect(fn(emptyPerson, { min: 'A', max: null })).toBe(true); expect(fn(nullPerson, {})).toBe(true); expect(fn(nullPerson, { min: '', max: 'z' })).toBe(true); expect(fn(nullPerson, { min: null, max: 'z' })).toBe(true); expect(fn(nullPerson, { min: 'A', max: '' })).toBe(true); expect(fn(nullPerson, { min: 'A', max: null })).toBe(true); expect(fn(undefinedPerson, {})).toBe(true); expect(fn(undefinedPerson, { min: '', max: 'z' })).toBe(true); expect(fn(undefinedPerson, { min: null, max: 'z' })).toBe(true); expect(fn(undefinedPerson, { min: 'A', max: '' })).toBe(true); expect(fn(undefinedPerson, { min: 'A', max: null })).toBe(true); // 'A' > '' > null > undefined expect(fn(undefinedPerson, { min: 'A', max: 'z' })).toBe(false); expect(fn(nullPerson, { min: 'A', max: 'z' })).toBe(false); expect(fn(emptyPerson, { min: 'A', max: 'z' })).toBe(false); }); test('between strict', function () { var fn = (0, _SearchBuilder.defineFilter)().between('firstName', 'min', 'max', true).end(); // 'Alex' > 'A' expect(fn(person, { min: undefined, max: 'A' })).toBe(false); expect(fn(person, { min: undefined, max: 'z' })).toBe(true); expect(fn(emptyPerson, { min: '', max: 'z' })).toBe(true); expect(fn(emptyPerson, { min: null, max: 'z' })).toBe(true); expect(fn(emptyPerson, { min: undefined, max: 'z' })).toBe(true); expect(fn(emptyPerson, { min: undefined, max: '' })).toBe(false); expect(fn(nullPerson, { min: '', max: 'z' })).toBe(false); expect(fn(nullPerson, { min: null, max: 'z' })).toBe(true); expect(fn(nullPerson, { min: undefined, max: 'z' })).toBe(true); expect(fn(nullPerson, { min: null, max: '' })).toBe(true); expect(fn(nullPerson, { min: undefined, max: null })).toBe(false); expect(fn(undefinedPerson, { min: null, max: 'z' })).toBe(false); expect(fn(undefinedPerson, { min: undefined, max: 'z' })).toBe(true); expect(fn(undefinedPerson, { min: undefined, max: null })).toBe(true); }); test('between strict invalid', function () { var fn = (0, _SearchBuilder.defineFilter)().between('firstName', 'min', 'max', true).end(); expect(function () { fn(person, { min: 'a', max: undefined }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"a\\\" not less than max undefined\""); expect(function () { fn(person, { min: 'a', max: '' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"a\\\" not less than max \\\"\\\"\""); expect(function () { fn(person, { min: '', max: null }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"\\\" not less than max null\""); expect(function () { fn(person, { min: null, max: undefined }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min null not less than max undefined\""); expect(function () { fn(person, { min: '', max: '' }); }).toThrowErrorMatchingInlineSnapshot("\"Invalid filter values for between operation of min and max. Min \\\"\\\" not less than max \\\"\\\"\""); }); }); }); describe('defineKqlQuery', function () { var values; beforeEach(function () { values = { name: 'Matt', names: ['Bob', 'Matt', '', undefined, null], emptyNames: [], nullNames: null, undefinedNames: undefined, otherName: 'Bob', slug: 'acme', empty: '', nullName: null, undefinedName: undefined, minValue: 'min', maxValue: 'max' }; }); test('empty expression', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('empty', 'empty').equals('nullName', 'nullName').equals('undefinedName', 'undefinedName').end(); expect(query).toBeDefined(); expect(query(values)).toBe(''); }); test('empty root expression', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('empty', 'empty').or().equals('slug', 'slug').equals('nullName', 'nullName').equals('undefinedName', 'undefinedName').end().end(); expect(query).toBeDefined(); expect(query(values)).toBe('( slug = "acme" )'); }); test('empty expression stack', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('slug', 'slug').equals('empty', 'empty').equals('nullName', 'nullName').equals('undefinedName', 'undefinedName').end(); expect(query).toBeDefined(); expect(query(values)).toBe('slug = "acme"'); }); test('equals', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('name', 'name').equals('slug', 'slug').equals('empty', 'empty').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name = \"Matt\" AND slug = \"acme\""); }); test('equals strict', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('empty', 'empty', true).equals('nullName', 'nullName', true).equals('undefinedName', 'undefinedName', true).end(); expect(query).toBeDefined(); expect(query(values)).toBe("empty = \"\" AND nullName = \"\" AND undefinedName = \"\""); }); test('startsWith', function () { var query = (0, _SearchBuilder.defineKqlQuery)().startsWith('name', 'name').startsWith('slug', 'slug').startsWith('empty', 'empty').startsWith('nullName', 'nullName').startsWith('undefinedName', 'undefinedName').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name =* \"Matt\" AND slug =* \"acme\""); }); test('in', function () { var query = (0, _SearchBuilder.defineKqlQuery)()["in"]('name', 'names').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name IN (\"Bob\", \"Matt\")"); }); test('in strict', function () { var query = (0, _SearchBuilder.defineKqlQuery)()["in"]('name', 'names', true).end(); expect(query).toBeDefined(); expect(query(values)).toBe("name IN (\"Bob\", \"Matt\", \"\", \"\", \"\")"); }); test('in invalid list', function () { var query = (0, _SearchBuilder.defineKqlQuery)()["in"]('name', 'names')["in"]('name', 'emptyNames')["in"]('name', 'nullNames')["in"]('name', 'undefinedNames').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name IN (\"Bob\", \"Matt\")"); }); test('between', function () { var query = (0, _SearchBuilder.defineKqlQuery)().between('values', 'minValue', 'maxValue').between('missingOne', 'missingValue', 'maxValue').between('missingBoth', 'missingValue', 'missingValue').end(); expect(query).toBeDefined(); expect(query(values)).toBe("values BETWEEN (\"min\", \"max\")"); }); test('between strict', function () { var query = (0, _SearchBuilder.defineKqlQuery)().between('values', 'minValue', 'maxValue', true).between('missingOne', 'missingValue', 'maxValue', true).between('missingBoth', 'missingValue', 'missingValue', true).end(); expect(query).toBeDefined(); expect(query(values)).toBe("values BETWEEN (\"min\", \"max\") AND missingOne BETWEEN (\"\", \"max\") AND missingBoth BETWEEN (\"\", \"\")"); }); test('greaterThan', function () { var query = (0, _SearchBuilder.defineKqlQuery)().greaterThan('name', 'name').greaterThan('slug', 'slug').greaterThan('empty', 'empty').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name > \"Matt\" AND slug > \"acme\""); }); test('greaterThan strict', function () { var query = (0, _SearchBuilder.defineKqlQuery)().greaterThan('empty', 'empty', true).greaterThan('nullName', 'nullName', true).greaterThan('undefinedName', 'undefinedName', true).end(); expect(query).toBeDefined(); expect(query(values)).toBe("empty > \"\" AND nullName > \"\" AND undefinedName > \"\""); }); test('greaterThanOrEquals', function () { var query = (0, _SearchBuilder.defineKqlQuery)().greaterThanOrEquals('name', 'name').greaterThanOrEquals('slug', 'slug').greaterThanOrEquals('empty', 'empty').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name >= \"Matt\" AND slug >= \"acme\""); }); test('greaterThanOrEquals strict', function () { var query = (0, _SearchBuilder.defineKqlQuery)().greaterThanOrEquals('empty', 'empty', true).greaterThanOrEquals('nullName', 'nullName', true).greaterThanOrEquals('undefinedName', 'undefinedName', true).end(); expect(query).toBeDefined(); expect(query(values)).toBe("empty >= \"\" AND nullName >= \"\" AND undefinedName >= \"\""); }); test('lessThan', function () { var query = (0, _SearchBuilder.defineKqlQuery)().lessThan('name', 'name').lessThan('slug', 'slug').lessThan('empty', 'empty').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name < \"Matt\" AND slug < \"acme\""); }); test('lessThan strict', function () { var query = (0, _SearchBuilder.defineKqlQuery)().lessThan('empty', 'empty', true).lessThan('nullName', 'nullName', true).lessThan('undefinedName', 'undefinedName', true).end(); expect(query).toBeDefined(); expect(query(values)).toBe("empty < \"\" AND nullName < \"\" AND undefinedName < \"\""); }); test('lessThanOrEquals', function () { var query = (0, _SearchBuilder.defineKqlQuery)().lessThanOrEquals('name', 'name').lessThanOrEquals('slug', 'slug').lessThanOrEquals('empty', 'empty').end(); expect(query).toBeDefined(); expect(query(values)).toBe("name <= \"Matt\" AND slug <= \"acme\""); }); test('lessThanOrEquals strict', function () { var query = (0, _SearchBuilder.defineKqlQuery)().lessThanOrEquals('empty', 'empty', true).lessThanOrEquals('nullName', 'nullName', true).lessThanOrEquals('undefinedName', 'undefinedName', true).end(); expect(query).toBeDefined(); expect(query(values)).toBe("empty <= \"\" AND nullName <= \"\" AND undefinedName <= \"\""); }); describe('groupings', function () { test('or separates equalities in its context with OR', function () { var query = (0, _SearchBuilder.defineKqlQuery)().or().equals('name', 'name').equals('name', 'otherName').end().end(); expect(query).toBeDefined(); expect(query(values)).toEqual('( name = "Matt" OR name = "Bob" )'); }); test('or following other equalities implies an and', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('slug', 'slug').or().equals('name', 'name').equals('name', 'otherName').end().end(); expect(query).toBeDefined(); expect(query(values)).toEqual('slug = "acme" AND ( name = "Matt" OR name = "Bob" )'); }); test('complex query', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('slug', 'slug').or().equals('name', 'name').and().equals('name', 'otherName').equals('slug', 'slug').end().end().end(); expect(query).toBeDefined(); expect(query(values)).toEqual('slug = "acme" AND ( name = "Matt" OR ( name = "Bob" AND slug = "acme" ) )'); }); test('when previous items are not included', function () { var query = (0, _SearchBuilder.defineKqlQuery)().equals('name', 'missingName').equals('slug', 'slug').end(); expect(query).toBeDefined(); expect(query(values)).toBe('slug = "acme"'); }); }); });