Skip to content

Commit

Permalink
chore: add valueMappings to forms (#537)
Browse files Browse the repository at this point in the history
Co-authored-by: Hein Jeong <heinje@amazon.com>
  • Loading branch information
hein-j and Hein Jeong authored Jul 22, 2022
1 parent 9ceb6bc commit 3634728
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import { mapFormFieldConfig, getFormDefinitionInputElement } from '../../../generate-form-definition/helpers';
import { mergeValueMappings } from '../../../generate-form-definition/helpers/form-field';
import { FormDefinition, ModelFieldsConfigs, StudioFormFieldConfig, StudioGenericFieldConfig } from '../../../types';

describe('mapFormFieldConfig', () => {
Expand Down Expand Up @@ -147,21 +148,18 @@ describe('getFormDefinitionInputElement', () => {
inputType: {
type: 'SelectField',
readOnly: true,
valueMappings: [
{ displayValue: 'value1Display', value: 'value1' },
{ displayValue: 'value2Display', value: 'value2' },
],
valueMappings: { values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }] },
defaultValue: 'value1',
},
};

expect(getFormDefinitionInputElement(config)).toStrictEqual({
componentType: 'SelectField',
props: { label: 'Label', isDisabled: true },
options: [
{ value: 'value1', children: 'value1Display' },
{ value: 'value2', children: 'value2Display' },
],
valueMappings: {
values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }],
bindingProperties: {},
},
defaultValue: 'value1',
});
});
Expand Down Expand Up @@ -289,20 +287,35 @@ describe('getFormDefinitionInputElement', () => {
inputType: {
type: 'RadioGroupField',
name: 'MyFieldName',
valueMappings: [
{ displayValue: 'value1Display', value: 'value1' },
{ displayValue: 'value2Display', value: 'value2' },
],
valueMappings: { values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }] },
},
};

expect(getFormDefinitionInputElement(config)).toStrictEqual({
componentType: 'RadioGroupField',
props: { label: 'Label', name: 'MyFieldName' },
valueMappings: {
values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }],
bindingProperties: {},
},
});
});

it('should return default valueMappings for RadioGroupField if no values available', () => {
const config = {
inputType: {
type: 'RadioGroupField',
name: 'MyFieldName',
valueMappings: { values: [] },
},
};

expect(getFormDefinitionInputElement(config)).toStrictEqual({
componentType: 'RadioGroupField',
props: { label: 'Label', name: 'MyFieldName' },
radios: [
{ value: 'value1', children: 'value1Display' },
{ value: 'value2', children: 'value2Display' },
],
valueMappings: {
values: [{ value: { value: 'value' }, displayValue: { value: 'Label' } }],
},
});
});

Expand All @@ -322,3 +335,61 @@ describe('getFormDefinitionInputElement', () => {
expect(() => getFormDefinitionInputElement(config)).toThrow();
});
});

