Skip to content

Commit

Permalink
fix: alias model names collision with component types (#733)
Browse files Browse the repository at this point in the history
* chore: set timezone to UTC before starting cypress tests (#730)

* chore: set timezone to UTC before starting cypress tests

* fix: cli test fix

Co-authored-by: Brandon Lyons <lyonsbp@amazon.com>
Co-authored-by: Scott Young <scoyou@amazon.com>

* fix: alias model names collision with component types

Co-authored-by: Brandon Lyons <lyonsbp@amazon.com>
Co-authored-by: Scott Young <scoyou@amazon.com>
Co-authored-by: Justin Shih <jushih@amazon.com>
  • Loading branch information
4 people authored Nov 2, 2022
1 parent c0ee240 commit b7372dc
Show file tree
Hide file tree
Showing 10 changed files with 395 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -345,14 +345,14 @@ exports[`amplify render tests actions with conditional in parameters 1`] = `
Object {
"componentText": "/* eslint-disable */
import * as React from \\"react\\";
import { User } from \\"../models\\";
import {
EscapeHatchProps,
createDataStorePredicate,
getOverrideProps,
useDataStoreBinding,
useStateMutationAction,
} from \\"@aws-amplify/ui-react/internal\\";
import { User } from \\"../models\\";
import { Button, Flex, FlexProps, Text } from \\"@aws-amplify/ui-react\\";

export type ConditionalInMutationProps = React.PropsWithChildren<
Expand Down Expand Up @@ -578,6 +578,39 @@ export default function DataBindingNamedClass(
"
`;

exports[`amplify render tests bindings data supports model with conflicting component type 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import { Flex as Flex0 } from \\"../models\\";
import {
EscapeHatchProps,
getOverrideProps,
} from \\"@aws-amplify/ui-react/internal\\";
import { Text, TextProps } from \\"@aws-amplify/ui-react\\";

export type DataBindingNamedClassProps = React.PropsWithChildren<
Partial<TextProps> & {
class?: Flex0;
} & {
overrides?: EscapeHatchProps | undefined | null;
}
>;
export default function DataBindingNamedClass(
props: DataBindingNamedClassProps
): React.ReactElement {
const { class: classProp, overrides, ...rest } = props;
return (
/* @ts-ignore: TS2322 */
<Text
children={classProp?.name}
{...rest}
{...getOverrideProps(overrides, \\"DataBindingNamedClass\\")}
></Text>
);
}
"
`;

exports[`amplify render tests collection should not render nested query if the data schema is not provided 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
Expand Down Expand Up @@ -639,13 +672,13 @@ export default function AuthorProfileCollection(
exports[`amplify render tests collection should render collection with data binding 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import { UserPreferences, User } from \\"../models\\";
import {
EscapeHatchProps,
createDataStorePredicate,
getOverrideProps,
useDataStoreBinding,
} from \\"@aws-amplify/ui-react/internal\\";
import { User, UserPreferences } from \\"../models\\";
import {
Button,
Collection,
Expand Down Expand Up @@ -742,14 +775,14 @@ exports[`amplify render tests collection should render collection with data bind
Object {
"componentText": "/* eslint-disable */
import * as React from \\"react\\";
import { UserPreferences, User } from \\"../models\\";
import {
EscapeHatchProps,
createDataStorePredicate,
getOverrideProps,
useDataStoreBinding,
} from \\"@aws-amplify/ui-react/internal\\";
import { SortDirection, SortPredicate } from \\"@aws-amplify/datastore\\";
import { User, UserPreferences } from \\"../models\\";
import {
Button,
Collection,
Expand Down Expand Up @@ -853,13 +886,13 @@ export default function CollectionOfCustomButtons(
exports[`amplify render tests collection should render collection with data binding if binding name is items 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import { UserPreferences, User } from \\"../models\\";
import {
EscapeHatchProps,
createDataStorePredicate,
getOverrideProps,
useDataStoreBinding,
} from \\"@aws-amplify/ui-react/internal\\";
import { User, UserPreferences } from \\"../models\\";
import {
Button,
Collection,
Expand Down Expand Up @@ -1058,6 +1091,123 @@ export default function ListingCardCollection(
"
`;

exports[`amplify render tests collection should render if model name collides with component types 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import { Flex as Flex0, FlexModel, Button as Button0 } from \\"../models\\";
import {
EscapeHatchProps,
createDataStorePredicate,
getOverrideProps,
useDataStoreBinding,
} from \\"@aws-amplify/ui-react/internal\\";
import { SortDirection, SortPredicate } from \\"@aws-amplify/datastore\\";
import {
Button,
Collection,
CollectionProps,
Flex,
} from \\"@aws-amplify/ui-react\\";
import { MyFlexProps } from \\"./MyFlex\\";

export type CollectionWithModelNameCollisionsProps = React.PropsWithChildren<
Partial<CollectionProps<any>> & {
backgroundColor?: String;
buttonColor?: Flex0;
buttonShape?: FlexModel;
items?: any[];
overrideItems?: (collectionItem: {
item: any;
index: number;
}) => MyFlexProps;
} & {
overrides?: EscapeHatchProps | undefined | null;
}
>;
export default function CollectionWithModelNameCollisions(
props: CollectionWithModelNameCollisionsProps
): React.ReactElement {
const {
backgroundColor,
buttonColor: buttonColorProp,
buttonShape: buttonShapeProp,
items,
overrideItems,
overrides,
...rest
} = props;
const buttonModelFilterObj = {
and: [
{ field: \\"age\\", operand: \\"10\\", operator: \\"gt\\" },
{ field: \\"lastName\\", operand: \\"L\\", operator: \\"beginsWith\\" },
],
};
const buttonModelFilter =
createDataStorePredicate<Button0>(buttonModelFilterObj);
const buttonModelPagination = {
sort: (s: SortPredicate<Button0>) => s.lastName(SortDirection.ASCENDING),
};
const buttonModelDataStore = useDataStoreBinding({
type: \\"collection\\",
model: Button0,
criteria: buttonModelFilter,
pagination: buttonModelPagination,
}).items;
const buttonModel = items !== undefined ? items : buttonModelDataStore;
const buttonColorFilterObj = {
field: \\"userID\\",
operand: \\"user@email.com\\",
operator: \\"eq\\",
};
const buttonColorFilter =
createDataStorePredicate<Flex0>(buttonColorFilterObj);
const buttonColorDataStore = useDataStoreBinding({
type: \\"collection\\",
model: Flex0,
criteria: buttonColorFilter,
}).items[0];
const buttonColor =
buttonColorProp !== undefined ? buttonColorProp : buttonColorDataStore;
const buttonShapeFilterObj = {
field: \\"userID\\",
operand: \\"user@email.com\\",
operator: \\"eq\\",
};
const buttonShapeFilter =
createDataStorePredicate<FlexModel>(buttonShapeFilterObj);
const buttonShapeDataStore = useDataStoreBinding({
type: \\"collection\\",
model: FlexModel,
criteria: buttonShapeFilter,
}).items[0];
const buttonShape =
buttonShapeProp !== undefined ? buttonShapeProp : buttonShapeDataStore;
return (
/* @ts-ignore: TS2322 */
<Collection
type=\\"list\\"
items={buttonModel || []}
{...rest}
{...getOverrideProps(overrides, \\"CollectionWithModelNameCollisions\\")}
>
{(item, index) => (
<Flex
key={item.id}
{...(overrideItems && overrideItems({ item, index }))}
>
<Button
backgroundColor={buttonColor?.favoriteColor}
children={item.lastName}
{...(overrideItems && overrideItems({ item, index }))}
></Button>
</Flex>
)}
</Collection>
);
}
"
`;

exports[`amplify render tests collection should render nested query if model has a hasMany relationship 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
Expand Down Expand Up @@ -5981,6 +6131,7 @@ exports[`amplify render tests mutations supports all initial value binding types
Object {
"componentText": "/* eslint-disable */
import * as React from \\"react\\";
import { User } from \\"../models\\";
import {
EscapeHatchProps,
createDataStorePredicate,
Expand All @@ -5989,7 +6140,6 @@ import {
useDataStoreBinding,
useStateMutationAction,
} from \\"@aws-amplify/ui-react/internal\\";
import { User } from \\"../models\\";
import { useEffect } from \\"react\\";
import {
Button,
Expand Down Expand Up @@ -6283,12 +6433,12 @@ exports[`amplify render tests mutations supports invalid statement names for mut
Object {
"componentText": "/* eslint-disable */
import * as React from \\"react\\";
import { Listing } from \\"../models\\";
import {
EscapeHatchProps,
getOverrideProps,
useStateMutationAction,
} from \\"@aws-amplify/ui-react/internal\\";
import { Listing } from \\"../models\\";
import { Flex, FlexProps, Image, Text } from \\"@aws-amplify/ui-react\\";

export type CardAProps = React.PropsWithChildren<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
import { ImportCollection } from '../../imports';
import { ImportCollection, ImportSource } from '../../imports';
import { assertASTMatchesSnapshot } from '../__utils__';

function assertImportCollectionMatchesSnapshot(importCollection: ImportCollection) {
Expand Down Expand Up @@ -69,6 +69,22 @@ describe('ImportCollection', () => {
importCollection.addImport('@aws-amplify/ui-react', 'getOverrideProps');
assertImportCollectionMatchesSnapshot(importCollection);
});
test('model imports colliding with exisiting imports', () => {
const importCollection = new ImportCollection({
componentNameToTypeMap: { TextInput: 'TextField' },
hasAuthBindings: false,
requiredDataModels: [],
stateReferences: [],
});
importCollection.addImport(ImportSource.LOCAL_MODELS, 'TextField0');
importCollection.addImport(ImportSource.LOCAL_MODELS, 'TextField');
importCollection.addImport(ImportSource.LOCAL_MODELS, 'TestModel');
importCollection.addImport(ImportSource.LOCAL_MODELS, 'ButtonProps');
expect(importCollection.getMappedAlias(ImportSource.LOCAL_MODELS, 'TextField')).toEqual('TextField1');
expect(importCollection.getMappedAlias(ImportSource.LOCAL_MODELS, 'TextField0')).toEqual('TextField0');
expect(importCollection.getMappedAlias(ImportSource.LOCAL_MODELS, 'TestModel')).toEqual('TestModel');
expect(importCollection.getMappedAlias(ImportSource.LOCAL_MODELS, 'ButtonProps')).toEqual('ButtonProps0');
});
});

test('mergeCollections', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ describe('amplify render tests', () => {
const { componentText } = generateWithAmplifyRenderer('authorCollectionComponent');
expect(componentText).toMatchSnapshot();
});
it('should render if model name collides with component types', () => {
const { componentText } = generateWithAmplifyRenderer('collectionWithModelNameCollisions');
expect(componentText).toMatchSnapshot();
});
});

describe('complex examples', () => {
Expand Down Expand Up @@ -594,6 +598,9 @@ describe('amplify render tests', () => {
it('supports bindings with reserved keywords', () => {
expect(generateWithAmplifyRenderer('bindings/data/dataBindingNamedClass').componentText).toMatchSnapshot();
});
it('supports model with conflicting component type', () => {
expect(generateWithAmplifyRenderer('bindings/data/dataBindingNamedFlex').componentText).toMatchSnapshot();
});
});
});
});
12 changes: 12 additions & 0 deletions packages/codegen-ui-react/lib/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,15 @@
limitations under the License.
*/
export const lowerCaseFirst = (input: string) => input.charAt(0).toLowerCase() + input.slice(1);

export const createUniqueName = (name: string, isNameUsed: (input: string) => boolean) => {
if (!isNameUsed(name)) {
return name;
}
let count = 0;
const prospectiveNewName = name;
while (isNameUsed(prospectiveNewName + count)) {
count += 1;
}
return prospectiveNewName + count;
};
Loading

0 comments on commit b7372dc

Please sign in to comment.