PromucFlow_constructor/app/client/src/workers/evaluationSubstitution.test.ts

353 lines
10 KiB
TypeScript

import { substituteDynamicBindingWithValues } from "workers/evaluationSubstitution";
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
describe("substituteDynamicBindingWithValues", () => {
describe("template substitution", () => {
it("substitutes strings values", () => {
const binding = "Hello {{name}}";
const subBindings = ["Hello ", "{{name}}"];
const subValues = ["Hello ", "Tester"];
const expected = "Hello Tester";
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.TEMPLATE,
);
expect(result).toBe(expected);
});
it("substitute number values", () => {
const binding = "My age is {{age}}";
const subBindings = ["My age is ", "{{age}}"];
const subValues = ["My age is ", 16];
const expected = "My age is 16";
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.TEMPLATE,
);
expect(result).toBe(expected);
});
it("substitute objects/ arrays values", () => {
const binding = "Response was {{response}}";
const subBindings = ["Response was ", "{{response}}"];
const subValues = ["Response was ", { message: "Unauthorised user" }];
const expected = 'Response was {\\"message\\":\\"Unauthorised user\\"}';
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.TEMPLATE,
);
expect(result).toBe(expected);
});
it("substitute multiple values values", () => {
const binding =
"My name is {{name}}. My age is {{age}}. Response: {{response}}";
const subBindings = [
"My name is ",
"{{name}}",
". My age is ",
"{{age}}",
". Response: ",
"{{response}}",
];
const subValues = [
"My name is ",
"Tester",
". My age is ",
16,
". Response: ",
{ message: "Unauthorised user" },
];
const expected =
'My name is Tester. My age is 16. Response: {\\"message\\":\\"Unauthorised user\\"}';
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.TEMPLATE,
);
expect(result).toBe(expected);
});
});
describe("parameter substitution", () => {
it("replaces bindings with $variables", () => {
const binding = "SELECT * from {{tableName}} LIMIT {{limit}}";
const subBindings = [
"SELECT * from ",
"{{tableName}}",
" LIMIT ",
"{{limit}}",
];
const subValues = ["SELECT * from ", "users", " LIMIT ", 10];
const expected = {
value: "SELECT * from $1 LIMIT $2",
parameters: {
$1: "users",
$2: 10,
},
};
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.PARAMETER,
);
expect(result).toHaveProperty("value");
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(result.value).toBe(expected.value);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(result.parameters).toStrictEqual(expected.parameters);
});
it("removed quotes around bindings", () => {
const binding =
'SELECT * from users WHERE lastname = "{{lastname}}" LIMIT {{limit}}';
const subBindings = [
'SELECT * from users WHERE lastname = "',
"{{lastname}}",
'" LIMIT ',
"{{limit}}",
];
const subValues = [
'SELECT * from users WHERE lastname = "',
"Smith",
'" LIMIT ',
10,
];
const expected = {
value: "SELECT * from users WHERE lastname = $1 LIMIT $2",
parameters: {
$1: "Smith",
$2: 10,
},
};
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.PARAMETER,
);
expect(result).toHaveProperty("value");
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(result.value).toBe(expected.value);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(result.parameters).toStrictEqual(expected.parameters);
});
it("stringifies objects and arrays", () => {
const binding = "SELECT * from {{testObject}} WHERE {{testArray}}";
const subBindings = [
"SELECT * from ",
"{{testObject}}",
" WHERE ",
"{{testArray}}",
];
const subValues = [
"SELECT * from ",
{ name: "tester" },
" WHERE ",
[42, "meaning", false],
];
const expected = {
value: "SELECT * from $1 WHERE $2",
parameters: {
$1: `{\n \"name\": \"tester\"\n}`,
$2: `[\n 42,\n \"meaning\",\n false\n]`,
},
};
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.PARAMETER,
);
expect(result).toHaveProperty("value");
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(result.value).toBe(expected.value);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(result.parameters).toStrictEqual(expected.parameters);
});
});
describe("smart substitution", () => {
it("substitutes strings, numbers, boolean, undefined, null values correctly", () => {
const binding = `{
"name": {{name}},
"age": {{age}},
"isHuman": {{isHuman}},
"wrongBinding": {{wrongBinding}},
"emptyBinding": {{emptyBinding}},
}`;
const subBindings = [
'{\n "name": ',
"{{name}}",
',\n "age": ',
"{{age}}",
',\n "isHuman": ',
"{{isHuman}}",
',\n "wrongBinding": ',
"{{wrongBinding}}",
',\n "emptyBinding": ',
"{{emptyBinding}}",
",\n }",
];
const subValues = [
'{\n "name": ',
"Tester",
',\n "age": ',
42,
',\n "isHuman": ',
false,
',\n "wrongBinding": ',
undefined,
',\n "emptyBinding": ',
null,
",\n }",
];
const expected = `{
"name": "Tester",
"age": 42,
"isHuman": false,
"wrongBinding": undefined,
"emptyBinding": null,
}`;
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.SMART_SUBSTITUTE,
);
expect(result).toBe(expected);
});
it("substitute objects/ arrays values", () => {
const binding = `{\n "data": {{formData}}\n}`;
const subBindings = ["{\n data: ", "{{formData}}", "\n}"];
const subValues = [
'{\n "data": ',
{
name: "Tester",
age: 42,
isHuman: false,
wrongBinding: undefined,
emptyBinding: null,
},
"\n}",
];
const expected =
'{\n "data": {\n "name": "Tester",\n "age": 42,\n "isHuman": false,\n "emptyBinding": null\n}\n}';
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.SMART_SUBSTITUTE,
);
expect(result).toBe(expected);
});
it("substitute correctly when quotes are surrounding the binding", () => {
const binding = `{
"name": "{{name}}",
"age": "{{age}}",
isHuman: {{isHuman}},
"wrongBinding": {{wrongBinding}},
"emptyBinding": "{{emptyBinding}}",
}`;
const subBindings = [
'{\n "name": "',
"{{name}}",
'",\n "age": "',
"{{age}}",
'",\n isHuman: ',
"{{isHuman}}",
',\n "wrongBinding": ',
"{{wrongBinding}}",
',\n "emptyBinding": "',
"{{emptyBinding}}",
'",\n }',
];
const subValues = [
'{\n "name": "',
"Tester",
'",\n "age": "',
42,
'",\n isHuman: ',
false,
',\n "wrongBinding": ',
undefined,
',\n "emptyBinding": "',
null,
'",\n }',
];
const expected = `{
"name": "Tester",
"age": 42,
isHuman: false,
"wrongBinding": undefined,
"emptyBinding": null,
}`;
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.SMART_SUBSTITUTE,
);
expect(result).toBe(expected);
});
it("escapes strings before substitution", () => {
const binding = `{\n "paragraph": {{paragraph}},\n}`;
const subBindings = ['{\n "paragraph": ', "{{paragraph}}", ",\n}"];
const subValues = [
'{\n "paragraph": ',
`This is a \f string \b with \n many different " characters that are not \n all. these \r\t`,
",\n}",
];
const expected = `{\n "paragraph": "This is a \\f string \\b with \\n many different \\" characters that are not \\n all. these \\r\\t",\n}`;
const result = substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.SMART_SUBSTITUTE,
);
expect(result).toBe(expected);
});
it("throws error when only binding is provided in parameter substitution", () => {
const binding = `{{ appsmith }}`;
const subBindings = ["{{appsmith}}"];
const subValues = [{ test: "object" }];
expect(() =>
substituteDynamicBindingWithValues(
binding,
subBindings,
subValues,
EvaluationSubstitutionType.PARAMETER,
),
).toThrowError();
});
});
});