Skip to content

Commit

Permalink
feat: add feature flags for relationship and non-model form fields su…
Browse files Browse the repository at this point in the history
…pport
  • Loading branch information
Hein Jeong authored and hein-j committed Dec 28, 2022
1 parent 2e8504d commit 40bfeec
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getGenericFromDataStore,
StudioForm,
StudioView,
FormFeatureFlags,
} from '@aws-amplify/codegen-ui';
import { Schema } from '@aws-amplify/datastore';
import { createPrinter, createSourceFile, EmitHint, NewLineKind, Node } from 'typescript';
Expand Down Expand Up @@ -56,14 +57,15 @@ export const generateWithAmplifyFormRenderer = (
formJsonFile: string,
dataSchemaJsonFile: string | undefined,
renderConfig: ReactRenderConfig = defaultCLIRenderConfig,
featureFlags?: FormFeatureFlags,
): { componentText: string; declaration?: string } => {
let dataSchema: GenericDataSchema | undefined;
if (dataSchemaJsonFile) {
const dataStoreSchema = loadSchemaFromJSONFile<Schema>(dataSchemaJsonFile);
dataSchema = getGenericFromDataStore(dataStoreSchema);
}
const rendererFactory = new StudioTemplateRendererFactory(
(component: StudioForm) => new AmplifyFormRenderer(component, dataSchema, renderConfig),
(component: StudioForm) => new AmplifyFormRenderer(component, dataSchema, renderConfig, featureFlags),
);

const renderer = rendererFactory.buildRenderer(loadSchemaFromJSONFile<StudioForm>(formJsonFile));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/post-datastore-create',
'datastore/post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toContain('resetStateValues();');
Expand All @@ -33,6 +35,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/book-datastore-relationship',
'datastore/relationship',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { Book, Author } from "../models";');
Expand All @@ -48,6 +52,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/book-datastore-relationship-multiple',
'datastore/relationship-multiple',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { Book, Author, Title } from "../models";');
Expand All @@ -64,6 +70,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/member-datastore-create',
'datastore/project-team-model',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { Member, Team as Team0 } from "../models";');
Expand All @@ -79,6 +87,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/member-datastore-update-belongs-to',
'datastore/project-team-model',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { Member, Team as Team0 } from "../models";');
Expand All @@ -94,6 +104,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/member-datastore-create',
'datastore/project-team-model',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// Check that custom field label is working as expected
expect(componentText).toContain('Team Label');
Expand All @@ -108,6 +120,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/tag-datastore-create',
'datastore/tag-post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { Tag, Post, TagPost } from "../models";');
Expand All @@ -126,6 +140,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/tag-datastore-update',
'datastore/tag-post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { Tag, Post, TagPost } from "../models";');
Expand Down Expand Up @@ -153,6 +169,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/tag-datastore-create',
'datastore/tag-post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// get displayValue function
expect(componentText).toContain('statuses: (r) => {');
Expand All @@ -171,6 +189,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/school-datastore-create',
'datastore/school-student',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { School, Student } from "../models";');
Expand All @@ -189,6 +209,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/school-datastore-update',
'datastore/school-student',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// check nested model is imported
expect(componentText).toContain('import { School, Student } from "../models";');
Expand Down Expand Up @@ -216,6 +238,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/post-datastore-create-row',
'datastore/post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toMatchSnapshot();
Expand All @@ -226,6 +250,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/post-datastore-update',
'datastore/post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toMatchSnapshot();
Expand All @@ -236,6 +262,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/blog-datastore-create',
'datastore/blog',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toMatchSnapshot();
Expand All @@ -246,6 +274,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/input-gallery-create',
'datastore/input-gallery',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toContain('const convertToLocal');
Expand All @@ -257,6 +287,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/input-gallery-update',
'datastore/input-gallery',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toContain('const convertToLocal');
Expand All @@ -272,6 +304,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/flex-datastore-create',
'datastore/flex',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toContain('Flex0');
Expand All @@ -282,6 +316,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/flex-datastore-update',
'datastore/flex',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toContain('DataStore.save');
expect(componentText).toContain('Flex0');
Expand Down Expand Up @@ -368,15 +404,29 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/post-datastore-create-with-custom-array',
'datastore/post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
expect(componentText).toMatchSnapshot();
expect(declaration).toMatchSnapshot();
});