describe('mergeValueMappings', () => {
it('should return override values if no base values', () => {
expect(mergeValueMappings(undefined, { values: [{ value: { value: 'value1' } }] }).values).toStrictEqual([
{ value: { value: 'value1' } },
]);
});

it('should return base values if no override values', () => {
expect(mergeValueMappings({ values: [{ value: { value: 'value1' } }] }, undefined).values).toStrictEqual([
{ value: { value: 'value1' } },
]);
});

it('should only return base values with overrides applied if both base and overrides present', () => {
const mergedMappings = mergeValueMappings(
{
values: [
{ value: { value: 'NEW_YORK' }, displayValue: { value: 'New york' } },
{ value: { value: 'HOUSTON' }, displayValue: { value: 'Houston' } },
{ value: { value: 'LOS_ANGELES' }, displayValue: { value: 'Los angeles' } },
],
},
{
values: [
{ value: { value: 'LOS_ANGELES' }, displayValue: { value: 'LA' } },
{ value: { value: 'AUSTIN' }, displayValue: { value: 'Austin' } },
],
},
);

expect(mergedMappings.values).toStrictEqual([
{ value: { value: 'NEW_YORK' }, displayValue: { value: 'New york' } },
{ value: { value: 'HOUSTON' }, displayValue: { value: 'Houston' } },
{ value: { value: 'LOS_ANGELES' }, displayValue: { value: 'LA' } },
]);

expect(mergedMappings.values.find((v) => 'value' in v.value && v.value.value === 'AUSTIN')).toBeUndefined();
});

it('should merge base and override bindingProperties', () => {
expect(
mergeValueMappings(
{
values: [{ value: { value: 'sdjoiflj' }, displayValue: { bindingProperties: { property: 'Dog' } } }],
bindingProperties: {
Dog: { type: 'Data', bindingProperties: { model: 'Dog' } },
Person: { type: 'Data', bindingProperties: { model: 'Person' } },
},
},
{ values: [], bindingProperties: { Dog: { type: 'Data', bindingProperties: { model: 'MyDog' } } } },
).bindingProperties,
).toStrictEqual({
Person: { type: 'Data', bindingProperties: { model: 'Person' } },
Dog: { type: 'Data', bindingProperties: { model: 'MyDog' } },
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
limitations under the License.
*/

import { mapModelFieldsConfigs } from '../../../generate-form-definition/helpers';
import { mapModelFieldsConfigs, getFieldTypeMapKey } from '../../../generate-form-definition/helpers';
import { FormDefinition, ModelFieldsConfigs, GenericDataSchema } from '../../../types';

describe('mapModelFieldsConfigs', () => {
Expand Down Expand Up @@ -106,7 +106,7 @@ describe('mapModelFieldsConfigs', () => {
).toThrow();
});

it('should throw if there is no default component', () => {
it('should generate config from id field but not add it to matrix', () => {
const formDefinition: FormDefinition = {
form: { layoutStyle: {} },
elements: {},
Expand All @@ -116,25 +116,37 @@ describe('mapModelFieldsConfigs', () => {

const modelFieldsConfigs: ModelFieldsConfigs = {};

const dataSchema: any = {
const dataSchema: GenericDataSchema = {
dataSourceType: 'DataStore',
enums: {},
nonModels: {},
models: {
Dog: {
fields: {
names: { dataType: 'ErrantType', readOnly: false, required: false, isArray: true },
id: { dataType: 'ID', readOnly: false, required: true, isArray: false },
},
},
},
};

expect(() =>
mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema }),
).toThrow();
mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema });

expect(formDefinition.elementMatrix).toStrictEqual([]);
expect(modelFieldsConfigs).toStrictEqual({
id: {
inputType: {
name: 'id',
readOnly: false,
required: true,
type: 'TextField',
value: 'true',
},
label: 'id',
},
});
});

it('should generate config from id field but not add it to matrix', () => {
it('should add read-only fields to configs but not to matrix', () => {
const formDefinition: FormDefinition = {
form: { layoutStyle: {} },
elements: {},
Expand All @@ -151,7 +163,7 @@ describe('mapModelFieldsConfigs', () => {
models: {
Dog: {
fields: {
id: { dataType: 'ID', readOnly: false, required: true, isArray: false },
name: { dataType: 'String', readOnly: true, required: false, isArray: false },
},
},
},
Expand All @@ -161,20 +173,20 @@ describe('mapModelFieldsConfigs', () => {

expect(formDefinition.elementMatrix).toStrictEqual([]);
expect(modelFieldsConfigs).toStrictEqual({
id: {
name: {
inputType: {
name: 'id',
readOnly: false,
required: true,
name: 'name',
readOnly: true,
required: false,
type: 'TextField',
value: 'true',
},
label: 'id',
label: 'name',
},
});
});

it('should add read-only fields to configs but not to matrix', () => {
it('should add value mappings from enums', () => {
const formDefinition: FormDefinition = {
form: { layoutStyle: {} },
elements: {},
Expand All @@ -184,33 +196,104 @@ describe('mapModelFieldsConfigs', () => {

const modelFieldsConfigs: ModelFieldsConfigs = {};

const nonEnglishAlphabetTest = 'ㅎ🌱يَّة';

const dataSchema: GenericDataSchema = {
dataSourceType: 'DataStore',
enums: {},
enums: { City: { values: ['NEW_YORK', 'HOUSTON', 'LOS_ANGELES', nonEnglishAlphabetTest] } },
nonModels: {},
models: {
Dog: {
fields: {
name: { dataType: 'String', readOnly: true, required: false, isArray: false },
city: { dataType: { enum: 'City' }, readOnly: false, required: false, isArray: false },
},
},
},
};

mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema });

expect(formDefinition.elementMatrix).toStrictEqual([]);
expect(modelFieldsConfigs).toStrictEqual({
name: {
city: {
inputType: {
name: 'name',
readOnly: true,
name: 'city',
readOnly: false,
required: false,
type: 'TextField',
type: 'SelectField',
value: 'true',
valueMappings: {
values: [
{ value: { value: 'NEW_YORK' }, displayValue: { value: 'New york' } },
{ value: { value: 'HOUSTON' }, displayValue: { value: 'Houston' } },
{ value: { value: 'LOS_ANGELES' }, displayValue: { value: 'Los angeles' } },
{ value: { value: nonEnglishAlphabetTest }, displayValue: { value: nonEnglishAlphabetTest } },
],
},
},
label: 'name',
label: 'city',
},
});
});

it('should throw if type is enum but no matching enum provided', () => {
const formDefinition: FormDefinition = {
form: { layoutStyle: {} },
elements: {},
buttons: {},
elementMatrix: [],
};

const modelFieldsConfigs: ModelFieldsConfigs = {};

const dataSchema: GenericDataSchema = {
dataSourceType: 'DataStore',
enums: {},
nonModels: {},
models: {
Dog: {
fields: {
city: { dataType: { enum: 'City' }, readOnly: false, required: false, isArray: false },
},
},
},
};

expect(() =>
mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema }),
).toThrow();
});
});

describe('getFieldTypeMapKey', () => {
it('should return `Relationship` if field is of type model or has a related model', () => {
expect(
getFieldTypeMapKey({
dataType: { model: 'Dog' },
readOnly: false,
required: false,
isArray: false,
}),
).toBe('Relationship');

expect(
getFieldTypeMapKey({
dataType: 'ID',
readOnly: false,
required: false,
isArray: false,
relationship: { relatedModelName: 'Dog', type: 'HAS_ONE' },
}),
).toBe('Relationship');
});

it('should return `NonModel` if dataType is nonModel', () => {
expect(
getFieldTypeMapKey({
dataType: { nonModel: 'Misc' },
readOnly: false,
required: false,
isArray: false,
}),
).toBe('NonModel');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const FORM_DEFINITION_DEFAULTS = {
defaultCountryCode: '+1',
value: 'true',
name: 'fieldName',
valueMappings: [{ value: 'value', displayValue: 'Label' }],
valueMappings: { values: [{ value: { value: 'value' }, displayValue: { value: 'Label' } }] },
},
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
limitations under the License.
*/

import { FormDefinitionInputElement } from '../../types';
import { FormDefinitionInputElement, FieldTypeMapKeys } from '../../types';

/**
* Maps data types to UI Components
*/
export const FIELD_TYPE_MAP: {
[key: string]: {
[key in FieldTypeMapKeys]: {
defaultComponent: FormDefinitionInputElement['componentType'];
supportedComponents: Set<FormDefinitionInputElement['componentType']>;
};
Expand Down Expand Up @@ -89,4 +89,8 @@ export const FIELD_TYPE_MAP: {
defaultComponent: 'SelectField',
supportedComponents: new Set(['SelectField']),
},
NonModel: {
defaultComponent: 'TextAreaField',
supportedComponents: new Set(['TextAreaField']),
},
};
Loading

0 comments on commit 3634728

Please sign in to comment.