Skip to content

Commit

Permalink
chore(amplify-util-uibuilder): remove codegen-ui usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Shih committed Sep 19, 2023
1 parent 8b5d433 commit ad4bf57
Show file tree
Hide file tree
Showing 13 changed files with 4,820 additions and 127 deletions.
4 changes: 2 additions & 2 deletions packages/amplify-util-uibuilder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
"@aws-amplify/amplify-category-api": "^5.6.2",
"@aws-amplify/amplify-cli-core": "4.2.5",
"@aws-amplify/amplify-prompts": "2.8.2",
"@aws-amplify/codegen-ui": "2.14.2",
"@aws-amplify/codegen-ui-react": "2.14.2",
"@aws-amplify/datastore": "^4.7.5",
"amplify-codegen": "^4.4.0",
"aws-sdk": "^2.1426.0",
"fs-extra": "^8.1.0",
Expand All @@ -32,6 +31,7 @@
"@types/jest": "^29.5.1",
"@types/semver": "^7.1.0",
"@types/tiny-async-pool": "^2.0.0",
"semver": "^7.5.4",
"ts-jest": "^29.1.0"
},
"jest": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import semver from 'semver';
import { ReactRequiredDependencyProvider } from '../commands/utils/codegen-ui-dependency-provider';

describe('ReactStudioDependencyProvider', () => {
const requiredDependencies = new ReactRequiredDependencyProvider().getRequiredDependencies(false);
const requiredDependenciesWithStorageManager = new ReactRequiredDependencyProvider().getRequiredDependencies(true);

describe('getRequiredDependencies', () => {
it('has required dependencies', () => {
expect(requiredDependencies.length).toBeGreaterThan(0);
});

it('includes ui-react', () => {
expect(requiredDependencies.filter((dep) => dep.dependencyName === '@aws-amplify/ui-react')).toBeTruthy();
});

it('includes all valid semver values', () => {
requiredDependencies.forEach((dep) => {
expect(semver.valid(dep.supportedSemVerPattern)).toBeDefined();
});
});

it('includes reasons on all dependencies', () => {
requiredDependencies.forEach((dep) => {
expect(dep.reason.length).toBeGreaterThan(0);
});
});

it('does not include ui-react-storage if user does not use StorageManager', () => {
expect(requiredDependencies.filter((dep) => dep.dependencyName !== '@aws-amplify/ui-react-storage')).toBeTruthy();
});

it('includes ui-react-storage if user is using StorageManager', () => {
expect(requiredDependenciesWithStorageManager.filter((dep) => dep.dependencyName === '@aws-amplify/ui-react-storage')).toBeTruthy();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
import { getGenericFromDataStore } from '../commands/utils/codegen-ui';
import { HasManyRelationshipType } from '../commands/utils/data-types';
import {
schemaWithEnums,
schemaWithNonModels,
schemaWithRelationships,
schemaWithRelationshipsV2,
schemaWithAssumptions,
schemaWithCPK,
schemaWithCompositeKeys,
schemaWithHasManyBelongsTo,
schemaWithoutJoinTables,
introspectionSchemaWithCompositeKeys,
schemaWithBiDirectionalHasManyWithDefinedField,
} from './mock-schemas';

describe('getGenericFromDataStore', () => {
it('should map fields', () => {
const genericSchema = getGenericFromDataStore(schemaWithRelationships);
expect(genericSchema.models.Child.fields).toStrictEqual({
id: {
dataType: 'ID',
required: true,
readOnly: false,
isArray: false,
},
name: {
dataType: 'String',
required: false,
readOnly: false,
isArray: false,
},
createdAt: {
dataType: 'AWSDateTime',
required: false,
readOnly: true,
isArray: false,
},
updatedAt: {
dataType: 'AWSDateTime',
required: false,
readOnly: true,
isArray: false,
},
});
});

it('should map relationships', () => {
const genericSchema = getGenericFromDataStore(schemaWithRelationships);

expect(genericSchema.models.PrimaryCareGiver.fields.Child.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Child',
associatedFields: ['primaryCareGiverChildId'],
});

expect(genericSchema.models.PrimaryCareGiver.fields.primaryCareGiverChildId.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Child',
});

expect(genericSchema.models.Student.fields.Teachers.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Teacher',
relatedModelFields: ['student'],
belongsToFieldOnRelatedModel: 'student',
canUnlinkAssociatedModel: false,
relatedJoinFieldName: 'teacher',
relatedJoinTableName: 'StudentTeacher',
});

expect(genericSchema.models.Teacher.fields.students.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Student',
belongsToFieldOnRelatedModel: 'teacher',
relatedModelFields: ['teacher'],
canUnlinkAssociatedModel: false,
relatedJoinFieldName: 'student',
relatedJoinTableName: 'StudentTeacher',
});

expect(genericSchema.models.Lock.fields.Key.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Key',
associatedFields: ['lockKeyId'],
});

expect(genericSchema.models.Lock.fields.lockKeyId.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Key',
});

expect(genericSchema.models.Key.fields.Lock.relationship).toStrictEqual({
type: 'BELONGS_TO',
relatedModelName: 'Lock',
associatedFields: ['keyLockId'],
});

expect(genericSchema.models.Owner.fields.Dog.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Dog',
relatedModelFields: ['ownerID'],
canUnlinkAssociatedModel: true,
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});

expect(genericSchema.models.Dog.fields.ownerID.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Owner',
isHasManyIndex: true,
});
});

