PromucFlow_constructor/app/client/src/workers/validations.test.ts
Abhinav Jha cd8407152c
Missing validations (#6281)
* Fix validations for certain scenarios which were missed earlier
2021-08-02 12:53:46 +05:30

650 lines
18 KiB
TypeScript

import { validate, WIDGET_TYPE_VALIDATION_ERROR } from "workers/validations";
import { WidgetProps } from "widgets/BaseWidget";
import { RenderModes, WidgetTypes } from "constants/WidgetConstants";
import { ValidationTypes } from "constants/WidgetValidation";
import moment from "moment";
const DUMMY_WIDGET: WidgetProps = {
bottomRow: 0,
isLoading: false,
leftColumn: 0,
parentColumnSpace: 0,
parentRowSpace: 0,
renderMode: RenderModes.CANVAS,
rightColumn: 0,
topRow: 0,
type: WidgetTypes.SKELETON_WIDGET,
version: 2,
widgetId: "",
widgetName: "",
};
describe("Validate Validators", () => {
it("correctly validates text", () => {
const validation = {
type: ValidationTypes.TEXT,
params: {
required: true,
default: "abc",
allowedValues: ["abc", "123", "mno", "test"],
},
};
const inputs = ["abc", "xyz", undefined, null, {}, [], 123];
const expected = [
{
isValid: true,
parsed: "abc",
},
{
isValid: false,
parsed: "abc",
message: "Value is not allowed",
},
{
isValid: false,
parsed: "abc",
message: `${WIDGET_TYPE_VALIDATION_ERROR} "string"`,
},
{
isValid: false,
parsed: "abc",
message: `${WIDGET_TYPE_VALIDATION_ERROR} "string"`,
},
{
isValid: false,
parsed: "{}",
message: `${WIDGET_TYPE_VALIDATION_ERROR} "string"`,
},
{
isValid: false,
parsed: "[]",
message: `${WIDGET_TYPE_VALIDATION_ERROR} "string"`,
},
{
isValid: true,
parsed: "123",
},
];
inputs.forEach((input, index) => {
const result = validate(validation, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates image url", () => {
const config = {
type: ValidationTypes.IMAGE_URL,
params: {
default:
"https://cdn.dribbble.com/users/1787323/screenshots/4563995/dribbbe_hammer-01.png",
required: true,
},
};
const inputs = [
"https://cdn.dribbble.com/users/1787323/screenshots/4563995/dribbbe_hammer-01.png",
"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAKAAoDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAQUGCP/EACAQAAICAgICAwAAAAAAAAAAAAECAwUEEQAhBkESFSL/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBv/EABwRAQAABwEAAAAAAAAAAAAAAAEAAgMEBREhQf/aAAwDAQACEQMRAD8A0nU5V9i+Q5/3NREaEpElc+NjGaVm1+iwQEhfe2A0ffIC5trSK3zYo8+dETIdVUMdABjocF9Z2UV1lRRWGXHGsxVVWZgAO+gN8WMSzFmPyYnZJ7JPAchcNQA5qKvEWktFmme7DyP/2Q==",
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAKAAoDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAQUGCP/EACAQAAICAgICAwAAAAAAAAAAAAECAwUEEQAhBkESFSL/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBv/EABwRAQAABwEAAAAAAAAAAAAAAAEAAgMEBREhQf/aAAwDAQACEQMRAD8A0nU5V9i+Q5/3NREaEpElc+NjGaVm1+iwQEhfe2A0ffIC5trSK3zYo8+dETIdVUMdABjocF9Z2UV1lRRWGXHGsxVVWZgAO+gN8WMSzFmPyYnZJ7JPAchcNQA5qKvEWktFmme7DyP/2Q==",
undefined,
];
const expected = [
{
isValid: true,
parsed:
"https://cdn.dribbble.com/users/1787323/screenshots/4563995/dribbbe_hammer-01.png",
},
{
isValid: true,
parsed:
"data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAKAAoDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAQUGCP/EACAQAAICAgICAwAAAAAAAAAAAAECAwUEEQAhBkESFSL/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBv/EABwRAQAABwEAAAAAAAAAAAAAAAEAAgMEBREhQf/aAAwDAQACEQMRAD8A0nU5V9i+Q5/3NREaEpElc+NjGaVm1+iwQEhfe2A0ffIC5trSK3zYo8+dETIdVUMdABjocF9Z2UV1lRRWGXHGsxVVWZgAO+gN8WMSzFmPyYnZJ7JPAchcNQA5qKvEWktFmme7DyP/2Q==",
},
{
isValid: true,
parsed:
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAKAAoDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAQUGCP/EACAQAAICAgICAwAAAAAAAAAAAAECAwUEEQAhBkESFSL/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBv/EABwRAQAABwEAAAAAAAAAAAAAAAEAAgMEBREhQf/aAAwDAQACEQMRAD8A0nU5V9i+Q5/3NREaEpElc+NjGaVm1+iwQEhfe2A0ffIC5trSK3zYo8+dETIdVUMdABjocF9Z2UV1lRRWGXHGsxVVWZgAO+gN8WMSzFmPyYnZJ7JPAchcNQA5qKvEWktFmme7DyP/2Q==",
},
{
isValid: false,
parsed:
"https://cdn.dribbble.com/users/1787323/screenshots/4563995/dribbbe_hammer-01.png",
message: `${WIDGET_TYPE_VALIDATION_ERROR}: base64 string or data uri or URL`,
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates number", () => {
const config = {
type: ValidationTypes.NUMBER,
params: {
required: true,
min: 100,
max: 200,
default: 150,
},
};
const inputs = [120, 90, 220, undefined, {}, [], "120"];
const expected = [
{
isValid: true,
parsed: 120,
},
{
isValid: false,
parsed: 90,
message: "Minimum allowed value: 100",
},
{
isValid: false,
parsed: 220,
message: "Maximum allowed value: 200",
},
{
isValid: false,
parsed: 150,
message: "This value is required",
},
{
isValid: false,
parsed: 150,
message: `${WIDGET_TYPE_VALIDATION_ERROR} "number"`,
},
{
isValid: false,
parsed: 150,
message: `${WIDGET_TYPE_VALIDATION_ERROR} "number"`,
},
{
isValid: true,
parsed: 120,
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates boolean", () => {
const config = {
type: ValidationTypes.BOOLEAN,
params: {
default: false,
required: true,
},
};
const inputs = ["123", undefined, false, true, [], {}, "true", "false"];
const expected = [
{
isValid: false,
message: `${WIDGET_TYPE_VALIDATION_ERROR} "boolean"`,
parsed: false,
},
{
isValid: false,
message: `${WIDGET_TYPE_VALIDATION_ERROR} "boolean"`,
parsed: false,
},
{
isValid: true,
parsed: false,
},
{
isValid: true,
parsed: true,
},
{
isValid: false,
message: `${WIDGET_TYPE_VALIDATION_ERROR} "boolean"`,
parsed: false,
},
{
isValid: false,
message: `${WIDGET_TYPE_VALIDATION_ERROR} "boolean"`,
parsed: false,
},
{
isValid: true,
parsed: true,
},
{
isValid: true,
parsed: false,
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates object", () => {
const config = {
type: ValidationTypes.OBJECT,
params: {
required: true,
default: { key1: 120, key2: "abc" },
allowedKeys: [
{
name: "key1",
type: ValidationTypes.NUMBER,
params: {
default: 120,
},
},
{
name: "key2",
type: ValidationTypes.TEXT,
params: {
default: "abc",
allowedValues: ["abc", "mnop"],
},
},
],
},
};
const inputs = [
{ key1: 100, key2: "mnop" },
`{ "key1": 100, "key2": "mnop" }`,
{ key3: "abc", key1: 30 },
undefined,
[],
{ key1: [], key2: "abc" },
{ key1: 120, key2: {} },
];
const expected = [
{
isValid: true,
parsed: { key1: 100, key2: "mnop" },
},
{
isValid: true,
parsed: { key1: 100, key2: "mnop" },
},
{
isValid: true,
parsed: { key1: 30, key3: "abc" },
},
{
isValid: false,
parsed: { key1: 120, key2: "abc" },
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Object`,
},
{
isValid: false,
parsed: { key1: 120, key2: "abc" },
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Object`,
},
{
isValid: false,
parsed: { key1: 120, key2: "abc" },
message: `Value of key: key1 is invalid: This value does not evaluate to type \"number\"`,
},
{
isValid: false,
parsed: { key1: 120, key2: "abc" },
message: `Value of key: key2 is invalid: This value does not evaluate to type "string"`,
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates array", () => {
const inputs = [
["a", "b", "c"],
["m", "n", "b"],
["p", "r", "q"],
[],
{},
undefined,
null,
"ABC",
`["a", "b", "c"]`,
'{ "key": "value" }',
];
const config = {
type: ValidationTypes.ARRAY,
params: {
required: true,
children: {
type: ValidationTypes.TEXT,
params: {
required: true,
allowedValues: ["a", "b", "c", "n", "m", "p", "r"],
},
},
},
};
const expected = [
{
isValid: true,
parsed: ["a", "b", "c"],
message: "",
},
{
isValid: true,
parsed: ["m", "n", "b"],
message: "",
},
{
isValid: false,
parsed: ["p", "r", "q"],
message: "Invalid entry at index: 2. Value is not allowed",
},
{
isValid: true,
parsed: [],
message: "",
},
{
isValid: false,
parsed: [],
message: "This value does not evaluate to type Array",
},
{
isValid: false,
parsed: [],
message:
"This property is required for the widget to function correctly",
},
{
isValid: false,
parsed: [],
message:
"This property is required for the widget to function correctly",
},
{
isValid: false,
parsed: [],
message: "This value does not evaluate to type Array",
},
{
isValid: true,
parsed: ["a", "b", "c"],
message: "",
},
{
isValid: false,
parsed: [],
message: "This value does not evaluate to type Array",
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates array with specific object children", () => {
const inputs = [
[{ label: 123, value: 234 }],
`[{"label": 123, "value": 234}]`,
[{ labels: 123, value: 234 }],
[{ label: "abcd", value: 234 }],
];
const config = {
type: ValidationTypes.ARRAY,
params: {
required: true,
children: {
type: ValidationTypes.OBJECT,
params: {
allowedKeys: [
{
name: "label",
type: ValidationTypes.NUMBER,
params: {
required: true,
},
},
{
name: "value",
type: ValidationTypes.NUMBER,
params: {
required: true,
},
},
],
},
},
},
};
const expected = [
{
isValid: true,
parsed: [{ label: 123, value: 234 }],
message: "",
},
{
isValid: true,
parsed: [{ label: 123, value: 234 }],
message: "",
},
{
isValid: false,
parsed: [{ labels: 123, value: 234 }],
message: "Invalid entry at index: 0. Missing required key: label",
},
{
isValid: false,
parsed: [{ label: 0, value: 234 }],
message: `Invalid entry at index: 0. Value of key: label is invalid: This value does not evaluate to type "number"`,
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates date iso string", () => {
const defaultLocalDate = moment().toISOString(true);
const defaultDate = moment().toISOString();
const inputs = [
defaultDate,
defaultLocalDate,
"2021-08-08",
undefined,
null,
];
const config = {
type: ValidationTypes.DATE_ISO_STRING,
params: {
required: true,
default: defaultDate,
},
};
const expected = [
{
isValid: true,
parsed: defaultDate,
},
{
isValid: true,
parsed: defaultLocalDate,
},
{
isValid: true,
parsed: moment("2021-08-08").toISOString(true),
},
{
isValid: false,
parsed: defaultDate,
message: "This value does not evaluate to type: ISO 8601 date string",
},
{
isValid: false,
parsed: defaultDate,
message: "This value does not evaluate to type: ISO 8601 date string",
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates object array", () => {
const inputs = [
[
{ apple: 1 },
{ orange: 2, mango: "fruit", watermelon: false },
{ banana: 3 },
],
`[{ "apple": 1, "orange": 2, "mango": "fruit", "watermelon": false }]`,
{},
undefined,
null,
[],
123,
"abcd",
];
const config = {
type: ValidationTypes.OBJECT_ARRAY,
params: {
required: true,
default: [{ id: 1, name: "alpha" }],
},
};
const expected = [
{
isValid: true,
parsed: [
{ apple: 1 },
{ orange: 2, mango: "fruit", watermelon: false },
{ banana: 3 },
],
},
{
isValid: true,
parsed: [{ apple: 1, orange: 2, mango: "fruit", watermelon: false }],
},
{
isValid: false,
parsed: [{ id: 1, name: "alpha" }],
message: "This value does not evaluate to type Array of objects",
},
{
isValid: false,
parsed: [{ id: 1, name: "alpha" }],
message: "This value does not evaluate to type Array of objects",
},
{
isValid: false,
parsed: [{ id: 1, name: "alpha" }],
message: "This value does not evaluate to type Array of objects",
},
{
isValid: false,
parsed: [{ id: 1, name: "alpha" }],
message: "This value does not evaluate to type Array of objects",
},
{
isValid: false,
parsed: [{ id: 1, name: "alpha" }],
message: "This value does not evaluate to type Array of objects",
},
{
isValid: false,
parsed: [{ id: 1, name: "alpha" }],
message: "This value does not evaluate to type Array of objects",
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
it("correctly validates safe URL", () => {
const config = {
type: ValidationTypes.SAFE_URL,
params: {
default: "https://wikipedia.org",
},
};
const inputs = [
"https://wikipedia.org",
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",
"javascript:alert(document.cookie)",
"data:text/html,<svg onload=alert(1)>",
];
const expected = [
{
isValid: true,
parsed: "https://wikipedia.org",
},
{
isValid: true,
parsed:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",
},
{
isValid: false,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: URL`,
parsed: "https://wikipedia.org",
},
{
isValid: false,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: URL`,
parsed: "https://wikipedia.org",
},
];
inputs.forEach((input, index) => {
const result = validate(config, input, DUMMY_WIDGET);
expect(result).toStrictEqual(expected[index]);
});
});
});
// describe("Color Picker Text validator", () => {
// const validator = VALIDATORS.COLOR_PICKER_TEXT;
// const inputs = [
// "#e0e0e0",
// "rgb(200,200,200)",
// "{{Text2.text}}",
// "<p>red</p>",
// ];
// const expected = [
// {
// isValid: true,
// parsed: "#e0e0e0",
// },
// {
// isValid: true,
// parsed: "rgb(200,200,200)",
// },
// {
// isValid: false,
// parsed: "",
// message: "This value does not evaluate to type: text",
// },
// {
// isValid: false,
// parsed: "",
// message: "This value does not evaluate to type: text",
// },
// ];
// inputs.forEach((input, index) => {
// const response = validator(input, DUMMY_WIDGET);
// expect(response).toStrictEqual(expected[index]);
// });
// });