From 2aea10f3d27751c843cf97d4b2d501ac674ddc78 Mon Sep 17 00:00:00 2001 From: tplevko Date: Tue, 25 Jun 2024 15:11:08 +0200 Subject: [PATCH] fix(1108): Provide common expression result types --- .../specialCamelRoutes/onException.cy.ts | 12 +++++----- .../expressionStepConfig.cy.ts | 23 +++++++++---------- .../setHeadersStepConfig.cy.ts | 12 +++++----- .../ui-tests/cypress/support/cypress.d.ts | 4 +++- .../next-commands/nodeConfiguration.ts | 18 ++++++++++++++- .../Form/customField/TypeaheadField.tsx | 1 + .../Form/expression/ExpressionEditor.test.tsx | 7 +++--- .../Form/expression/ExpressionEditor.tsx | 2 +- .../Form/expression/expression.service.ts | 16 +++++++++++++ 9 files changed, 64 insertions(+), 31 deletions(-) diff --git a/packages/ui-tests/cypress/e2e/designer/specialCamelRoutes/onException.cy.ts b/packages/ui-tests/cypress/e2e/designer/specialCamelRoutes/onException.cy.ts index bfc90b6ad..b8be954de 100644 --- a/packages/ui-tests/cypress/e2e/designer/specialCamelRoutes/onException.cy.ts +++ b/packages/ui-tests/cypress/e2e/designer/specialCamelRoutes/onException.cy.ts @@ -63,18 +63,18 @@ describe('Test for root on exception container', () => { cy.get(`input[name="redeliveryPolicyRef"]`).clear().type('testRedeliveryPolicyRef'); cy.openExpressionModal('retryWhile'); cy.selectExpression('Constant'); - cy.interactWithExpressinInputObject('expression', `retryWhile.constant`); - cy.interactWithExpressinInputObject('id', 'retryWhile.constantExpressionId'); + cy.interactWithExpressionInputObject('expression', `retryWhile.constant`); + cy.interactWithExpressionInputObject('id', 'retryWhile.constantExpressionId'); cy.confirmExpressionModal(); cy.openExpressionModal('handled'); cy.selectExpression('Constant'); - cy.interactWithExpressinInputObject('expression', `handled.constant`); - cy.interactWithExpressinInputObject('id', 'handled.constantExpressionId'); + cy.interactWithExpressionInputObject('expression', `handled.constant`); + cy.interactWithExpressionInputObject('id', 'handled.constantExpressionId'); cy.confirmExpressionModal(); cy.openExpressionModal('continued'); cy.selectExpression('Constant'); - cy.interactWithExpressinInputObject('expression', `continued.constant`); - cy.interactWithExpressinInputObject('id', 'continued.constantExpressionId'); + cy.interactWithExpressionInputObject('expression', `continued.constant`); + cy.interactWithExpressionInputObject('id', 'continued.constantExpressionId'); cy.confirmExpressionModal(); cy.openSourceCode(); diff --git a/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/expressionStepConfig.cy.ts b/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/expressionStepConfig.cy.ts index f2194ff81..d43c0e306 100644 --- a/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/expressionStepConfig.cy.ts +++ b/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/expressionStepConfig.cy.ts @@ -10,11 +10,10 @@ describe('Tests for sidebar expression configuration', () => { cy.openStepConfigurationTab('setHeader'); cy.openExpressionModalBtn(); cy.selectExpression('Simple'); - cy.interactWithExpressinInputObject('expression', `{{}{{}header.baz}}`); - cy.interactWithExpressinInputObject('id', 'simpleExpressionId'); - cy.interactWithExpressinInputObject('resultType', 'java.lang.String'); + cy.interactWithExpressionInputObject('expression', `{{}{{}header.baz}}`); + cy.interactWithExpressionInputObject('id', 'simpleExpressionId'); + cy.addExpressionResultType('java.lang.String'); cy.confirmExpressionModal(); - // CHECK they are reflected in the code editor cy.openSourceCode(); cy.checkCodeSpanLine('expression: "{{header.baz}}"', 1); @@ -31,7 +30,7 @@ describe('Tests for sidebar expression configuration', () => { cy.openExpressionModalBtn(); cy.selectExpression('JQ'); cy.interactWithConfigInputObject('expression', '.id'); - cy.interactWithConfigInputObject('resultType', 'java.lang.String'); + cy.addExpressionResultType('java.lang.String'); cy.interactWithConfigInputObject('trim'); cy.confirmExpressionModal(); @@ -44,7 +43,7 @@ describe('Tests for sidebar expression configuration', () => { cy.openExpressionModalBtn(); cy.selectExpression('JQ'); cy.interactWithConfigInputObject('expression', '.name'); - cy.interactWithConfigInputObject('resultType', 'java.lang.String'); + cy.addExpressionResultType('java.lang.String'); cy.interactWithConfigInputObject('trim'); cy.confirmExpressionModal(); @@ -53,7 +52,7 @@ describe('Tests for sidebar expression configuration', () => { // Check the configured fields didn't disappear from the first node cy.openExpressionModalBtn(); cy.checkConfigCheckboxObject('trim', true); - cy.checkConfigInputObject('resultType', 'java.lang.String'); + cy.checkExpressionResultType('java.lang.String'); cy.checkConfigInputObject('expression', '.id'); cy.cancelExpressionModal(); @@ -61,7 +60,7 @@ describe('Tests for sidebar expression configuration', () => { cy.openStepConfigurationTab('setHeader', 0); cy.openExpressionModalBtn(); cy.checkConfigCheckboxObject('trim', true); - cy.checkConfigInputObject('resultType', 'java.lang.String'); + cy.addExpressionResultType('java.lang.String'); cy.checkConfigInputObject('expression', '.name'); cy.cancelExpressionModal(); @@ -79,7 +78,7 @@ describe('Tests for sidebar expression configuration', () => { cy.openStepConfigurationTab('setHeader'); cy.openExpressionModalBtn(); cy.selectExpression('Simple'); - cy.interactWithExpressinInputObject('expression', `{{}{{}header.baz}}`); + cy.interactWithExpressionInputObject('expression', `{{}{{}header.baz}}`); cy.get('[data-ouia-component-id="ExpressionModal"]').within(() => { cy.get('textarea[name="expression"]').should('have.value', '{{header.baz}}'); }); @@ -103,9 +102,9 @@ describe('Tests for sidebar expression configuration', () => { cy.openStepConfigurationTab('setBody'); cy.openExpressionModalBtn(); cy.selectExpression('Simple'); - cy.interactWithExpressinInputObject('expression', `{{}{{}body.baz}}`); - cy.interactWithExpressinInputObject('id', 'simpleExpressionId'); - cy.interactWithExpressinInputObject('resultType', 'java.lang.String'); + cy.interactWithExpressionInputObject('expression', `{{}{{}body.baz}}`); + cy.interactWithExpressionInputObject('id', 'simpleExpressionId'); + cy.addExpressionResultType('java.lang.String'); cy.confirmExpressionModal(); // CHECK they are reflected in the code editor diff --git a/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/setHeadersStepConfig.cy.ts b/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/setHeadersStepConfig.cy.ts index 4bb7840ad..91a047c74 100644 --- a/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/setHeadersStepConfig.cy.ts +++ b/packages/ui-tests/cypress/e2e/designer/specialStepConfiguration/setHeadersStepConfig.cy.ts @@ -15,18 +15,18 @@ describe('Tests for sidebar setHeaders step configuration', () => { cy.get('[data-testid="launch-expression-modal-btn"]').should('be.visible').click(); cy.selectExpression('Simple'); - cy.interactWithExpressinInputObject('expression', `{{}random(1,100)}`); - cy.interactWithExpressinInputObject('id', 'simpleExpressionId'); - cy.interactWithExpressinInputObject('resultType', 'java.lang.String'); + cy.interactWithExpressionInputObject('expression', `{{}random(1,100)}`); + cy.interactWithExpressionInputObject('id', 'simpleExpressionId'); + cy.addExpressionResultType('java.lang.String'); cy.confirmExpressionModal(); cy.get('[data-testid="list-add-field"]').click(); cy.get('[data-testid="launch-expression-modal-btn"]').eq(1).should('be.visible').click(); cy.selectExpression('Constant'); - cy.interactWithExpressinInputObject('expression', `constant`); - cy.interactWithExpressinInputObject('id', 'constantExpressionId'); - cy.interactWithExpressinInputObject('resultType', 'java.lang.String'); + cy.interactWithExpressionInputObject('expression', `constant`); + cy.interactWithExpressionInputObject('id', 'constantExpressionId'); + cy.addExpressionResultType('java.lang.String'); cy.confirmExpressionModal(); cy.openSourceCode(); diff --git a/packages/ui-tests/cypress/support/cypress.d.ts b/packages/ui-tests/cypress/support/cypress.d.ts index c70c774ce..e145a9a12 100644 --- a/packages/ui-tests/cypress/support/cypress.d.ts +++ b/packages/ui-tests/cypress/support/cypress.d.ts @@ -53,7 +53,9 @@ declare global { checkCatalogVersion(version: string): Chainable>; chooseFromCatalog(nodeType: string, name: string): Chainable>; // nodeConfiguration - interactWithExpressinInputObject(inputName: string, value?: string): Chainable>; + interactWithExpressionInputObject(inputName: string, value?: string): Chainable>; + addExpressionResultType(value: string): Chainable>; + checkExpressionResultType(value: string): Chainable>; interactWithConfigInputObject(inputName: string, value?: string): Chainable>; interactWithDataformatInputObject(inputName: string, value?: string): Chainable>; checkConfigCheckboxObject(inputName: string, value: boolean): Chainable>; diff --git a/packages/ui-tests/cypress/support/next-commands/nodeConfiguration.ts b/packages/ui-tests/cypress/support/next-commands/nodeConfiguration.ts index 6a60db4e2..bf3a90506 100644 --- a/packages/ui-tests/cypress/support/next-commands/nodeConfiguration.ts +++ b/packages/ui-tests/cypress/support/next-commands/nodeConfiguration.ts @@ -1,9 +1,24 @@ -Cypress.Commands.add('interactWithExpressinInputObject', (inputName: string, value?: string) => { +Cypress.Commands.add('interactWithExpressionInputObject', (inputName: string, value?: string) => { cy.get('[data-ouia-component-id="ExpressionModal"]').within(() => { cy.interactWithConfigInputObject(inputName, value); }); }); +Cypress.Commands.add('addExpressionResultType', (value: string) => { + cy.get('[data-ouia-component-id="ExpressionModal"]').within(() => { + cy.get('[data-fieldname="resultType"]').within(() => { + cy.get(`input.pf-v5-c-text-input-group__text-input`).clear(); + cy.get(`input.pf-v5-c-text-input-group__text-input`).type(value).type('{enter}'); + }); + }); +}); + +Cypress.Commands.add('checkExpressionResultType', (value: string) => { + cy.get('[data-fieldname="resultType"]').within(() => { + cy.get(`input.pf-v5-c-text-input-group__text-input`).should('have.value', value); + }); +}); + Cypress.Commands.add('interactWithDataformatInputObject', (inputName: string, value?: string) => { cy.get('[data-testid="dataformat-config-card"]').within(() => { cy.interactWithConfigInputObject(inputName, value); @@ -42,6 +57,7 @@ Cypress.Commands.add('openExpressionModal', (expression: string) => { Cypress.Commands.add('selectExpression', (expression: string) => { cy.get('div[data-ouia-component-id="ExpressionModal"] button.pf-v5-c-menu-toggle__button') + .eq(0) .should('be.visible') .click(); const regex = new RegExp(`^${expression}$`); diff --git a/packages/ui/src/components/Form/customField/TypeaheadField.tsx b/packages/ui/src/components/Form/customField/TypeaheadField.tsx index 925fc3f89..0316b2c49 100644 --- a/packages/ui/src/components/Form/customField/TypeaheadField.tsx +++ b/packages/ui/src/components/Form/customField/TypeaheadField.tsx @@ -172,6 +172,7 @@ export const TypeaheadField = connectField((props: TypeaheadProps) => { onChange={onTextInputChange} onKeyDown={onInputKeyDown} id="create-typeahead-select-input" + data-testid="create-typeahead-select-input" autoComplete="off" innerRef={textInputRef} placeholder="Select an option" diff --git a/packages/ui/src/components/Form/expression/ExpressionEditor.test.tsx b/packages/ui/src/components/Form/expression/ExpressionEditor.test.tsx index eb80c463e..5df803eb7 100644 --- a/packages/ui/src/components/Form/expression/ExpressionEditor.test.tsx +++ b/packages/ui/src/components/Form/expression/ExpressionEditor.test.tsx @@ -43,10 +43,9 @@ describe('ExpressionEditor', () => { const dropdown = screen.getAllByTestId('typeahead-select-input').filter((input) => input.innerHTML.includes('JQ')); expect(dropdown).toHaveLength(1); const resultTypeInput = screen - .getAllByRole('textbox') - .filter((textbox) => textbox.getAttribute('label') === 'Result Type'); + .getAllByTestId('create-typeahead-select-input') + .filter((input) => input.innerHTML.includes('string')); expect(resultTypeInput).toHaveLength(1); - expect(resultTypeInput[0].getAttribute('value')).toEqual('string'); const sourceInput = screen.getAllByRole('textbox').filter((textbox) => textbox.getAttribute('label') === 'Source'); expect(sourceInput).toHaveLength(1); expect(sourceInput[0].getAttribute('value')).toEqual(''); @@ -70,7 +69,7 @@ describe('ExpressionEditor', () => { onChangeExpressionModel={onChangeMock} >, ); - const inputElement = screen.getByRole('combobox'); + const inputElement = screen.getAllByRole('combobox')[0]; await act(async () => { fireEvent.change(inputElement, { target: { value: 'JQ' } }); }); diff --git a/packages/ui/src/components/Form/expression/ExpressionEditor.tsx b/packages/ui/src/components/Form/expression/ExpressionEditor.tsx index 9a50adf55..c0d142169 100644 --- a/packages/ui/src/components/Form/expression/ExpressionEditor.tsx +++ b/packages/ui/src/components/Form/expression/ExpressionEditor.tsx @@ -37,7 +37,7 @@ export const ExpressionEditor: FunctionComponent = ({ ); const languageSchema = useMemo(() => { - return language && ExpressionService.getLanguageSchema(language); + return language && ExpressionService.getLanguageSchema(ExpressionService.setStepExpressionResultType(language)); }, [language]); const handleOnChange = useCallback( diff --git a/packages/ui/src/components/Form/expression/expression.service.ts b/packages/ui/src/components/Form/expression/expression.service.ts index 7593d6784..b605c3e66 100644 --- a/packages/ui/src/components/Form/expression/expression.service.ts +++ b/packages/ui/src/components/Form/expression/expression.service.ts @@ -144,6 +144,22 @@ export class ExpressionService { } } + /** + * Set the result type property to enum of common result types. + * + * @param language + * @returns + */ + static setStepExpressionResultType(language: ICamelLanguageDefinition): ICamelLanguageDefinition { + if (language.propertiesSchema?.properties?.resultType) { + language.propertiesSchema.properties.resultType = { + ...language.propertiesSchema.properties.resultType, + enum: ['java.lang.String', 'java.lang.Boolean', 'java.lang.Integer', 'java.lang.Double', 'java.lang.Float'], + }; + } + return language; + } + /** * Parse the property expression model from the parent parameter model object. * @param languageCatalogMap The language catalog map to use as a dictionary.