it('should map v2 relationships', () => {
const genericSchema = getGenericFromDataStore(schemaWithRelationshipsV2);

expect(genericSchema.models.PrimaryCareGiver.fields.Child.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Child',
associatedFields: ['primaryCareGiverChildId'],
});

expect(genericSchema.models.PrimaryCareGiver.fields.primaryCareGiverChildId.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Child',
});

expect(genericSchema.models.Student.fields.Teachers.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Teacher',
relatedModelFields: ['student'],
belongsToFieldOnRelatedModel: 'student',
canUnlinkAssociatedModel: false,
relatedJoinFieldName: 'teacher',
relatedJoinTableName: 'StudentTeacher',
});

expect(genericSchema.models.Teacher.fields.students.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Student',
belongsToFieldOnRelatedModel: 'teacher',
relatedModelFields: ['teacher'],
canUnlinkAssociatedModel: false,
relatedJoinFieldName: 'student',
relatedJoinTableName: 'StudentTeacher',
});

expect(genericSchema.models.Lock.fields.Key.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Key',
associatedFields: ['lockKeyId'],
});

expect(genericSchema.models.Lock.fields.lockKeyId.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Key',
});

expect(genericSchema.models.Key.fields.Lock.relationship).toStrictEqual({
type: 'BELONGS_TO',
relatedModelName: 'Lock',
associatedFields: ['keyLockId'],
});

expect(genericSchema.models.Owner.fields.Dog.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Dog',
relatedModelFields: ['ownerID'],
canUnlinkAssociatedModel: true,
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});

expect(genericSchema.models.Dog.fields.ownerID.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Owner',
isHasManyIndex: true,
});
});

it('should map enums', () => {
const genericSchema = getGenericFromDataStore(schemaWithEnums);

expect(genericSchema.enums).toStrictEqual(schemaWithEnums.enums);
});

it('should map nonModels', () => {
const genericSchema = getGenericFromDataStore(schemaWithNonModels);
expect(genericSchema.nonModels).toStrictEqual({
Reactions: {
fields: {
ball: { dataType: 'String', required: false, readOnly: false, isArray: false },
fireworks: { dataType: 'String', required: false, readOnly: false, isArray: false },
},
},
Misc: { fields: { quotes: { dataType: 'String', required: false, readOnly: false, isArray: true } } },
});
});

it('should handle schema with assumed associated fields and models', () => {
const genericSchema = getGenericFromDataStore(schemaWithAssumptions);
const userFields = genericSchema.models.User.fields;

expect(userFields.friends.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Friend',
relatedModelFields: ['friendId'],
canUnlinkAssociatedModel: true,
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});

expect(userFields.posts.relationship).toStrictEqual<HasManyRelationshipType>({
type: 'HAS_MANY',
relatedModelName: 'Post',
relatedModelFields: ['userPostsId'],
canUnlinkAssociatedModel: true,
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});
});

