fix(evaluators): fix preprocessing and add test cases (#1519)
* fix(evaluators): fix preprocessing and add test cases * fix(plugin-workflow): fix calculation test case
This commit is contained in:
parent
f8256548e5
commit
ac039ad0e2
42
packages/core/evaluators/src/server/__tests__/index.test.ts
Normal file
42
packages/core/evaluators/src/server/__tests__/index.test.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import evaluators from '..';
|
||||||
|
|
||||||
|
const mathEval = evaluators.get('math.js');
|
||||||
|
const formulaEval = evaluators.get('formula.js');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
describe('evaluate', () => {
|
||||||
|
it('reference null or undefined', () => {
|
||||||
|
const result = formulaEval('{{a.b}}', { a: null });
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('function result string with quote', () => {
|
||||||
|
const result = formulaEval('{{a}}', { a() { return "I'm done." } });
|
||||||
|
expect(result).toBe("I'm done.");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('function result number', () => {
|
||||||
|
const result = formulaEval('{{a}}', { a() { return 1 } });
|
||||||
|
expect(result).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('number path to array item 0 (math.js)', () => {
|
||||||
|
expect(() => mathEval('{{a.0}}', { a: [1, 2, 3] })).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('number path to array item 1 (math.js)', () => {
|
||||||
|
const result = mathEval('{{a}}[1]', { a: [1, 2, 3] });
|
||||||
|
expect(result).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('number path to array item 1 (math.js)', () => {
|
||||||
|
const result = mathEval('{{a.1}}', { a: [1, 2, 3] });
|
||||||
|
expect(result).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('number path to object member 0 (math.js)', () => {
|
||||||
|
const result = mathEval('{{a.1}}', { a: { 1: 1 } });
|
||||||
|
expect(result).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
@ -9,7 +9,7 @@ export type Evaluator = (expression: string, scope?: Scope) => any;
|
|||||||
function appendArrayColumn(scope, key) {
|
function appendArrayColumn(scope, key) {
|
||||||
const paths = key.split('.');
|
const paths = key.split('.');
|
||||||
let data = scope;
|
let data = scope;
|
||||||
for (let p = 0; p < paths.length; p++) {
|
for (let p = 0; p < paths.length && data != null; p++) {
|
||||||
const path = paths[p];
|
const path = paths[p];
|
||||||
const isIndex = path.match(/^\d+$/);
|
const isIndex = path.match(/^\d+$/);
|
||||||
if (Array.isArray(data) && !isIndex && !data[path]) {
|
if (Array.isArray(data) && !isIndex && !data[path]) {
|
||||||
@ -19,13 +19,43 @@ function appendArrayColumn(scope, key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function replaceNumberIndex(path: string, scope: Scope): string {
|
||||||
|
const segments = path.split('.');
|
||||||
|
const paths = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < segments.length; i++) {
|
||||||
|
const p = segments[i];
|
||||||
|
if (p.match(/^\d+$/)) {
|
||||||
|
paths.push(Array.isArray(get(scope, segments.slice(0, i))) ? `[${p}]` : `["${p}"]`);
|
||||||
|
} else {
|
||||||
|
if (i) {
|
||||||
|
paths.push('.', p);
|
||||||
|
} else {
|
||||||
|
paths.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths.join('');
|
||||||
|
}
|
||||||
|
|
||||||
export function evaluate(this: Evaluator, expression: string, scope: Scope = {}) {
|
export function evaluate(this: Evaluator, expression: string, scope: Scope = {}) {
|
||||||
const context = cloneDeep(scope);
|
const context = cloneDeep(scope);
|
||||||
const exp = expression.trim().replace(/{{\s*([^{}]+)\s*}}/g, (_, v) => {
|
const exp = expression.trim().replace(/{{\s*([^{}]+)\s*}}/g, (_, v) => {
|
||||||
appendArrayColumn(context, v);
|
appendArrayColumn(context, v);
|
||||||
|
|
||||||
const item = get(context, v);
|
const item = get(context, v);
|
||||||
const key = v.replace(/\.(\d+)/g, '["$1"]');
|
|
||||||
return ` ${typeof item === 'function' ? item() : key} `;
|
if (item == null) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof item === 'function') {
|
||||||
|
const result = item();
|
||||||
|
return typeof result === 'string' ? `'${result.replace(/'/g, "\\'")}'` : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replaceNumberIndex(v, context);
|
||||||
});
|
});
|
||||||
return this(exp, context);
|
return this(exp, context);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user