fix(operators): Update tests for _js and _actions.

This commit is contained in:
Gervwyk 2021-05-16 10:59:29 +02:00
parent 2113ae5c74
commit 022893bbca
5 changed files with 101 additions and 75 deletions

View File

@ -122,16 +122,16 @@ function _js({ context, params, location, methodName }) {
throw new Error(`Operator Error: _js.${methodName} is not a function.`);
}
if (context.lowdefy.imports.jsOperators[methodName]) {
if (!type.isArray(params)) {
if (!type.isNone(params) && !type.isArray(params)) {
throw new Error(`Operator Error: _js.${methodName} takes an array as input at ${location}.`);
}
return context.lowdefy.imports.jsOperators[methodName](...params);
return context.lowdefy.imports.jsOperators[methodName](...(params || []));
}
// ! DEPRECATED ---------------
console.warn(
'WARNING: _js.evaluate and _js.function will has been deprecated and will be removed in the next version. Please see: https://docs.lowdefy.com/_js for more details.'
);
if (type.isObject(params)) {
if (!type.isObject(params)) {
throw new Error(`Operator Error: _js.${methodName} takes an object as input at ${location}.`);
}
return _DEPRECATED_js({ params, location, methodName });

View File

@ -479,22 +479,6 @@ describe('parse operators', () => {
expect(errors).toEqual([]);
});
test('parse _js operator', async () => {
const input = {
'_js.function': {
code: `function (a,b){
return a+b;
}`,
},
};
const parser = new NodeParser({});
await parser.init();
const { output, errors } = parser.parse({ input, location: 'locationId' });
expect(output).toBeInstanceOf(Function);
expect(output(1, 2)).toEqual(3);
expect(errors).toEqual([]);
});
test('parse _index operator', async () => {
const input = { _index: 0 };
const parser = new NodeParser({ input: { key: 'value' }, arrayIndices: [3, 2] });

View File

@ -7,6 +7,10 @@ const operators = Object.keys({
});
const lowdefy = {
imports: {
jsOperators: {},
jsActions: {},
},
inputs: {
own: {
string: 'input',

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
import actions from '../../src/common/actions';
import actions from '../../src/web/actions';
import getFromObject from '../../src/getFromObject';
jest.mock('../../src/getFromObject');

View File

@ -14,13 +14,54 @@
limitations under the License.
*/
import _js from '../../src/common/js';
import _js from '../../src/web/js';
import { context } from '../testContext';
const location = 'location';
beforeAll(async () => {
await _js.init();
});
test('_js.test_fn and params to return a value', () => {
const params = [12, 14];
const test_fn = (a, b) => a + b;
const mockFn = jest.fn().mockImplementation(test_fn);
context.lowdefy.imports.jsOperators.test_fn = mockFn;
expect(_js({ context, location, params, methodName: 'test_fn' })).toEqual(26);
});
test('_js.test_fn no params to return a value', () => {
const test_fn = () => 'some value';
const mockFn = jest.fn().mockImplementation(test_fn);
context.lowdefy.imports.jsOperators.test_fn = mockFn;
expect(_js({ context, location, params: undefined, methodName: 'test_fn' })).toEqual(
'some value'
);
});
test('_js.test_fn and params to return a function', () => {
const params = [12, 14];
const test_fn = (a, b) => (c) => a + b + c;
const mockFn = jest.fn().mockImplementation(test_fn);
context.lowdefy.imports.jsOperators.test_fn = mockFn;
const fn = _js({ context, location, params, methodName: 'test_fn' });
expect(fn).toBeInstanceOf(Function);
expect(fn(4)).toEqual(30);
});
test('_js.test_fn params not an array', () => {
const params = 10;
const test_fn = (a, b) => a + b;
const mockFn = jest.fn().mockImplementation(test_fn);
context.lowdefy.imports.jsOperators.test_fn = mockFn;
expect(() => _js({ context, location, params, methodName: 'test_fn' })).toThrow(
new Error('Operator Error: _js.test_fn takes an array as input at location.')
);
});
// ! --------------
// ! DEPRECATED
// ! --------------
test('_js with code and args specified', () => {
const params = {
code: `function (one, two) {
@ -28,11 +69,13 @@ test('_js with code and args specified', () => {
}`,
args: [12, 14],
};
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
expect(fn(1, 2)).toEqual(3);
expect(_js({ location, params, methodName: 'evaluate' })).toEqual(26);
expect(_js({ location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(null);
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual(26);
expect(_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(
null
);
});
test('_js with code and args specified to return json object', () => {
@ -42,17 +85,19 @@ test('_js with code and args specified to return json object', () => {
}`,
args: [12, 14],
};
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
expect(fn(1, 2)).toEqual({ a: 1, b: 2, c: [1, 2, 3, 1, 2, 'three'] });
expect(_js({ location, params, methodName: 'evaluate' })).toEqual({
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual({
a: 12,
b: 14,
c: [1, 2, 3, 12, 14, 'three'],
});
expect(_js({ location, params: { code: params.code }, methodName: 'evaluate' })).toEqual({
expect(_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(
{
c: [1, 2, 3, null, null, 'three'],
});
}
);
});
test('_js with code and args specified to return json array', () => {
@ -62,18 +107,20 @@ test('_js with code and args specified to return json array', () => {
}`,
args: [12, 14],
};
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
expect(fn(1, 2)).toEqual([1, 2, 3, 1, 2, 'three']);
expect(_js({ location, params, methodName: 'evaluate' })).toEqual([1, 2, 3, 12, 14, 'three']);
expect(_js({ location, params: { code: params.code }, methodName: 'evaluate' })).toEqual([
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual([
1,
2,
3,
null,
null,
12,
14,
'three',
]);
expect(
_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })
).toEqual([1, 2, 3, null, null, 'three']);
});
test('_js with open "\'" in result', () => {
@ -84,10 +131,10 @@ test('_js with open "\'" in result', () => {
}`,
args: [str],
};
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
expect(fn(str)).toEqual([{ x: str, b: 1 }]);
expect(_js({ location, params, methodName: 'evaluate' })).toEqual([{ x: str, b: 1 }]);
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual([{ x: str, b: 1 }]);
});
test('_js with date in input and result', () => {
@ -103,10 +150,10 @@ test('_js with date in input and result', () => {
}`,
args: [new Date(0), new Date(10)],
};
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
expect(_js({ location, params, methodName: 'evaluate' })).toEqual({
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual({
from: new Date(0),
to: new Date(10),
duration: 10,
@ -129,11 +176,13 @@ test('_js with undefined result returns null', () => {
}`,
args: [12, 14],
};
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
expect(fn()).toEqual(null);
expect(_js({ location, params, methodName: 'evaluate' })).toEqual(null);
expect(_js({ location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(null);
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual(null);
expect(_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(
null
);
});
test('_js with console.log', () => {
@ -148,9 +197,9 @@ test('_js with console.log', () => {
}`,
args: [12, new Date(1)],
};
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
_js({ location, params, methodName: 'evaluate' });
_js({ context, location, params, methodName: 'evaluate' });
expect(console.log.mock.calls).toEqual([
[12],
[new Date(1)],
@ -170,10 +219,10 @@ test('_js with code with args that needs escaped characters', () => {
},
],
};
expect(_js({ location, params, methodName: 'evaluate' })).toEqual(
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual(
'<div><a href="https://lowdefy.com">Lowdefy Website</a></html>'
);
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(fn).toBeInstanceOf(Function);
expect(
fn({
@ -191,10 +240,10 @@ test('_js with code and no "function" specified to throw', () => {
};
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(`"unexpected token in expression: 'var'"`);
expect(() => {
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
fn();
}).toThrowErrorMatchingInlineSnapshot(`"unexpected token in expression: 'var'"`);
});
@ -204,9 +253,9 @@ test('_js invalid js code', () => {
code: 'Hello',
};
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(`"'Hello' is not defined"`);
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(() => fn()).toThrowErrorMatchingInlineSnapshot(`"'Hello' is not defined"`);
});
@ -215,21 +264,21 @@ test('_js not a function', () => {
code: '"Hello"',
};
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(`"not a function"`);
const fn = _js({ location, params, methodName: 'function' });
const fn = _js({ context, location, params, methodName: 'function' });
expect(() => fn()).toThrowErrorMatchingInlineSnapshot(`"not a function"`);
});
test('_js params not a object', () => {
const params = [];
expect(() =>
_js({ location, params, methodName: 'function' })
_js({ context, location, params, methodName: 'function' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.function takes an object as input at location."`
);
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.evaluate takes an object as input at location."`
);
@ -241,9 +290,9 @@ test('_js.invalid methodName', () => {
return args[0] + args[1]
}`,
};
expect(() => _js({ location, params, methodName: 'invalid' })).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.invalid is not supported at location. Use one of the following: evaluate, function."`
);
expect(() =>
_js({ context, location, params, methodName: 'invalid' })
).toThrowErrorMatchingInlineSnapshot(`"Operator Error: _js.invalid is not a function."`);
});
test('_js invalid js code', () => {
@ -251,12 +300,12 @@ test('_js invalid js code', () => {
code: 1,
};
expect(() =>
_js({ location, params, methodName: 'function' })
_js({ context, location, params, methodName: 'function' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.function \\"code\\" argument should be a string at location."`
);
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.evaluate \\"code\\" argument should be a string at location."`
);
@ -265,12 +314,12 @@ test('_js invalid js code', () => {
test('_js no body or file', () => {
const params = {};
expect(() =>
_js({ location, params, methodName: 'function' })
_js({ context, location, params, methodName: 'function' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.function \\"code\\" argument should be a string at location."`
);
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.evaluate \\"code\\" argument should be a string at location."`
);
@ -284,7 +333,7 @@ test('_js.evaluate, args not an array', () => {
}`,
};
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js.evaluate \\"args\\" argument should be an array, null or undefined at location."`
);
@ -298,25 +347,14 @@ test('_js with undefined vm', () => {
};
_js.clear();
expect(() =>
_js({ location, params, methodName: 'function' })
_js({ context, location, params, methodName: 'function' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js is not initialized. Received: {\\"code\\":\\"{\\\\n return args[0] + args[1]\\\\n }\\"} at location."`
);
expect(() =>
_js({ location, params, methodName: 'evaluate' })
_js({ context, location, params, methodName: 'evaluate' })
).toThrowErrorMatchingInlineSnapshot(
`"Operator Error: _js is not initialized. Received: {\\"code\\":\\"{\\\\n return args[0] + args[1]\\\\n }\\"} at location."`
);
});
// TODO: interrupt handler does not seem to work.
// test('_js interrupts infinite loop execution', () => {
// const params = {
// body: `{
// i = 0; while (1) { i++ }
// }`,
// };
// expect(() =>
// _js({ location, instances, params, methodName: 'evaluate' })
// ).toThrowErrorMatchingInlineSnapshot();
// });
// ! --------------