it('should not render non-model fields if non-model support off', () => {
const { componentText } = generateWithAmplifyFormRenderer(
'forms/post-datastore-create-with-custom-array',
'datastore/post',
undefined,
);

expect(componentText).not.toContain('nonModelField');
});

it('should use matching case for ref when array field is capitalized', () => {
const { componentText } = generateWithAmplifyFormRenderer(
'forms/post-datastore-create-with-custom-array',
'datastore/post',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);

expect(componentText).toContain('const CustomtagsRef');
Expand All @@ -388,6 +438,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/cpk-teacher-datastore-update',
'datastore/cpk-relationships',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);
// hasOne
expect(componentText).toContain('specialTeacherId: specialTeacherIdProp');
Expand Down Expand Up @@ -416,6 +468,8 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/composite-dog-datastore-update',
'datastore/composite-relationships',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);

expect(componentText).toMatchSnapshot();
Expand All @@ -426,11 +480,25 @@ describe('amplify form renderer tests', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/composite-dog-datastore-create',
'datastore/composite-relationships',
undefined,
{ isNonModelSupported: true, isRelationshipSupported: true },
);

expect(componentText).toMatchSnapshot();
expect(declaration).toMatchSnapshot();
});

it('should not render relationships if relationship support off', () => {
const { componentText } = generateWithAmplifyFormRenderer(
'forms/composite-dog-datastore-create',
'datastore/composite-relationships',
undefined,
);
expect(componentText).not.toContain('CompositeBowl');
expect(componentText).not.toContain('CompositeOwner');
expect(componentText).not.toContain('CompositeToys');
expect(componentText).not.toContain('CompositeVets');
});
});
});
});
10 changes: 8 additions & 2 deletions packages/codegen-ui-react/lib/forms/react-form-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
StudioNode,
StudioTemplateRenderer,
validateFormSchema,
FormFeatureFlags,
} from '@aws-amplify/codegen-ui';
import { EOL } from 'os';
import {
Expand Down Expand Up @@ -131,7 +132,12 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<

protected primaryKeys: string[] | undefined;

constructor(component: StudioForm, dataSchema: GenericDataSchema | undefined, renderConfig: ReactRenderConfig) {
constructor(
component: StudioForm,
dataSchema: GenericDataSchema | undefined,
renderConfig: ReactRenderConfig,
featureFlags?: FormFeatureFlags,
) {
super(component, new ReactOutputManager(), renderConfig);
this.renderConfig = {
...defaultRenderConfig,
Expand All @@ -140,7 +146,7 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
// the super class creates a component aka form which is what we pass in this extended implmentation
this.fileName = `${this.component.name}.${scriptKindToFileExtension(this.renderConfig.script)}`;

this.formDefinition = generateFormDefinition({ form: component, dataSchema });
this.formDefinition = generateFormDefinition({ form: component, dataSchema, featureFlags });

// create a studio component which will represent the structure of the form
this.formComponent = mapFormDefinitionToComponent(this.component.name, this.formDefinition);
Expand Down
21 changes: 19 additions & 2 deletions packages/codegen-ui/lib/__tests__/check-support.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('checkIsSupportedAsForm', () => {
expect(checkIsSupportedAsForm(model)).toBe(false);
});

it('should support relationships', () => {
it('should support relationships if relationship is enabled', () => {
const model: GenericDataModel = {
primaryKeys: ['id'],
fields: {
Expand All @@ -75,6 +75,23 @@ describe('checkIsSupportedAsForm', () => {
},
};

expect(checkIsSupportedAsForm(model)).toBe(true);
expect(checkIsSupportedAsForm(model, { isRelationshipSupported: true })).toBe(true);
});

it('should not support relationships if relationship is not enabled', () => {
const model: GenericDataModel = {
primaryKeys: ['id'],
fields: {
relationship: {
dataType: 'ID',
required: true,
readOnly: false,
isArray: false,
relationship: { type: 'HAS_ONE', relatedModelName: 'RelatedModel' },
},
},
};

expect(checkIsSupportedAsForm(model)).toBe(false);
});
});

0 comments on commit 40bfeec

Please sign in to comment.