Skip to content

Commit 5efe82a

Browse files
authored
Add tests (#47)
1 parent 80eafdb commit 5efe82a

File tree

4 files changed

+121
-12
lines changed

4 files changed

+121
-12
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "json-expression-eval",
3-
"version": "8.2.0",
3+
"version": "8.2.1",
44
"description": "json serializable rule engine / boolean expression evaluator",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/test/evaluator.spec.ts

Lines changed: 115 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as chai from 'chai';
22
import {expect} from 'chai';
3-
import {evaluate, ExpressionHandler, validate} from '../';
3+
import {evaluate, ExpressionHandler, validate, ValidationContext} from '../';
44
import chaiAsPromised from 'chai-as-promised';
55

66
chai.use(chaiAsPromised);
@@ -1679,11 +1679,44 @@ describe('evaluator', () => {
16791679
expect(await evaluate(expression, context, functionsTable, runOpts)).to.eql(true);
16801680
});
16811681

1682+
it('should evaluate recordNested.a with ref', async () => {
1683+
const expression = {
1684+
'recordNested.a': {eq: {ref: 'recordNested.a' as const}},
1685+
};
1686+
type Context = {
1687+
timesCounter: number;
1688+
userId: string;
1689+
recordNested?: Record<string, string | boolean | number | undefined>;
1690+
};
1691+
const context: Context = {
1692+
timesCounter: 5,
1693+
userId: '[email protected]',
1694+
recordNested: {
1695+
a: 5,
1696+
},
1697+
};
1698+
const validationContext = {
1699+
timesCounter: 5,
1700+
userId: '[email protected]',
1701+
recordNested: {
1702+
a: 5,
1703+
},
1704+
};
1705+
const runOpts: CustomEvaluatorFuncRunOptions = {dryRun: false};
1706+
expect(await validate(expression, validationContext, functionsTable, runOpts)).to.be.an('undefined');
1707+
expect(await evaluate(expression, context, functionsTable, runOpts)).to.eql(true);
1708+
});
1709+
16821710
it('should evaluate recordNested.a with short eq to false', async () => {
16831711
const expression = {
16841712
'recordNested.a': 5,
16851713
};
1686-
const context = {
1714+
type Context = {
1715+
timesCounter: number;
1716+
userId: string;
1717+
recordNested?: Record<string, string | boolean | number | undefined>;
1718+
};
1719+
const context: ValidationContext<Context> = {
16871720
timesCounter: 5,
16881721
userId: '[email protected]',
16891722
recordNested: {
@@ -1699,7 +1732,35 @@ describe('evaluator', () => {
16991732
const expression = {
17001733
'specialNested.a': 5,
17011734
};
1702-
const context = {
1735+
type Context = {
1736+
timesCounter: number;
1737+
userId: string;
1738+
specialNested?: Record<string, string | boolean | number | undefined |
1739+
(string | boolean | number | (string | boolean | number)[])[]>;
1740+
};
1741+
const context:ValidationContext<Context> = {
1742+
timesCounter: 5,
1743+
userId: '[email protected]',
1744+
specialNested: {
1745+
a: 5,
1746+
},
1747+
};
1748+
const runOpts: CustomEvaluatorFuncRunOptions = {dryRun: false};
1749+
expect(await validate(expression, context, functionsTable, runOpts)).to.be.an('undefined');
1750+
expect(await evaluate(expression, context, functionsTable, runOpts)).to.eql(true);
1751+
});
1752+
1753+
it('should evaluate specialNested.a with ref', async () => {
1754+
const expression = {
1755+
'specialNested.a': {eq: {ref: 'specialNested.a' as const}},
1756+
};
1757+
type Context = {
1758+
timesCounter: number;
1759+
userId: string;
1760+
specialNested?: Record<string, string | boolean | number | undefined |
1761+
(string | boolean | number | (string | boolean | number)[])[]>;
1762+
};
1763+
const context: ValidationContext<Context> = {
17031764
timesCounter: 5,
17041765
userId: '[email protected]',
17051766
specialNested: {
@@ -1715,7 +1776,13 @@ describe('evaluator', () => {
17151776
const expression = {
17161777
'specialNested.a': {eq: 5},
17171778
};
1718-
const context = {
1779+
type Context = {
1780+
timesCounter: number;
1781+
userId: string;
1782+
specialNested?: Record<string, string | boolean | number | undefined |
1783+
(string | boolean | number | (string | boolean | number)[])[]>;
1784+
};
1785+
const context:ValidationContext<Context> = {
17191786
timesCounter: 5,
17201787
userId: '[email protected]',
17211788
specialNested: {
@@ -1731,7 +1798,13 @@ describe('evaluator', () => {
17311798
const expression = {
17321799
'specialNested.b': {gt: 10},
17331800
};
1734-
const context = {
1801+
type Context = {
1802+
timesCounter: number;
1803+
userId: string;
1804+
specialNested?: Record<string, string | boolean | number | undefined |
1805+
(string | boolean | number | (string | boolean | number)[])[]>;
1806+
};
1807+
const context:ValidationContext<Context> = {
17351808
timesCounter: 5,
17361809
userId: '[email protected]',
17371810
specialNested: {
@@ -1747,7 +1820,13 @@ describe('evaluator', () => {
17471820
const expression = {
17481821
'specialNested.name': {regexp: '^test'},
17491822
};
1750-
const context = {
1823+
type Context = {
1824+
timesCounter: number;
1825+
userId: string;
1826+
specialNested?: Record<string, string | boolean | number | undefined |
1827+
(string | boolean | number | (string | boolean | number)[])[]>;
1828+
};
1829+
const context:ValidationContext<Context> = {
17511830
timesCounter: 5,
17521831
userId: '[email protected]',
17531832
specialNested: {
@@ -1763,7 +1842,13 @@ describe('evaluator', () => {
17631842
const expression = {
17641843
'specialNested.id': {inq: [1, 2, 3]},
17651844
};
1766-
const context = {
1845+
type Context = {
1846+
timesCounter: number;
1847+
userId: string;
1848+
specialNested?: Record<string, string | boolean | number | undefined |
1849+
(string | boolean | number | (string | boolean | number)[])[]>;
1850+
};
1851+
const context:ValidationContext<Context> = {
17671852
timesCounter: 5,
17681853
userId: '[email protected]',
17691854
specialNested: {
@@ -1779,7 +1864,12 @@ describe('evaluator', () => {
17791864
const expression = {
17801865
'recordNested.status': true,
17811866
};
1782-
const context = {
1867+
type Context = {
1868+
timesCounter: number;
1869+
userId: string;
1870+
recordNested?: Record<string, string | boolean | number | undefined>;
1871+
};
1872+
const context:ValidationContext<Context> = {
17831873
timesCounter: 5,
17841874
userId: '[email protected]',
17851875
recordNested: {
@@ -1798,7 +1888,22 @@ describe('evaluator', () => {
17981888
{'specialNested.b': {gt: 10}},
17991889
],
18001890
};
1801-
const context = {
1891+
type Context = {
1892+
timesCounter: number;
1893+
userId: string;
1894+
specialNested?: Record<string, string | boolean | number | undefined |
1895+
(string | boolean | number | (string | boolean | number)[])[]>;
1896+
};
1897+
const validationContext: ValidationContext<Context> = {
1898+
timesCounter: 5,
1899+
userId: '[email protected]',
1900+
specialNested: {
1901+
a: 3,
1902+
b: 15,
1903+
},
1904+
};
1905+
1906+
const context: Context = {
18021907
timesCounter: 5,
18031908
userId: '[email protected]',
18041909
specialNested: {
@@ -1807,7 +1912,7 @@ describe('evaluator', () => {
18071912
},
18081913
};
18091914
const runOpts: CustomEvaluatorFuncRunOptions = {dryRun: false};
1810-
expect(await validate(expression, context, functionsTable, runOpts)).to.be.an('undefined');
1915+
expect(await validate(expression, validationContext, functionsTable, runOpts)).to.be.an('undefined');
18111916
expect(await evaluate(expression, context, functionsTable, runOpts)).to.eql(true);
18121917
});
18131918
});

src/test/types/evaluator.test-d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ expectType<TestExpressionEvalWithRecords>(new ExpressionHandler<ContextWithRecor
230230
Ignore, CustomEvaluatorFuncRunOptions>({'recordNested.b': {inq: [1, 2, 3]}}, functionsForRecords));
231231
expectType<TestExpressionEvalWithRecords>(new ExpressionHandler<ContextWithRecords, ExpressionFunction,
232232
Ignore, CustomEvaluatorFuncRunOptions>({'recordNested.b': {exists: true}}, functionsForRecords));
233+
expectType<TestExpressionEvalWithRecords>(new ExpressionHandler<ContextWithRecords, ExpressionFunction,
234+
Ignore, CustomEvaluatorFuncRunOptions>({'recordNested.b': {eq: {ref: 'recordNested.c'}}}, functionsForRecords));
233235

234236
// specialNested - should extract primitive types, ignoring array types in union
235237
expectType<TestExpressionEvalWithRecords>(new ExpressionHandler<ContextWithRecords, ExpressionFunction,
@@ -250,3 +252,5 @@ expectType<TestExpressionEvalWithRecords>(new ExpressionHandler<ContextWithRecor
250252
Ignore, CustomEvaluatorFuncRunOptions>({'specialNested.c': {inq: ['a', 'b']}}, functionsForRecords));
251253
expectType<TestExpressionEvalWithRecords>(new ExpressionHandler<ContextWithRecords, ExpressionFunction,
252254
Ignore, CustomEvaluatorFuncRunOptions>({'specialNested.c': {exists: true}}, functionsForRecords));
255+
expectType<TestExpressionEvalWithRecords>(new ExpressionHandler<ContextWithRecords, ExpressionFunction,
256+
Ignore, CustomEvaluatorFuncRunOptions>({'specialNested.c': {eq: {ref: 'recordNested.b'}}}, functionsForRecords));

src/types/evaluator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export type Primitive = string | number | boolean;
1313

1414
export type PropertyPathsOfType<C extends Context, Ignore, V extends Primitive> = {
1515
[K in StringPaths<C, Ignore>]:
16-
Union.NonNullable<Object.Path<C, String.Split<K, '.'>>> extends V ? 1 : 0;
16+
Union.NonNullable<Extract<Object.Path<C, String.Split<K, '.'>>, V>> extends V ? 1 : 0;
1717
};
1818

1919
export type ExtractPropertyPathsOfType<T extends Record<string, 1 | 0>> = {

0 commit comments

Comments
 (0)