From ee9e1b4a3ea9e9ddfc224e217edba4722365bb9a Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Thu, 21 Oct 2021 21:00:36 +0000 Subject: [PATCH] fix: dont pass all props to top level component --- .../studio-ui-codegen-react.test.ts.snap | 342 +++++++++++++----- .../component-renderer.test.ts.snap | 18 +- .../lib/amplify-ui-renderers/badge.ts | 1 + .../lib/amplify-ui-renderers/button.ts | 1 + .../lib/amplify-ui-renderers/card.ts | 2 + .../lib/amplify-ui-renderers/collection.ts | 1 + .../amplify-ui-renderers/customComponent.ts | 1 + .../lib/amplify-ui-renderers/divider.ts | 1 + .../lib/amplify-ui-renderers/flex.ts | 1 + .../lib/amplify-ui-renderers/image.ts | 2 + .../lib/amplify-ui-renderers/text.ts | 2 + .../lib/amplify-ui-renderers/view.ts | 1 + .../lib/react-component-renderer.ts | 2 +- .../react-component-with-children-renderer.ts | 2 +- .../lib/react-studio-template-renderer.ts | 123 ++++--- .../integration/generated-components-spec.js | 55 +-- .../src/ComponentTests.tsx | 4 + .../basicComponentCollection.json | 3 - .../componentWithConcatenation.json | 58 ++- .../components/componentWithConditional.json | 69 +--- 20 files changed, 419 insertions(+), 270 deletions(-) diff --git a/packages/studio-ui-codegen-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap b/packages/studio-ui-codegen-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap index f14ece18a..491f2a09a 100644 --- a/packages/studio-ui-codegen-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap +++ b/packages/studio-ui-codegen-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap @@ -6,18 +6,22 @@ Object { import React from \\"react\\"; import { Button, + ButtonProps, EscapeHatchProps, Flex, + FlexProps, Heading, + HeadingProps, findChildOverrides, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type SiteHeaderProps = { +export type SiteHeaderProps = Partial & { overrides?: EscapeHatchProps | undefined | null; }; export default function SiteHeader(props: SiteHeaderProps): React.ReactElement { - const overrides = { ...props.overrides }; + const { overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; const { invokeAction } = useActions({ signOutAction: { type: \\"Amplify.Auth.SignOut\\", @@ -28,7 +32,7 @@ export default function SiteHeader(props: SiteHeaderProps): React.ReactElement { & { overrides?: EscapeHatchProps | undefined | null; }; export default function CustomButton( props: CustomButtonProps ): React.ReactElement { - const overrides = { ...props.overrides }; + const { overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( ); @@ -85,19 +91,21 @@ import React from \\"react\\"; import { EscapeHatchProps, Text, + TextProps, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type CustomTextProps = { +export type CustomTextProps = Partial & { overrides?: EscapeHatchProps | undefined | null; }; export default function CustomText(props: CustomTextProps): React.ReactElement { - const overrides = { ...props.overrides }; + const { overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( {\\"Text Value\\"} @@ -113,19 +121,21 @@ import React from \\"react\\"; import { EscapeHatchProps, View, + ViewProps, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type TestProps = { +export type TestProps = Partial & { overrides?: EscapeHatchProps | undefined | null; }; export default function Test(props: TestProps): React.ReactElement { - const overrides = { ...props.overrides }; + const { overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( ); @@ -139,13 +149,16 @@ import React from \\"react\\"; import { User, UserPreferences } from \\"../models\\"; import { Button, + ButtonProps, Collection, + CollectionProps, EscapeHatchProps, Flex, + FlexProps, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type CollectionOfCustomButtonsProps = { +export type CollectionOfCustomButtonsProps = Partial> & { width?: Number; backgroundColor?: String; buttonColor?: UserPreferences; @@ -156,8 +169,15 @@ export type CollectionOfCustomButtonsProps = { export default function CollectionOfCustomButtons( props: CollectionOfCustomButtonsProps ): React.ReactElement { - const { width, backgroundColor, buttonColor, items } = props; - const overrides = { ...props.overrides }; + const { + width, + backgroundColor, + buttonColor, + items, + overrides: overridesProp, + ...rest + } = props; + const overrides = { ...overridesProp }; const buttonUserFilter = { and: [ { field: \\"age\\", operand: \\"10\\", operator: \\"gt\\" }, @@ -189,7 +209,7 @@ export default function CollectionOfCustomButtons( gap=\\"1.5rem\\" backgroundColor={backgroundColor} items={buttonUser || []} - {...props} + {...rest} {...getOverrideProps(overrides, \\"Collection\\")} > {(item, index) => ( @@ -216,14 +236,17 @@ import React from \\"react\\"; import { User, UserPreferences } from \\"../models\\"; import { Button, + ButtonProps, Collection, + CollectionProps, EscapeHatchProps, Flex, + FlexProps, SortDirection, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type CollectionOfCustomButtonsProps = { +export type CollectionOfCustomButtonsProps = Partial> & { width?: Number; backgroundColor?: String; buttonColor?: UserPreferences; @@ -234,8 +257,15 @@ export type CollectionOfCustomButtonsProps = { export default function CollectionOfCustomButtons( props: CollectionOfCustomButtonsProps ): React.ReactElement { - const { width, backgroundColor, buttonColor, items } = props; - const overrides = { ...props.overrides }; + const { + width, + backgroundColor, + buttonColor, + items, + overrides: overridesProp, + ...rest + } = props; + const overrides = { ...overridesProp }; const buttonUserFilter = { and: [ { field: \\"age\\", operand: \\"10\\", operator: \\"gt\\" }, @@ -272,7 +302,7 @@ export default function CollectionOfCustomButtons( gap=\\"1.5rem\\" backgroundColor={backgroundColor} items={buttonUser || []} - {...props} + {...rest} {...getOverrideProps(overrides, \\"Collection\\")} > {(item, index) => ( @@ -300,14 +330,16 @@ exports[`amplify render tests collection should render collection with data bind import React from \\"react\\"; import { Collection, + CollectionProps, EscapeHatchProps, ListingCard, + ListingCardProps, findChildOverrides, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; import { UntitledModel } from \\"../models\\"; -export type ListingCardCollectionProps = { +export type ListingCardCollectionProps = Partial> & { items?: any[]; } & { overrides?: EscapeHatchProps | undefined | null; @@ -315,8 +347,8 @@ export type ListingCardCollectionProps = { export default function ListingCardCollection( props: ListingCardCollectionProps ): React.ReactElement { - const { items } = props; - const overrides = { ...props.overrides }; + const { items, overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; const bananas = items !== undefined ? items @@ -332,7 +364,7 @@ export default function ListingCardCollection( columns=\\"2\\" order=\\"left-to-right\\" items={bananas || []} - {...props} + {...rest} {...getOverrideProps(overrides, \\"Collection\\")} > {(item, index) => ( @@ -355,13 +387,15 @@ exports[`amplify render tests collection should render collection without data b import React from \\"react\\"; import { Collection, + CollectionProps, EscapeHatchProps, ListingCard, + ListingCardProps, findChildOverrides, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type ListingCardCollectionProps = { +export type ListingCardCollectionProps = Partial> & { items?: any[]; } & { overrides?: EscapeHatchProps | undefined | null; @@ -369,14 +403,14 @@ export type ListingCardCollectionProps = { export default function ListingCardCollection( props: ListingCardCollectionProps ): React.ReactElement { - const { items } = props; - const overrides = { ...props.overrides }; + const { items, overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( {(item, index) => ( @@ -395,20 +429,23 @@ exports[`amplify render tests complex component tests should generate a button w import React from \\"react\\"; import { Button, + ButtonProps, EscapeHatchProps, View, + ViewProps, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type ViewWithButtonProps = { +export type ViewWithButtonProps = Partial & { overrides?: EscapeHatchProps | undefined | null; }; export default function ViewWithButton( props: ViewWithButtonProps ): React.ReactElement { - const overrides = { ...props.overrides }; + const { overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( - + ); @@ -557,11 +609,13 @@ import { UntitledModel } from \\"../models\\"; import { EscapeHatchProps, Flex, + FlexProps, Text, + TextProps, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type SectionHeadingProps = { +export type SectionHeadingProps = Partial & { newProp6fd1?: UntitledModel; } & { overrides?: EscapeHatchProps | undefined | null; @@ -569,14 +623,14 @@ export type SectionHeadingProps = { export default function SectionHeading( props: SectionHeadingProps ): React.ReactElement { - const { newProp6fd1 } = props; - const overrides = { ...props.overrides }; + const { newProp6fd1, overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( & { textValue?: String; } & { overrides?: EscapeHatchProps | undefined | null; @@ -630,10 +686,10 @@ export type ChildComponentWithDataBindingProps = { export default function ChildComponentWithDataBinding( props: ChildComponentWithDataBindingProps ): React.ReactElement { - const { textValue } = props; - const overrides = { ...props.overrides }; + const { textValue, overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( - ); @@ -647,12 +703,13 @@ Object { import React from \\"react\\"; import { Button, + ButtonProps, EscapeHatchProps, getOverrideProps, getOverridesFromVariants, } from \\"@aws-amplify/ui-react\\"; -export type CustomButtonProps = { +export type CustomButtonProps = Partial & { variant: \\"primary\\" | \\"secondary\\"; size?: \\"large\\"; } & { @@ -661,7 +718,7 @@ export type CustomButtonProps = { export default function CustomButton( props: CustomButtonProps ): React.ReactElement { - const {} = props; + const { overrides: overridesProp, ...rest } = props; const variants = [ { variantValues: { variant: \\"primary\\" }, @@ -678,11 +735,9 @@ export default function CustomButton( ]; const overrides = { ...getOverridesFromVariants(variants, props), - ...props.overrides, + ...overridesProp, }; - return ( - - ); + return ; } ", "declaration": undefined, @@ -695,23 +750,26 @@ exports[`amplify render tests concat and conditional transform should render chi import React from \\"react\\"; import { Button, + ButtonProps, EscapeHatchProps, Text, + TextProps, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type ChildComponentWithDataBoundConcatenationProps = { - textValue?: String; -} & { - overrides?: EscapeHatchProps | undefined | null; -}; +export type ChildComponentWithDataBoundConcatenationProps = + Partial & { + textValue?: String; + } & { + overrides?: EscapeHatchProps | undefined | null; + }; export default function ChildComponentWithDataBoundConcatenation( props: ChildComponentWithDataBoundConcatenationProps ): React.ReactElement { - const { textValue } = props; - const overrides = { ...props.overrides }; + const { textValue, overrides: overridesProp, ...rest } = props; + const overrides = { ...overridesProp }; return ( - ); @@ -792,11 +860,12 @@ import React from \\"react\\"; import { User } from \\"../models\\"; import { Button, + ButtonProps, EscapeHatchProps, getOverrideProps, } from \\"@aws-amplify/ui-react\\"; -export type CustomButtonProps = { +export type CustomButtonProps = Partial & { width?: Number; buttonUser?: User; buttonColor?: String; @@ -806,8 +875,14 @@ export type CustomButtonProps = { export default function CustomButton( props: CustomButtonProps ): React.ReactElement { - const { width, buttonUser, buttonColor } = props; - const overrides = { ...props.overrides }; + const { + width, + buttonUser, + buttonColor, + overrides: overridesProp, + ...rest + } = props; + const overrides = { ...overridesProp }; return ( ); @@ -851,14 +926,33 @@ exports[`amplify render tests custom render config should render ES5 1`] = ` }; return __assign.apply(this, arguments); }; +var __rest = + (this && this.__rest) || + function (s, e) { + var t = {}; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === \\"function\\") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if ( + e.indexOf(p[i]) < 0 && + Object.prototype.propertyIsEnumerable.call(s, p[i]) + ) + t[p[i]] = s[p[i]]; + } + return t; + }; /* eslint-disable */ import React from \\"react\\"; import { Button, View, getOverrideProps } from \\"@aws-amplify/ui-react\\"; export default function ViewWithButton(props) { - var overrides = __assign({}, props.overrides); + var overridesProp = props.overrides, + rest = __rest(props, [\\"overrides\\"]); + var overrides = __assign({}, overridesProp); return React.createElement( View, - __assign({}, props, getOverrideProps(overrides, \\"View\\")), + __assign({}, rest, getOverrideProps(overrides, \\"View\\")), React.createElement( Button, __assign( @@ -872,13 +966,32 @@ export default function ViewWithButton(props) { `; exports[`amplify render tests custom render config should render JSX 1`] = ` -"/* eslint-disable */ +"var __rest = + (this && this.__rest) || + function (s, e) { + var t = {}; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === \\"function\\") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if ( + e.indexOf(p[i]) < 0 && + Object.prototype.propertyIsEnumerable.call(s, p[i]) + ) + t[p[i]] = s[p[i]]; + } + return t; + }; +/* eslint-disable */ import React from \\"react\\"; import { Button, View, getOverrideProps } from \\"@aws-amplify/ui-react\\"; export default function ViewWithButton(props) { - const overrides = Object.assign({}, props.overrides); + const { overrides: overridesProp } = props, + rest = __rest(props, [\\"overrides\\"]); + const overrides = Object.assign({}, overridesProp); return ( - + "`; +exports[`Component Renderers ButtonRenderer 1`] = `""`; -exports[`Component Renderers CardRenderer 1`] = `""`; +exports[`Component Renderers CardRenderer 1`] = `""`; -exports[`Component Renderers CollectionRenderer 1`] = `"{(item, index) => ()}"`; +exports[`Component Renderers CollectionRenderer 1`] = `"{(item, index) => ()}"`; exports[`Component Renderers CustomComponentRenderer 1`] = `""`; -exports[`Component Renderers DividerRenderer 1`] = `""`; +exports[`Component Renderers DividerRenderer 1`] = `""`; -exports[`Component Renderers FlexRenderer 1`] = `""`; +exports[`Component Renderers FlexRenderer 1`] = `""`; -exports[`Component Renderers ImageRenderer 1`] = `""`; +exports[`Component Renderers ImageRenderer 1`] = `""`; exports[`Component Renderers StringRenderer basic 1`] = `"<>{\\"test\\"}"`; exports[`Component Renderers StringRenderer missing props 1`] = `"Failed to render String - Unexpected component structure"`; -exports[`Component Renderers TextRenderer 1`] = `"{\\"test\\"}"`; +exports[`Component Renderers TextRenderer 1`] = `"{\\"test\\"}"`; diff --git a/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/badge.ts b/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/badge.ts index 0ff2fa66d..5357e8970 100644 --- a/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/badge.ts +++ b/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/badge.ts @@ -31,6 +31,7 @@ export default class BadgeRenderer extends ReactComponentWithChildrenRenderer { ); this.importCollection.addImport('@aws-amplify/ui-react', this.component.componentType); + this.importCollection.addImport('@aws-amplify/ui-react', `${this.component.componentType}Props`); + return element; } } diff --git a/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/text.ts b/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/text.ts index 86f9bb03b..19a9dbe89 100644 --- a/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/text.ts +++ b/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/text.ts @@ -30,6 +30,8 @@ export default class TextRenderer extends ReactComponentRenderer { ); this.importCollection.addImport('@aws-amplify/ui-react', this.component.componentType); + this.importCollection.addImport('@aws-amplify/ui-react', `${this.component.componentType}Props`); + return element; } } diff --git a/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/view.ts b/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/view.ts index 4daac4cda..a16dd0aa3 100644 --- a/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/view.ts +++ b/packages/studio-ui-codegen-react/lib/amplify-ui-renderers/view.ts @@ -30,6 +30,7 @@ export default class ViewRenderer extends ReactComponentWithChildrenRenderer extends ComponentRendererB private addPropsSpreadAttributes(attributes: JsxAttributeLike[]) { if (this.node.isRoot()) { - const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('props')); + const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('rest')); attributes.push(propsAttr); } diff --git a/packages/studio-ui-codegen-react/lib/react-component-with-children-renderer.ts b/packages/studio-ui-codegen-react/lib/react-component-with-children-renderer.ts index ad3e0f5e2..2ef027457 100644 --- a/packages/studio-ui-codegen-react/lib/react-component-with-children-renderer.ts +++ b/packages/studio-ui-codegen-react/lib/react-component-with-children-renderer.ts @@ -106,7 +106,7 @@ export abstract class ReactComponentWithChildrenRenderer extends Compon private addPropsSpreadAttributes(attributes: JsxAttributeLike[]) { if (this.node.isRoot()) { - const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('props')); + const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('rest')); attributes.push(propsAttr); } diff --git a/packages/studio-ui-codegen-react/lib/react-studio-template-renderer.ts b/packages/studio-ui-codegen-react/lib/react-studio-template-renderer.ts index 7ac70c28a..58028b6ca 100644 --- a/packages/studio-ui-codegen-react/lib/react-studio-template-renderer.ts +++ b/packages/studio-ui-codegen-react/lib/react-studio-template-renderer.ts @@ -259,7 +259,7 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer } renderBindingPropsType(component: StudioComponent): TypeAliasDeclaration { - const escapeHatchType = factory.createTypeLiteralNode([ + const escapeHatchTypeNode = factory.createTypeLiteralNode([ factory.createPropertySignature( undefined, factory.createIdentifier('overrides'), @@ -280,14 +280,43 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer undefined, factory.createIntersectionTypeNode( this.dropMissingListElements([ - this.buildComponentPropNodes(component), - this.buildVariantPropNodes(component), - escapeHatchType, + this.buildPrimitivePropNode(component), + this.buildComponentPropNode(component), + this.buildVariantPropNode(component), + escapeHatchTypeNode, ]), ), ); } + private hasPrimitivePropType(component: StudioComponent): boolean { + return component.componentType !== 'String'; + } + + private getParameterizedPrimitivePropType(component: StudioComponent): TypeNode | undefined { + switch (component.componentType) { + case 'Collection': + return factory.createTypeReferenceNode(factory.createIdentifier('CollectionProps'), [ + factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + ]); + default: + return undefined; + } + } + + private buildPrimitivePropNode(component: StudioComponent): TypeNode | undefined { + if (!this.hasPrimitivePropType(component)) { + return undefined; + } + + const parameterizedPrimitivePropType = this.getParameterizedPrimitivePropType(component); + const primitivePropType = + parameterizedPrimitivePropType || + factory.createTypeReferenceNode(factory.createIdentifier(`${component.componentType}Props`), undefined); + + return factory.createTypeReferenceNode(factory.createIdentifier('Partial'), [primitivePropType]); + } + /** * This builder is responsible primarily for identifying the variant options, partioning them into * required and optional parameters, then building the appropriate property signature based on that. @@ -297,7 +326,7 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer size?: "large", } */ - private buildVariantPropNodes(component: StudioComponent): TypeNode | undefined { + private buildVariantPropNode(component: StudioComponent): TypeNode | undefined { if (!isStudioComponentWithVariants(component)) { return undefined; } @@ -349,7 +378,7 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer return factory.createTypeLiteralNode([...requiredProperties, ...optionalProperties]); } - private buildComponentPropNodes(component: StudioComponent): TypeNode | undefined { + private buildComponentPropNode(component: StudioComponent): TypeNode | undefined { const propSignatures: PropertySignature[] = []; const bindingProps = component.bindingProperties; if (bindingProps === undefined || !isStudioComponentWithBinding(component)) { @@ -392,9 +421,8 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer private buildVariableStatements(component: StudioComponent): Statement[] { const statements: Statement[] = []; - + const elements: BindingElement[] = []; if (isStudioComponentWithBinding(component)) { - const elements: BindingElement[] = []; Object.entries(component.bindingProperties).forEach((entry) => { const [propName, binding] = entry; if (isSimplePropertyBinding(binding) || isDataPropertyBinding(binding)) { @@ -407,34 +435,54 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer elements.push(bindingElement); } }); + } - if (component.componentType === 'Collection') { - const bindingElement = factory.createBindingElement( - undefined, - undefined, - factory.createIdentifier('items'), - undefined, - ); - elements.push(bindingElement); - } - - const statement = factory.createVariableStatement( + if (component.componentType === 'Collection') { + const bindingElement = factory.createBindingElement( + undefined, + undefined, + factory.createIdentifier('items'), undefined, - factory.createVariableDeclarationList( - [ - factory.createVariableDeclaration( - factory.createObjectBindingPattern(elements), - undefined, - undefined, - factory.createIdentifier('props'), - ), - ], - ts.NodeFlags.Const, - ), ); - statements.push(statement); + elements.push(bindingElement); } + // remove overrides from rest of props + elements.push( + factory.createBindingElement( + undefined, + factory.createIdentifier('overrides'), + factory.createIdentifier('overridesProp'), + undefined, + ), + ); + + // get rest of props to pass to top level component + elements.push( + factory.createBindingElement( + factory.createToken(ts.SyntaxKind.DotDotDotToken), + undefined, + factory.createIdentifier('rest'), + undefined, + ), + ); + + const statement = factory.createVariableStatement( + undefined, + factory.createVariableDeclarationList( + [ + factory.createVariableDeclaration( + factory.createObjectBindingPattern(elements), + undefined, + undefined, + factory.createIdentifier('props'), + ), + ], + ts.NodeFlags.Const, + ), + ); + statements.push(statement); + if (isStudioComponentWithVariants(component)) { statements.push(this.buildVariantDeclaration(component.variants)); // TODO: In components, replace props.override with override (defined here). @@ -542,8 +590,8 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer } /** - * case: hasVariants = true => const overrides = { ...getOverridesFromVariants(variants), ...props.overrides }; - * case: hasVariants = false => const overrides = { ...props.overrides }; + * case: hasVariants = true => const overrides = { ...getOverridesFromVariants(variants, props) }; + * case: hasVariants = false => const overrides = { ...overridesProp }; */ private buildOverridesDeclaration(hasVariants: boolean): VariableStatement { if (hasVariants) { @@ -573,14 +621,7 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer ] : [], ) - .concat([ - factory.createSpreadAssignment( - factory.createPropertyAccessExpression( - factory.createIdentifier('props'), - factory.createIdentifier('overrides'), - ), - ), - ]), + .concat([factory.createSpreadAssignment(factory.createIdentifier('overridesProp'))]), ), ), ], diff --git a/packages/test-generator/integration-test-templates/cypress/integration/generated-components-spec.js b/packages/test-generator/integration-test-templates/cypress/integration/generated-components-spec.js index 358bf4656..44734dd37 100644 --- a/packages/test-generator/integration-test-templates/cypress/integration/generated-components-spec.js +++ b/packages/test-generator/integration-test-templates/cypress/integration/generated-components-spec.js @@ -57,33 +57,34 @@ describe('Generated Components', () => { }); }); - describe('Conditional Data', () => { - it('Renders Button disabled when user is not logged in', () => { - cy.visit('http://localhost:3000/component-tests'); - cy.get('[label="Disabled Conditional Button"]').get('[disabled]'); - }); - - it('Renders May vote when user old enough', () => { - cy.visit('http://localhost:3000/component-tests'); - cy.get('[label="May Vote Conditional Button"]').get('[prompt="May Vote, cast your vote."]'); - }); - - it('Renders May not vote when user too young', () => { - cy.visit('http://localhost:3000/component-tests'); - cy.get('[label="May Not Vote Conditional Button"]').get('[prompt="Sorry you cannot vote"]'); - }); - }); - - // TODO: We should be rendering the element as a text child, but concat doesn't seem to support that yet. - describe('Concatenated Data', () => { - it('Renders Button text as a concatenated, bound element', () => { - cy.visit('http://localhost:3000/component-tests'); - cy.get('[label="Harry Callahan"]'); - }); - - it('Renders Button text as a concatenated, bound element, with overrides', () => { - cy.visit('http://localhost:3000/component-tests'); - cy.get('[label="Norm Gunderson"]'); + describe('Generated Components', () => { + describe('Concatenated Data', () => { + it('Renders Button text as a concatenated, bound element', () => { + cy.visit('http://localhost:3000/component-tests'); + cy.get('#concat-and-conditional').contains('Harry Callahan'); + }); + + it('Renders Button text as a concatenated, bound element, with overrides', () => { + cy.visit('http://localhost:3000/component-tests'); + cy.get('#concat-and-conditional').contains('Norm Gunderson'); + }); + }); + + describe('Conditional Data', () => { + it('Renders Button with one background when user is logged in', () => { + cy.visit('http://localhost:3000/component-tests'); + cy.get('#concat-and-conditional').get('#conditional1').should('have.css', 'background-color', 'rgb(255, 0, 0)'); + }); + + it('Renders Button with a different background when user is not logged in', () => { + cy.visit('http://localhost:3000/component-tests'); + cy.get('#concat-and-conditional').get('#conditional2').should('have.css', 'background-color', 'rgb(0, 0, 255)'); + }); + + it('Renders Button disabled when user is not logged in', () => { + cy.visit('http://localhost:3000/component-tests'); + cy.get('#concat-and-conditional').get('#conditional2').get('[disabled]'); + }); }); }); diff --git a/packages/test-generator/integration-test-templates/src/ComponentTests.tsx b/packages/test-generator/integration-test-templates/src/ComponentTests.tsx index 696b36829..b4930438f 100644 --- a/packages/test-generator/integration-test-templates/src/ComponentTests.tsx +++ b/packages/test-generator/integration-test-templates/src/ComponentTests.tsx @@ -30,6 +30,7 @@ import BasicComponentDivider from './ui-components/BasicComponentDivider'; import BasicComponentFlex from './ui-components/BasicComponentFlex'; import BasicComponentImage from './ui-components/BasicComponentImage'; import BasicComponentCustomRating from './ui-components/BasicComponentCustomRating'; +import ComponentWithVariant from './ui-components/ComponentWithVariant'; /* eslint-enable import/extensions */ function ComponentTests() { @@ -67,6 +68,7 @@ function ComponentTests() { }} />