fix: chartWidget fix for "TypeError: r.palettecolors.split" (#7717)

* adding validation for fusion chart's paletteColors Attribute

* restructuring as params for TEXT type

* removing unnecessary space

* addressing review comments

* adding validations to ignore case
This commit is contained in:
rahulramesha 2021-09-23 18:12:34 +05:30 committed by GitHub
parent f0325c11c6
commit fb7143cef2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 144 additions and 14 deletions

View File

@ -88,6 +88,8 @@ type ValidationConfigParams = {
) => ValidationResponse; // Function in a FUNCTION type
fnString?: string; // AUTO GENERATED, SHOULD NOT BE SET BY WIDGET DEVELOPER
expected?: CodeEditorExpected; // FUNCTION type expected type and example
strict?: boolean; //for strict string validation of TEXT type
ignoreCase?: boolean; //to ignore the case of key
};
export type ValidationConfig = {

View File

@ -96,6 +96,16 @@ export default [
name: "chart",
type: ValidationTypes.OBJECT,
params: {
allowedKeys: [
{
name: "paletteColors",
type: ValidationTypes.TEXT,
params: {
strict: true,
ignoreCase: true,
},
},
],
default: {},
},
},

View File

@ -96,6 +96,39 @@ describe("Validate Validators", () => {
});
});
it("correctly validates strict text", () => {
const validation = {
type: ValidationTypes.TEXT,
params: {
required: true,
default: "abc",
allowedValues: ["abc", "123", "mno", "test"],
strict: true,
},
};
const inputs = ["abc", "xyz", 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 ( abc | 123 | mno | test )`,
},
];
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,
@ -939,6 +972,10 @@ describe("Validate Validators", () => {
label: true,
value: "true",
},
{
paletteColors1: "#ffffff",
palettecolors2: "#ffffff",
},
];
const config = [
{
@ -987,6 +1024,28 @@ describe("Validate Validators", () => {
],
},
},
{
type: ValidationTypes.OBJECT,
params: {
allowedKeys: [
{
name: "paletteColors1",
type: ValidationTypes.TEXT,
params: {
strict: true,
},
},
{
name: "paletteColors2",
type: ValidationTypes.TEXT,
params: {
strict: true,
ignoreCase: true,
},
},
],
},
},
];
const expected = [
{
@ -1000,6 +1059,13 @@ describe("Validate Validators", () => {
isValid: true,
parsed: { label: true, value: "true" },
},
{
isValid: true,
parsed: {
paletteColors1: "#ffffff",
palettecolors2: "#ffffff",
},
},
];
inputs.forEach((input, index) => {
const result = validate(config[index], input, DUMMY_WIDGET);
@ -1015,6 +1081,10 @@ describe("Validate Validators", () => {
{
label: true,
},
{
paletteColors1: "#ffffff",
palettecolors2: 3,
},
];
const config = [
{
@ -1063,6 +1133,28 @@ describe("Validate Validators", () => {
],
},
},
{
type: ValidationTypes.OBJECT,
params: {
allowedKeys: [
{
name: "paletteColors1",
type: ValidationTypes.TEXT,
params: {
strict: true,
},
},
{
name: "paletteColors2",
type: ValidationTypes.TEXT,
params: {
strict: true,
ignoreCase: true,
},
},
],
},
},
];
const expected = [
{
@ -1078,6 +1170,15 @@ describe("Validate Validators", () => {
message: "Missing required key: value",
parsed: { label: true },
},
{
isValid: false,
message:
"Value of key: palettecolors2 is invalid: This value does not evaluate to type string",
parsed: {
paletteColors1: "#ffffff",
palettecolors2: "",
},
},
];
inputs.forEach((input, index) => {
const result = validate(config[index], input, DUMMY_WIDGET);

View File

@ -32,6 +32,20 @@ const flat = (array: Record<string, any>[], uniqueParam: string) => {
});
return result;
};
function getPropertyEntry(
obj: Record<string, unknown>,
name: string,
ignoreCase = false,
) {
if (!ignoreCase) {
return name;
} else {
const keys = Object.getOwnPropertyNames(obj);
return keys.find((key) => key.toLowerCase() === name.toLowerCase()) || name;
}
}
function validatePlainObject(
config: ValidationConfig,
value: Record<string, unknown>,
@ -42,24 +56,25 @@ function validatePlainObject(
const _messages: string[] = [];
const parsedValue: Record<string, unknown> = value;
config.params.allowedKeys.forEach((entry) => {
if (value.hasOwnProperty(entry.name)) {
const ignoreCase = !!entry.params?.ignoreCase;
const entryName = getPropertyEntry(value, entry.name, ignoreCase);
if (value.hasOwnProperty(entryName)) {
const { isValid, message, parsed } = validate(
entry,
value[entry.name],
value[entryName],
props,
);
parsedValue[entry.name] = parsed;
parsedValue[entryName] = parsed;
if (!isValid) {
value[entry.name] = parsed;
value[entryName] = parsed;
_valid = isValid;
message &&
_messages.push(
`Value of key: ${entry.name} is invalid: ${message}`,
);
_messages.push(`Value of key: ${entryName} is invalid: ${message}`);
}
} else if (entry.params?.required) {
_valid = false;
_messages.push(`Missing required key: ${entry.name}`);
_messages.push(`Missing required key: ${entryName}`);
}
});
if (_valid) {
@ -303,15 +318,17 @@ export const VALIDATORS: Record<ValidationTypes, Validator> = {
}
const isValid = isString(parsed);
const stringValidationError = {
isValid: false,
parsed: config.params?.default || "",
message: `${WIDGET_TYPE_VALIDATION_ERROR} ${getExpectedType(config)}`,
};
if (!isValid) {
try {
parsed = toString(parsed);
if (!config.params?.strict) parsed = toString(parsed);
else return stringValidationError;
} catch (e) {
return {
isValid: false,
parsed: config.params?.default || "",
message: `${WIDGET_TYPE_VALIDATION_ERROR} ${getExpectedType(config)}`,
};
return stringValidationError;
}
}
// If the value is an empty string we skip