diff --git a/frontend/packages/shared/src/types/ComponentSpecificConfig.ts b/frontend/packages/shared/src/types/ComponentSpecificConfig.ts index 9dbccf45a19..db8474f8145 100644 --- a/frontend/packages/shared/src/types/ComponentSpecificConfig.ts +++ b/frontend/packages/shared/src/types/ComponentSpecificConfig.ts @@ -7,6 +7,7 @@ import type { ActionButtonAction } from 'app-shared/types/ActionButtonAction'; import type { GridRow } from 'app-shared/types/GridRow'; import type { HTMLAutoCompleteValue } from 'app-shared/types/HTMLAutoCompleteValue'; import type { BooleanExpression, StringExpression } from '@studio/components'; +import type { InternalBindingFormat } from '@altinn/ux-editor/utils/dataModelUtils'; type DataModelBindingsForAddress = { address: string; @@ -38,12 +39,12 @@ type DataModelBindingsList = { }; type DataModelBindingsOptionsSimple = { - simpleBinding: string; + simpleBinding: string | InternalBindingFormat; metadata?: string; }; export type DataModelBindingsSimple = { - simpleBinding: string; + simpleBinding: string | InternalBindingFormat; }; type DataModelBindingsForFileUpload = DataModelBindingsSimple | DataModelBindingsList; diff --git a/frontend/packages/shared/src/utils/featureToggleUtils.ts b/frontend/packages/shared/src/utils/featureToggleUtils.ts index df5dfc0aa20..a3c5c22de1f 100644 --- a/frontend/packages/shared/src/utils/featureToggleUtils.ts +++ b/frontend/packages/shared/src/utils/featureToggleUtils.ts @@ -8,7 +8,6 @@ export enum FeatureFlag { ComponentConfigBeta = 'componentConfigBeta', ExportForm = 'exportForm', Maskinporten = 'maskinporten', - MultipleDataModelsPerTask = 'multipleDataModelsPerTask', OptionListEditor = 'optionListEditor', AccessPackages = 'accessPackages', ShouldOverrideAppLibCheck = 'shouldOverrideAppLibCheck', diff --git a/frontend/packages/ux-editor/src/components/Properties/DataModelBindings.test.tsx b/frontend/packages/ux-editor/src/components/Properties/DataModelBindings.test.tsx index fb1c2d4373d..57d4ade443d 100644 --- a/frontend/packages/ux-editor/src/components/Properties/DataModelBindings.test.tsx +++ b/frontend/packages/ux-editor/src/components/Properties/DataModelBindings.test.tsx @@ -17,7 +17,7 @@ import { layoutSet1NameMock } from '@altinn/ux-editor/testing/layoutSetsMock'; import { app, org } from '@studio/testing/testids'; import type { DataModelMetadataResponse } from 'app-shared/types/api'; -const defaultModel = 'testModel'; +const defaultModel = 'testModelField'; const defaultDataModel = 'testModel'; const secondDataModel = 'secondDataModel'; diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.test.tsx index 98b5ff43d95..65f37d51b68 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.test.tsx @@ -8,7 +8,6 @@ import { ComponentType } from 'app-shared/types/ComponentType'; import type { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import { screen, waitForElementToBeRemoved } from '@testing-library/react'; import { textMock } from '@studio/testing/mocks/i18nMock'; -import { typedLocalStorage } from '@studio/pure-functions'; import userEvent from '@testing-library/user-event'; import type { InternalBindingFormat } from '@altinn/ux-editor/utils/dataModelUtils'; import { layoutSet1NameMock } from '../../../../../testing/layoutSetsMock'; @@ -18,6 +17,7 @@ import { app, org } from '@studio/testing/testids'; const defaultLabel = 'label'; const defaultBindingKey = 'simpleBinding'; const defaultDataModelField = 'field1'; +const secondDataModelField = 'field2'; const defaultDataModel = 'defaultModel'; const secondDataModel = 'secondModel'; @@ -43,9 +43,10 @@ const MockedParentComponent = (props: MockedParentComponentProps) => { { + const fieldBinding = formItem.dataModelBindings[defaultBindingKey] as InternalBindingFormat; setNewInternalBindingFormat((prev) => ({ ...prev, - field: formItem.dataModelBindings[defaultBindingKey], + field: fieldBinding.field, })); }} internalBindingFormat={newInternalBindingFormat} @@ -97,7 +98,7 @@ const getDataModelMetadataMock = jest .fn() .mockImplementation(() => Promise.resolve(dataModelMetadataResponseMock)); -describe('EditBinding without featureFlag', () => { +describe('EditBinding', () => { it('should render loading spinner', async () => { renderEditBinding({}); @@ -120,7 +121,7 @@ describe('EditBinding without featureFlag', () => { expect(fieldSet).toBeInTheDocument(); }); - it('should render correct elements in field set', async () => { + it('should display two selectors: data model and a data model field', async () => { renderEditBinding({ queries: { getAppMetadataModelIds: getAppMetadataModelIdsMock, @@ -132,18 +133,15 @@ describe('EditBinding without featureFlag', () => { screen.queryByTitle(textMock('ux_editor.modal_properties_loading')), ); - const label = screen.getByText(defaultEditBinding.label); - expect(label).toBeInTheDocument(); - - const selectedModel = screen.getByText(defaultDataModel); - const noneExistingDataModelSelector = screen.queryByRole('combobox', { + const dataModelSelector = screen.getByRole('combobox', { name: textMock('ux_editor.modal_properties_data_model_binding'), }); - expect(selectedModel).toBeInTheDocument(); - expect(noneExistingDataModelSelector).not.toBeInTheDocument(); + expect(dataModelSelector).toBeInTheDocument(); - const selectedField = screen.getByRole('combobox'); - expect(selectedField).toBeInTheDocument(); + const dataModelFieldSelector = screen.getByRole('combobox', { + name: textMock('ux_editor.modal_properties_data_model_field_binding'), + }); + expect(dataModelFieldSelector).toBeInTheDocument(); }); it('should display default data model and "choose datafield" when no bindings', async () => { @@ -165,7 +163,10 @@ describe('EditBinding without featureFlag', () => { screen.queryByTitle(textMock('ux_editor.modal_properties_loading')), ); - expect(screen.getByText(defaultDataModel)).toBeInTheDocument(); + const dataModelSelector = screen.getByRole('combobox', { + name: textMock('ux_editor.modal_properties_data_model_binding'), + }); + expect(dataModelSelector).toHaveValue(defaultDataModel); const chooseDataFieldOption: HTMLOptionElement = screen.getByRole('option', { name: textMock('ux_editor.modal_properties_data_model_field_choose'), @@ -226,14 +227,15 @@ describe('EditBinding without featureFlag', () => { ); expect(errorMessage).toBeInTheDocument(); - const dataModelFieldSelector = screen.getByRole('combobox'); - const option2 = screen.getByRole('option', { name: defaultDataModelField }); + const dataModelFieldSelector = screen.getByRole('combobox', { + name: textMock('ux_editor.modal_properties_data_model_field_binding'), + }); + const option2 = screen.getByRole('option', { name: secondDataModelField }); await user.selectOptions(dataModelFieldSelector, option2); - expect(errorMessage).not.toBeInTheDocument(); }); - it('should call handleComponentChange with old binding format when data model field is changed', async () => { + it('should call handleComponentChange with new binding format when data model field is changed', async () => { const user = userEvent.setup(); const handleComponentChange = jest.fn(); renderEditBinding({ @@ -251,7 +253,9 @@ describe('EditBinding without featureFlag', () => { screen.queryByTitle(textMock('ux_editor.modal_properties_loading')), ); - const dataModelFieldSelector = screen.getByRole('combobox'); + const dataModelFieldSelector = screen.getByRole('combobox', { + name: textMock('ux_editor.modal_properties_data_model_field_binding'), + }); const option2 = screen.getByRole('option', { name: 'field2' }); await user.selectOptions(dataModelFieldSelector, option2); @@ -260,7 +264,10 @@ describe('EditBinding without featureFlag', () => { { ...componentMocks[ComponentType.Input], dataModelBindings: { - [defaultEditBinding.bindingKey]: 'field2', + [defaultEditBinding.bindingKey]: { + field: 'field2', + dataType: defaultDataModel, + }, }, maxCount: undefined, required: true, @@ -272,8 +279,7 @@ describe('EditBinding without featureFlag', () => { ); }); - it('should set the data model binding to the default value when click on delete button', async () => { - window.confirm = jest.fn(() => true); + it('should call handleComponentChange with new binding format when data model is changed', async () => { const user = userEvent.setup(); const handleComponentChange = jest.fn(); renderEditBinding({ @@ -291,17 +297,21 @@ describe('EditBinding without featureFlag', () => { screen.queryByTitle(textMock('ux_editor.modal_properties_loading')), ); - const deleteButton = screen.getByRole('button', { - name: textMock('general.delete'), + const dataModelSelector = screen.getByRole('combobox', { + name: textMock('ux_editor.modal_properties_data_model_binding'), }); - await user.click(deleteButton); + const option2 = screen.getByRole('option', { name: secondDataModel }); + await user.selectOptions(dataModelSelector, option2); expect(handleComponentChange).toHaveBeenCalledTimes(1); expect(handleComponentChange).toHaveBeenCalledWith( { ...componentMocks[ComponentType.Input], dataModelBindings: { - simpleBinding: '', + [defaultEditBinding.bindingKey]: { + field: '', + dataType: secondDataModel, + }, }, maxCount: undefined, required: undefined, @@ -313,14 +323,13 @@ describe('EditBinding without featureFlag', () => { ); }); - it('should delete the data model binding when click on delete button and no default value is defined', async () => { + it('should call handleComponentChange when click on delete button', async () => { window.confirm = jest.fn(() => true); const user = userEvent.setup(); const handleComponentChange = jest.fn(); renderEditBinding({ editBindingProps: { ...defaultEditBinding, - component: componentMocks[ComponentType.FileUpload], handleComponentChange, }, queries: { @@ -338,120 +347,12 @@ describe('EditBinding without featureFlag', () => { }); await user.click(deleteButton); - expect(handleComponentChange).toHaveBeenCalledTimes(1); - expect(handleComponentChange).toHaveBeenCalledWith(componentMocks[ComponentType.FileUpload], { - onSuccess: expect.any(Function), - }); - }); -}); - -describe('EditBinding with featureFlag', () => { - beforeEach(() => { - typedLocalStorage.removeItem('featureFlags'); - }); - it('should display two selectors: data model and a data model field, when the feature flag is enabled', async () => { - typedLocalStorage.setItem('featureFlags', ['multipleDataModelsPerTask']); - renderEditBinding({ - queries: { - getAppMetadataModelIds: getAppMetadataModelIdsMock, - getDataModelMetadata: getDataModelMetadataMock, - }, - }); - - await waitForElementToBeRemoved(() => - screen.queryByTitle(textMock('ux_editor.modal_properties_loading')), - ); - - const dataModelSelector = screen.getByRole('combobox', { - name: textMock('ux_editor.modal_properties_data_model_binding'), - }); - expect(dataModelSelector).toBeInTheDocument(); - - const dataModelFieldSelector = screen.getByRole('combobox', { - name: textMock('ux_editor.modal_properties_data_model_field_binding'), - }); - expect(dataModelFieldSelector).toBeInTheDocument(); - }); - - it('should call handleComponentChange with new binding format when data model field is changed', async () => { - typedLocalStorage.setItem('featureFlags', ['multipleDataModelsPerTask']); - const user = userEvent.setup(); - const handleComponentChange = jest.fn(); - renderEditBinding({ - editBindingProps: { - ...defaultEditBinding, - handleComponentChange, - }, - queries: { - getAppMetadataModelIds: getAppMetadataModelIdsMock, - getDataModelMetadata: getDataModelMetadataMock, - }, - }); - - await waitForElementToBeRemoved(() => - screen.queryByTitle(textMock('ux_editor.modal_properties_loading')), - ); - - const dataModelFieldSelector = screen.getByRole('combobox', { - name: textMock('ux_editor.modal_properties_data_model_field_binding'), - }); - const option2 = screen.getByRole('option', { name: 'field2' }); - await user.selectOptions(dataModelFieldSelector, option2); - - expect(handleComponentChange).toHaveBeenCalledTimes(1); - expect(handleComponentChange).toHaveBeenCalledWith( - { - ...componentMocks[ComponentType.Input], - dataModelBindings: { - [defaultEditBinding.bindingKey]: { - field: 'field2', - dataType: defaultDataModel, - }, - }, - maxCount: undefined, - required: true, - timeStamp: undefined, - }, - { - onSuccess: expect.any(Function), - }, - ); - }); - - it('should call handleComponentChange with new binding format when data model is changed', async () => { - typedLocalStorage.setItem('featureFlags', ['multipleDataModelsPerTask']); - const user = userEvent.setup(); - const handleComponentChange = jest.fn(); - renderEditBinding({ - editBindingProps: { - ...defaultEditBinding, - handleComponentChange, - }, - queries: { - getAppMetadataModelIds: getAppMetadataModelIdsMock, - getDataModelMetadata: getDataModelMetadataMock, - }, - }); - - await waitForElementToBeRemoved(() => - screen.queryByTitle(textMock('ux_editor.modal_properties_loading')), - ); - - const dataModelSelector = screen.getByRole('combobox', { - name: textMock('ux_editor.modal_properties_data_model_binding'), - }); - const option2 = screen.getByRole('option', { name: secondDataModel }); - await user.selectOptions(dataModelSelector, option2); - expect(handleComponentChange).toHaveBeenCalledTimes(1); expect(handleComponentChange).toHaveBeenCalledWith( { ...componentMocks[ComponentType.Input], dataModelBindings: { - [defaultEditBinding.bindingKey]: { - field: '', - dataType: secondDataModel, - }, + simpleBinding: '', }, maxCount: undefined, required: undefined, diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.tsx index 2c88efc3155..8af8ed9cefd 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/EditBinding.tsx @@ -10,7 +10,6 @@ import { getXsdDataTypeFromDataModelFields, type InternalBindingFormat, } from '@altinn/ux-editor/utils/dataModelUtils'; -import { shouldDisplayFeature, FeatureFlag } from 'app-shared/utils/featureToggleUtils'; import { useAppContext } from '@altinn/ux-editor/hooks'; import type { UpdateFormMutateOptions } from '@altinn/ux-editor/containers/FormItemContext'; import { EditBindingButtons } from './EditBindingButtons'; @@ -48,9 +47,7 @@ export const EditBinding = ({ const selectedDataFieldElement = updatedBinding?.field; const value = - (shouldDisplayFeature(FeatureFlag.MultipleDataModelsPerTask) - ? updatedBinding - : selectedDataFieldElement) ?? + updatedBinding ?? formItemConfigs[component.type]?.defaultProperties?.['dataModelBindings']?.[bindingKey]; const dataModelBindings = { ...component.dataModelBindings }; diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/SelectDataModelBinding.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/SelectDataModelBinding.tsx index 379cca53608..4888002b749 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/SelectDataModelBinding.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditBinding/SelectDataModelBinding.tsx @@ -1,8 +1,7 @@ import React, { useId } from 'react'; import classes from './SelectDataModelBinding.module.css'; import { FormField } from 'app-shared/components/FormField'; -import { shouldDisplayFeature, FeatureFlag } from 'app-shared/utils/featureToggleUtils'; -import { StudioDisplayTile, StudioNativeSelect } from '@studio/components'; +import { StudioNativeSelect } from '@studio/components'; import { useTranslation } from 'react-i18next'; import type { InternalBindingFormat } from '@altinn/ux-editor/utils/dataModelUtils'; import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams'; @@ -41,7 +40,7 @@ export const SelectDataModelBinding = ({ handleBindingChange(dataModelBinding); }; - return shouldDisplayFeature(FeatureFlag.MultipleDataModelsPerTask) ? ( + return ( )} /> - ) : ( - ); }; diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditDataModelBinding.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditDataModelBinding.test.tsx index 97f849eb6c1..dea076c407a 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditDataModelBinding.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBinding/EditDataModelBinding.test.tsx @@ -62,7 +62,9 @@ describe('EditDataModelBinding', () => { await user.click(bindingButton); expect(bindingButton).not.toBeInTheDocument(); - const dataModelFieldSelector = screen.getByRole('combobox'); + const dataModelFieldSelector = screen.getByRole('combobox', { + name: textMock('ux_editor.modal_properties_data_model_field_binding'), + }); expect(dataModelFieldSelector).toBeInTheDocument(); }; diff --git a/frontend/packages/ux-editor/src/utils/component.ts b/frontend/packages/ux-editor/src/utils/component.ts index 2903ad55525..d7d7a35b1a3 100644 --- a/frontend/packages/ux-editor/src/utils/component.ts +++ b/frontend/packages/ux-editor/src/utils/component.ts @@ -141,10 +141,9 @@ export const generateFormItem = ( type: T, id: string, ): FormItem => { - const { defaultProperties, itemType } = formItemConfigs[type]; - const componentType = formItemConfigs[type].componentRef - ? formItemConfigs[type].componentRef - : type; + const { defaultProperties, itemType, componentRef } = formItemConfigs[type]; + const componentType = componentRef ? componentRef : type; + return { ...defaultProperties, id, type: componentType, itemType } as FormItem; }; diff --git a/frontend/testing/playwright/tests/ui-editor/ui-editor-data-model-binding-and-gitea.spec.ts b/frontend/testing/playwright/tests/ui-editor/ui-editor-data-model-binding-and-gitea.spec.ts index 82867f39665..2867a778b8c 100644 --- a/frontend/testing/playwright/tests/ui-editor/ui-editor-data-model-binding-and-gitea.spec.ts +++ b/frontend/testing/playwright/tests/ui-editor/ui-editor-data-model-binding-and-gitea.spec.ts @@ -153,7 +153,7 @@ test('That it is possible to navigate to data model page and create another data page, testAppName, }): Promise => { - await setupAndVerifyUiEditorPage(page, testAppName, ['multipleDataModelsPerTask']); + await setupAndVerifyUiEditorPage(page, testAppName); const header = new Header(page, { app: testAppName }); const dataModelPage = new DataModelPage(page, { app: testAppName }); @@ -165,9 +165,7 @@ test('That it is possible to navigate back to ui-editor page and add the newly a page, testAppName, }): Promise => { - const uiEditorPage = await setupAndVerifyUiEditorPage(page, testAppName, [ - 'multipleDataModelsPerTask', - ]); + const uiEditorPage = await setupAndVerifyUiEditorPage(page, testAppName); const header = new Header(page, { app: testAppName }); await header.clickOnNavigateToPageInTopMenuHeader('create');