it('should correctly identify join tables', () => {
const genericSchemaWithJoinTable = getGenericFromDataStore(schemaWithRelationships);
const joinTables1 = Object.entries(genericSchemaWithJoinTable.models)
.filter(([, model]) => model.isJoinTable)
.map(([name]) => name);
expect(joinTables1).toStrictEqual(['StudentTeacher']);

const genericSchemaWithoutJoinTable = getGenericFromDataStore(schemaWithoutJoinTables);
const joinTables2 = Object.entries(genericSchemaWithoutJoinTable.models)
.filter(([, model]) => model.isJoinTable)
.map(([name]) => name);
expect(joinTables2).toHaveLength(0);
});

it('should correctly identify primary keys', () => {
const genericSchema = getGenericFromDataStore(schemaWithCPK);
const { models } = genericSchema;
expect(models.CPKStudent.primaryKeys).toStrictEqual(['specialStudentId']);
expect(models.CPKTeacher.primaryKeys).toStrictEqual(['specialTeacherId']);
});

it('should correctly map model with composite keys', () => {
const genericSchema = getGenericFromDataStore(schemaWithCompositeKeys);
const { CompositeDog } = genericSchema.models;
expect(CompositeDog.primaryKeys).toStrictEqual(['name', 'description']);
expect(CompositeDog.fields.CompositeBowl.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'CompositeBowl',
associatedFields: ['compositeDogCompositeBowlShape', 'compositeDogCompositeBowlSize'],
});
expect(CompositeDog.fields.CompositeOwner.relationship).toStrictEqual({
type: 'BELONGS_TO',
relatedModelName: 'CompositeOwner',
associatedFields: ['compositeDogCompositeOwnerLastName', 'compositeDogCompositeOwnerFirstName'],
});
});

it('should correctly map schema with hasMany-belongsTo', () => {
const genericSchema = getGenericFromDataStore(schemaWithHasManyBelongsTo);
const { User, Org, Post, Comment } = genericSchema.models;

expect(User.fields.comments.relationship).toStrictEqual({
type: 'HAS_MANY',
canUnlinkAssociatedModel: true,
relatedModelName: 'Comment',
relatedModelFields: ['userCommentsId'],
belongsToFieldOnRelatedModel: 'User',
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});

expect(Post.fields.comments.relationship).toStrictEqual({
type: 'HAS_MANY',
canUnlinkAssociatedModel: true,
relatedModelName: 'Comment',
relatedModelFields: ['postCommentsId'],
belongsToFieldOnRelatedModel: 'post',
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});

expect(Org.fields.comments.relationship).toStrictEqual({
type: 'HAS_MANY',
canUnlinkAssociatedModel: false,
relatedModelName: 'Comment',
relatedModelFields: ['orgCommentsId'],
belongsToFieldOnRelatedModel: 'Org',
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});

expect(Comment.fields.postID.relationship).toStrictEqual({
type: 'BELONGS_TO',
relatedModelName: 'Post',
});

expect(Comment.fields.userCommentsId.relationship).toStrictEqual({
type: 'BELONGS_TO',
relatedModelName: 'User',
isHasManyIndex: true,
});

expect(Comment.fields.orgCommentsId.relationship).toStrictEqual({
type: 'BELONGS_TO',
relatedModelName: 'Org',
isHasManyIndex: true,
});

expect(Comment.fields.postCommentsId.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Post',
isHasManyIndex: true,
});
});

it('should produce the same generic schema from MIPR and introspection schema', () => {
expect(getGenericFromDataStore(introspectionSchemaWithCompositeKeys).models).toStrictEqual(
getGenericFromDataStore(schemaWithCompositeKeys).models,
);
});

it('should handle bidirectional hasMany with defined field', () => {
const { Car, Dealership } = getGenericFromDataStore(schemaWithBiDirectionalHasManyWithDefinedField).models;
expect(Car.fields.dealership.relationship).toStrictEqual({
type: 'BELONGS_TO',
relatedModelName: 'Dealership',
associatedFields: ['dealershipId'],
});

expect(Dealership.fields.cars.relationship).toStrictEqual({
type: 'HAS_MANY',
canUnlinkAssociatedModel: true,
relatedModelName: 'Car',
relatedModelFields: [],
belongsToFieldOnRelatedModel: 'dealership',
relatedJoinFieldName: undefined,
relatedJoinTableName: undefined,
});
});
});
Loading

0 comments on commit ad4bf57

Please sign in to comment.