diff --git a/packages/codegen-ui/lib/__tests__/__snapshots__/validation-helper.test.ts.snap b/packages/codegen-ui/lib/__tests__/__snapshots__/validation-helper.test.ts.snap index 514b6073b..1a8ed1504 100644 --- a/packages/codegen-ui/lib/__tests__/__snapshots__/validation-helper.test.ts.snap +++ b/packages/codegen-ui/lib/__tests__/__snapshots__/validation-helper.test.ts.snap @@ -12,8 +12,12 @@ exports[`validation-helper validateComponentSchema top-level component requires exports[`validation-helper validateComponentSchema top-level component requires componentType to be the correct type 1`] = `"componentType must be a \`string\` type, but the final value was: \`2\`."`; +exports[`validation-helper validateComponentSchema top-level component requires non-empty property values 1`] = `"property cannot be empty."`; + exports[`validation-helper validateComponentSchema top-level component requires properties 1`] = `"properties is a required field"`; +exports[`validation-helper validateComponentSchema top-level component requires properties to be the correct type 1`] = `"properties must be a \`object\` type, but the final value was: \`\\"property\\"\`."`; + exports[`validation-helper validateThemeSchema children objects should not be empty 1`] = `"values[1].key is a required field, values[1].value is a required field"`; exports[`validation-helper validateThemeSchema overrides should contain the right shape 1`] = `"overrides[0].key is a required field"`; diff --git a/packages/codegen-ui/lib/__tests__/validation-helper.test.ts b/packages/codegen-ui/lib/__tests__/validation-helper.test.ts index e438ed2e5..3ddde46f4 100644 --- a/packages/codegen-ui/lib/__tests__/validation-helper.test.ts +++ b/packages/codegen-ui/lib/__tests__/validation-helper.test.ts @@ -52,6 +52,28 @@ describe('validation-helper', () => { }).toThrowErrorMatchingSnapshot(); }); + test('top-level component requires non-empty property values', () => { + expect(() => { + validateComponentSchema({ + componentType: 'View', + name: 'MyBindingView', + properties: { + pathData: {}, + }, + }); + }).toThrowErrorMatchingSnapshot(); + }); + + test('top-level component requires properties to be the correct type', () => { + expect(() => { + validateComponentSchema({ + componentType: 'View', + name: 'MyBindingView', + properties: 'property', + }); + }).toThrowErrorMatchingSnapshot(); + }); + test('top-level component requires componentType to be the correct type', () => { expect(() => { validateComponentSchema({ diff --git a/packages/codegen-ui/lib/validation-helper.ts b/packages/codegen-ui/lib/validation-helper.ts index be9159e8c..3a83ef963 100644 --- a/packages/codegen-ui/lib/validation-helper.ts +++ b/packages/codegen-ui/lib/validation-helper.ts @@ -26,6 +26,20 @@ const alphaNumNoLeadingNumberString = () => { .matches(/^[a-zA-Z][a-zA-Z0-9]*$/, { message: 'Expected an alphanumeric string, starting with a character' }); }; +const propertiesSchema = (value: Object) => { + return yup.object().shape( + Object.fromEntries( + Object.keys(value || {}).map((key) => [ + key, + yup + .object() + .test('property', 'property cannot be empty.', (property: Object) => Object.keys(property).length > 0) + .required(), + ]), + ), + ); +}; + /** * Component Schema Definitions */ @@ -33,7 +47,7 @@ const studioComponentChildSchema: any = yup.object({ componentType: alphaNumNoLeadingNumberString().required(), // TODO: Name is required in the studio-types file, but doesn't seem to need to be. Relaxing the restriction here. name: yup.string().nullable(), - properties: yup.object().required(), + properties: yup.lazy((value) => propertiesSchema(value).required()), // Doing lazy eval here since we reference our own type otherwise children: yup.lazy(() => yup.array(studioComponentChildSchema.default(undefined))), figmaMetadata: yup.object().nullable(), @@ -49,7 +63,7 @@ const studioComponentSchema = yup.object({ id: yup.string().nullable(), sourceId: yup.string().nullable(), componentType: alphaNumNoLeadingNumberString().required(), - properties: yup.object().required(), + properties: yup.lazy((value) => propertiesSchema(value).required()), children: yup.array(studioComponentChildSchema).nullable(), figmaMetadata: yup.object().nullable(), variants: yup.array().nullable(),