diff --git a/packages/codegen-ui/lib/__tests__/utils/component-metadata.test.ts b/packages/codegen-ui/lib/__tests__/utils/component-metadata.test.ts index 604561d8a..e6d500951 100644 --- a/packages/codegen-ui/lib/__tests__/utils/component-metadata.test.ts +++ b/packages/codegen-ui/lib/__tests__/utils/component-metadata.test.ts @@ -745,5 +745,123 @@ describe('computeComponentMetadata', () => { }; expect(computeComponentMetadata(component)).toEqual(expectedMetadata); }); + + it('supports undefined values coming in from the sdk', () => { + const component: StudioComponent = { + componentType: 'Flex', + name: 'TopLevelComponent', + properties: {}, + bindingProperties: { + color: { + type: 'String', + }, + }, + collectionProperties: { + user: { + model: 'User', + }, + }, + children: [ + { + componentType: 'Flex', + name: 'NestedComponent', + properties: {}, + children: [ + { + componentType: 'Button', + name: 'NestedButton', + properties: {}, + events: { + click: { + action: 'Amplify.Mutation', + parameters: { + state: { + componentName: 'NestedComponent', + property: 'color', + set: { + bindingProperties: { + property: 'color', + }, + }, + }, + }, + }, + }, + }, + ], + }, + { + componentType: 'TextField', + name: 'NicknameField', + properties: { + label: { + value: 'Enter your nickname', + concat: undefined, + condition: undefined, + }, + }, + }, + { + componentType: 'Button', + name: 'MyButton', + properties: { + label: { + concat: [ + { + value: 'Click Me - ', + }, + { + userAttribute: 'firstName', + }, + ], + }, + }, + events: { + click: { + action: 'Amplify.DataStoreCreateItemAction', + parameters: { + model: 'Listing', + fields: { + name: { + userAttribute: 'firstName', + }, + preferredName: { + condition: { + property: 'color', + operator: 'eq', + operand: 'blue', + then: { + value: 'Nice Color', + }, + else: { + componentName: 'NicknameField', + property: 'value', + }, + }, + }, + }, + }, + }, + }, + }, + ], + }; + const expectedMetadata: ComponentMetadata = { + hasAuthBindings: true, + requiredDataModels: ['User', 'Listing'], + stateReferences: [ + { componentName: 'NicknameField', property: 'value' }, + { componentName: 'NestedComponent', property: 'color', set: { bindingProperties: { property: 'color' } } }, + ], + componentNameToTypeMap: { + TopLevelComponent: 'Flex', + NestedComponent: 'Flex', + MyButton: 'Button', + NestedButton: 'Button', + NicknameField: 'TextField', + }, + }; + expect(computeComponentMetadata(component)).toEqual(expectedMetadata); + }); }); }); diff --git a/packages/codegen-ui/lib/utils/component-metadata.ts b/packages/codegen-ui/lib/utils/component-metadata.ts index 04ebd82b4..51cd9973d 100644 --- a/packages/codegen-ui/lib/utils/component-metadata.ts +++ b/packages/codegen-ui/lib/utils/component-metadata.ts @@ -66,7 +66,9 @@ function computeComponentMetadataHelper(component: StudioComponent | StudioCompo function dedupeStateReferences(stateReferences: StateReference[]): StateReference[] { const stateReferenceMap: Record> = {}; stateReferences - .filter((stateReference) => !('set' in stateReference)) + .filter( + (stateReference) => !('set' in stateReference) || stateReference.set === null || stateReference.set === undefined, + ) .forEach(({ componentName, property }) => { if (!(componentName in stateReferenceMap)) { stateReferenceMap[componentName] = new Set([]); @@ -79,7 +81,7 @@ function dedupeStateReferences(stateReferences: StateReference[]): StateReferenc return { componentName, property }; }), ) - .concat(stateReferences.filter((stateReference) => 'set' in stateReference)); + .concat(stateReferences.filter((stateReference) => 'set' in stateReference && stateReference.set)); } function dedupeComponentMetadata(componentMetadata: ComponentMetadata): ComponentMetadata { @@ -183,20 +185,20 @@ function computeBindingPropertyMetadata(bindingProperty: StudioComponentProperty function computePropertyMetadata(property: StudioComponentProperty): ComponentMetadata { return reduceComponentMetadata( ([] as ComponentMetadata[]) - .concat('concat' in property ? property.concat.map(computePropertyMetadata) : []) - .concat('userAttribute' in property ? [generateAuthBindingMetadata()] : []) + .concat('concat' in property && property.concat ? property.concat.map(computePropertyMetadata) : []) + .concat('userAttribute' in property && property.userAttribute ? [generateAuthBindingMetadata()] : []) .concat( - 'condition' in property && 'then' in property.condition + 'condition' in property && property.condition && 'then' in property.condition && property.condition.then ? [computePropertyMetadata(property.condition.then)] : [], ) .concat( - 'condition' in property && 'else' in property.condition + 'condition' in property && property.condition && 'else' in property.condition && property.condition.else ? [computePropertyMetadata(property.condition.else)] : [], ) .concat( - 'componentName' in property && 'property' in property + 'componentName' in property && property.componentName && 'property' in property && property.property ? [generateReferenceMetadata(property as StateReference)] : [], ), @@ -208,7 +210,7 @@ function computePropertyMetadata(property: StudioComponentProperty): ComponentMe */ function computeEventMetadata(event: StudioComponentEvent): ComponentMetadata { - if (!('action' in event)) { + if (!('action' in event) || event.action === undefined || event.action === null) { return generateEmptyMetadata(); }