Skip to content

Commit

Permalink
fix: allow operand type to be specified in ConditionalStudioComponent…
Browse files Browse the repository at this point in the history
…Property (#335)
  • Loading branch information
kpranoto-aws authored and alharris-at committed Feb 25, 2022
1 parent b925697 commit 3b3932b
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ NodeObject {
}
`;

exports[`react-component-render-helper buildContionalExpression operandType does not exist 1`] = `"{(user?.age && user?.age > \\"18\\") ? \\"Vote\\" : \\"Sorry you cannot vote\\"}"`;
exports[`react-component-render-helper buildContionalExpression operandType exists 1`] = `"{(user?.age && user?.age > 18) ? \\"Vote\\" : \\"Sorry you cannot vote\\"}"`;
exports[`react-component-render-helper buildFixedJsxExpression boolean 1`] = `"{true}"`;
exports[`react-component-render-helper buildFixedJsxExpression json parse error 1`] = `"Failed to parse value \\"⭐\\""`;
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 { RelationalOperator } from '@aws-amplify/codegen-ui';
import { RelationalOperator, ConditionalStudioComponentProperty } from '@aws-amplify/codegen-ui';
import {
getFixedComponentPropValueExpression,
ComponentPropertyValueTypes,
Expand All @@ -27,10 +27,34 @@ import {
isDefaultValueOnly,
getSyntaxKindToken,
buildChildElement,
buildConditionalExpression,
} from '../react-component-render-helper';

import { assertASTMatchesSnapshot } from './__utils__/snapshot-helpers';

function buildConditionalWithOperand(operand: string, type?: string) {
const conditional: ConditionalStudioComponentProperty = {
condition: {
property: 'user',
field: 'age',
operator: 'gt',
operand,
then: {
value: 'Vote',
},
else: {
value: 'Sorry you cannot vote',
},
},
};

if (type) {
conditional.condition.operandType = type;
}

return conditional;
}

describe('react-component-render-helper', () => {
test('getFixedComponentPropValueExpression', () => {
const value = 'testValue';
Expand All @@ -52,20 +76,7 @@ describe('react-component-render-helper', () => {
ConcatenatedStudioComponentProperty: { checker: isConcatenatedProperty, property: { concat: [] } },
ConditionalStudioComponentProperty: {
checker: isConditionalProperty,
property: {
condition: {
property: 'user',
field: 'age',
operator: 'gt',
operand: '18',
then: {
value: 'Vote',
},
else: {
value: 'Sorry you cannot vote',
},
},
},
property: buildConditionalWithOperand('18'),
},
FixedStudioComponentProperty: { checker: isFixedPropertyWithValue, property: { value: 'testValue' } },
BoundStudioComponentProperty: {
Expand Down Expand Up @@ -249,4 +260,22 @@ describe('react-component-render-helper', () => {
expect(buildChildElement(prop)).toMatchSnapshot();
});
});

describe('buildContionalExpression', () => {
test('operandType exists', () => {
const exp = buildConditionalExpression(buildConditionalWithOperand('18', 'number'));
assertASTMatchesSnapshot(exp);
});

test('operandType does not exist', () => {
const exp = buildConditionalExpression(buildConditionalWithOperand('18'));
assertASTMatchesSnapshot(exp);
});

test('operand and operandType mismatch', () => {
expect(() => buildConditionalExpression(buildConditionalWithOperand('18', 'boolean'))).toThrow(
'Parsed value 18 and type boolean mismatch',
);
});
});
});
44 changes: 37 additions & 7 deletions packages/codegen-ui-react/lib/react-component-render-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
JsxExpression,
BinaryOperatorToken,
JsxChild,
PrimaryExpression,
} from 'typescript';

import { ImportCollection, ImportSource } from './imports';
Expand Down Expand Up @@ -324,19 +325,44 @@ export function getSyntaxKindToken(operator: RelationalOperator): BinaryOperator
}
}

export function getConditionalOperandExpression(operand: string | number | boolean): Expression {
switch (typeof operand) {
export function getConditionalOperandExpression(
operand: string | number | boolean,
operandType: string | undefined,
): Expression {
if (typeof operand === 'string' && operandType && operandType !== 'string') {
return stringValueToTypedLiteral(operand, operandType);
}
return typedValueToJsxLiteral(operand);
}

function stringValueToTypedLiteral(value: any, valueType: string): PrimaryExpression {
try {
const typedVal = JSON.parse(value);
if (valueType === typeof typedVal) {
return typedValueToJsxLiteral(typedVal);
}
throw Error(`Parsed value ${value} and type ${valueType} mismatch`);
} catch (err) {
if (err instanceof SyntaxError) {
return factory.createStringLiteral(value);
}
throw err;
}
}

function typedValueToJsxLiteral(value: any): PrimaryExpression {
switch (typeof value) {
case 'number':
return factory.createNumericLiteral(operand);
return factory.createNumericLiteral(value);
case 'boolean':
return operand ? factory.createTrue() : factory.createFalse();
return value ? factory.createTrue() : factory.createFalse();
default:
return factory.createStringLiteral(operand);
return factory.createStringLiteral(value);
}
}

export function buildConditionalExpression(prop: ConditionalStudioComponentProperty): JsxExpression {
const { property, field, operand, operator, then } = prop.condition;
const { property, field, operand, operandType, operator, then } = prop.condition;
const elseBlock = prop.condition.else;
const operatorToken = getSyntaxKindToken(operator);

Expand All @@ -360,7 +386,11 @@ export function buildConditionalExpression(prop: ConditionalStudioComponentPrope
factory.createBinaryExpression(
propertyAccess,
factory.createToken(SyntaxKind.AmpersandAmpersandToken),
factory.createBinaryExpression(propertyAccess, operatorToken, getConditionalOperandExpression(operand)),
factory.createBinaryExpression(
propertyAccess,
operatorToken,
getConditionalOperandExpression(operand, operandType),
),
),
),
factory.createToken(SyntaxKind.QuestionToken),
Expand Down
1 change: 1 addition & 0 deletions packages/codegen-ui/lib/types/studio-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ export type ConditionalStudioComponentProperty = {
field?: string;
operator: RelationalOperator;
operand: string | number | boolean;
operandType?: string;
then: StudioComponentProperty;
else: StudioComponentProperty;
};
Expand Down

0 comments on commit 3b3932b

Please sign in to comment.