From d0dce57c142bbcc02dce786d59875a1204138e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20FIlipovi=C4=87?= Date: Fri, 1 Nov 2024 16:11:54 +0100 Subject: [PATCH] refactor(editor): Migrate `ParameterOptions` to composition API (no-changelog) (#11501) --- .../AssignmentCollection.vue | 4 +- .../src/components/ParameterOptions.test.ts | 123 ++++++++ .../src/components/ParameterOptions.vue | 283 ++++++++---------- .../ResourceMapper/MappingFields.vue | 1 + .../ResourceMapper/MatchingColumnsSelect.vue | 1 + 5 files changed, 251 insertions(+), 161 deletions(-) create mode 100644 packages/editor-ui/src/components/ParameterOptions.test.ts diff --git a/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue b/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue index fb13948302..24545bd7b9 100644 --- a/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue +++ b/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue @@ -98,10 +98,10 @@ function getIssues(index: number): string[] { return issues.value[`${props.parameter.name}.${index}`] ?? []; } -function optionSelected(action: 'clearAll' | 'addAll') { +function optionSelected(action: string) { if (action === 'clearAll') { state.paramValue.assignments = []; - } else { + } else if (action === 'addAll' && inputData.value) { const newAssignments = inputDataToAssignments(inputData.value); state.paramValue.assignments = state.paramValue.assignments.concat(newAssignments); } diff --git a/packages/editor-ui/src/components/ParameterOptions.test.ts b/packages/editor-ui/src/components/ParameterOptions.test.ts new file mode 100644 index 0000000000..e3984d6e50 --- /dev/null +++ b/packages/editor-ui/src/components/ParameterOptions.test.ts @@ -0,0 +1,123 @@ +import { renderComponent } from '@/__tests__/render'; +import userEvent from '@testing-library/user-event'; +import { within } from '@testing-library/vue'; +import { waitFor } from '@testing-library/vue'; +import ParameterOptions from './ParameterOptions.vue'; + +const DEFAULT_PARAMETER = { + displayName: 'Fields to Set', + name: 'assignments', + type: 'assignmentCollection', + default: {}, +}; + +describe('ParameterOptions', () => { + it('renders default options properly', () => { + const { getByTestId } = renderComponent(ParameterOptions, { + props: { + parameter: DEFAULT_PARAMETER, + isReadOnly: false, + }, + }); + expect(getByTestId('parameter-options-container')).toBeInTheDocument(); + expect(getByTestId('action-toggle')).toBeInTheDocument(); + expect(getByTestId('radio-button-fixed')).toBeInTheDocument(); + expect(getByTestId('radio-button-expression')).toBeInTheDocument(); + }); + + it("doesn't render expression with showExpression set to false", () => { + const { getByTestId, queryByTestId, container } = renderComponent(ParameterOptions, { + props: { + parameter: DEFAULT_PARAMETER, + isReadOnly: false, + showExpressionSelector: false, + value: 'manual', + }, + }); + expect(getByTestId('parameter-options-container')).toBeInTheDocument(); + expect(getByTestId('action-toggle')).toBeInTheDocument(); + expect(queryByTestId('radio-button-fixed')).not.toBeInTheDocument(); + expect(queryByTestId('radio-button-expression')).not.toBeInTheDocument(); + expect(container.querySelector('.noExpressionSelector')).toBeInTheDocument(); + }); + + it('should render loading state', () => { + const CUSTOM_LOADING_MESSAGE = 'Loading...'; + const { getByTestId, getByText } = renderComponent(ParameterOptions, { + props: { + parameter: DEFAULT_PARAMETER, + isReadOnly: false, + showExpressionSelector: false, + value: 'manual', + loading: true, + loadingMessage: CUSTOM_LOADING_MESSAGE, + }, + }); + expect(getByTestId('parameter-options-loader')).toBeInTheDocument(); + expect(getByText(CUSTOM_LOADING_MESSAGE)).toBeInTheDocument(); + }); + + it('should render horizontal icon', () => { + const { container } = renderComponent(ParameterOptions, { + props: { + parameter: DEFAULT_PARAMETER, + value: 'manual', + isReadOnly: false, + iconOrientation: 'horizontal', + }, + }); + expect(container.querySelector('[data-icon="ellipsis-h"]')).toBeInTheDocument(); + }); + + it('should render custom actions', async () => { + const CUSTOM_ACTIONS = [ + { label: 'Action 1', value: 'action1' }, + { label: 'Action 2', value: 'action2' }, + ]; + const { getByTestId } = renderComponent(ParameterOptions, { + props: { + parameter: DEFAULT_PARAMETER, + value: 'manual', + isReadOnly: false, + customActions: CUSTOM_ACTIONS, + }, + }); + const actionToggle = getByTestId('action-toggle'); + const actionToggleButton = within(actionToggle).getByRole('button'); + expect(actionToggleButton).toBeVisible(); + await userEvent.click(actionToggle); + const actionToggleId = actionToggleButton.getAttribute('aria-controls'); + const actionDropdown = document.getElementById(actionToggleId as string) as HTMLElement; + expect(actionDropdown).toBeInTheDocument(); + // All custom actions should be rendered + CUSTOM_ACTIONS.forEach((action) => { + expect(within(actionDropdown).getByText(action.label)).toBeInTheDocument(); + }); + }); + + it('should emit update:modelValue when changing to expression', async () => { + const { emitted, getByTestId } = renderComponent(ParameterOptions, { + props: { + parameter: DEFAULT_PARAMETER, + value: 'manual', + isReadOnly: false, + }, + }); + expect(getByTestId('radio-button-expression')).toBeInTheDocument(); + await userEvent.click(getByTestId('radio-button-expression')); + await waitFor(() => expect(emitted('update:modelValue')).toEqual([['addExpression']])); + }); + + it('should emit update:modelValue when changing to fixed', async () => { + const { emitted, getByTestId } = renderComponent(ParameterOptions, { + props: { + parameter: DEFAULT_PARAMETER, + value: '=manual', + isReadOnly: false, + }, + }); + expect(getByTestId('radio-button-fixed')).toBeInTheDocument(); + await userEvent.click(getByTestId('radio-button-fixed')); + await waitFor(() => expect(emitted('update:modelValue')).toEqual([['removeExpression']])); + }); +}); diff --git a/packages/editor-ui/src/components/ParameterOptions.vue b/packages/editor-ui/src/components/ParameterOptions.vue index bfe9939805..10c3759324 100644 --- a/packages/editor-ui/src/components/ParameterOptions.vue +++ b/packages/editor-ui/src/components/ParameterOptions.vue @@ -1,169 +1,134 @@ - diff --git a/packages/editor-ui/src/components/ResourceMapper/MatchingColumnsSelect.vue b/packages/editor-ui/src/components/ResourceMapper/MatchingColumnsSelect.vue index 7a40e24400..e663190c95 100644 --- a/packages/editor-ui/src/components/ResourceMapper/MatchingColumnsSelect.vue +++ b/packages/editor-ui/src/components/ResourceMapper/MatchingColumnsSelect.vue @@ -187,6 +187,7 @@ defineExpose({ :loading="props.refreshInProgress" :loading-message="fetchingFieldsLabel" :is-read-only="isReadOnly" + :value="state.selected" @update:model-value="onParameterActionSelected" />