mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-11-30 03:08:31 +08:00
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) {
|
||||
const paths = key.split('.');
|
||||
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 isIndex = path.match(/^\d+$/);
|
||||
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 = {}) {
|
||||
const context = cloneDeep(scope);
|
||||
const exp = expression.trim().replace(/{{\s*([^{}]+)\s*}}/g, (_, v) => {
|
||||
appendArrayColumn(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);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ describe('workflow > instructions > calculation', () => {
|
||||
|
||||
const [execution] = await workflow.getExecutions();
|
||||
const [job] = await execution.getJobs();
|
||||
expect(job.result).toBe('a $context.data.title ');
|
||||
expect(job.result).toBe('a$context.data.title');
|
||||
});
|
||||
|
||||
it('text', async () => {
|
||||
|
Loading…
Reference in New Issue
Block a user