Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Remove featureflag multiple data models per task #14171

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
5 changes: 3 additions & 2 deletions frontend/packages/shared/src/types/ComponentSpecificConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion frontend/packages/shared/src/utils/featureToggleUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export enum FeatureFlag {
ComponentConfigBeta = 'componentConfigBeta',
ExportForm = 'exportForm',
Maskinporten = 'maskinporten',
MultipleDataModelsPerTask = 'multipleDataModelsPerTask',
OptionListEditor = 'optionListEditor',
ResourceMigration = 'resourceMigration',
ShouldOverrideAppLibCheck = 'shouldOverrideAppLibCheck',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { InternalBindingFormat } from '@altinn/ux-editor/utils/dataModelUtils';

type TableColumnCellContent = {
query: string;
query: string | InternalBindingFormat;
default?: string;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';

Expand All @@ -43,9 +43,10 @@ const MockedParentComponent = (props: MockedParentComponentProps) => {
<EditBinding
{...props}
handleComponentChange={(formItem) => {
const fieldBinding = formItem.dataModelBindings[defaultBindingKey] as InternalBindingFormat;
setNewInternalBindingFormat((prev) => ({
...prev,
field: formItem.dataModelBindings[defaultBindingKey],
field: fieldBinding.field,
}));
}}
internalBindingFormat={newInternalBindingFormat}
Expand Down Expand Up @@ -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({});

Expand All @@ -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,
Expand All @@ -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 () => {
Expand All @@ -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'),
Expand Down Expand Up @@ -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({
Expand All @@ -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);

Expand All @@ -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,
Expand All @@ -272,8 +279,7 @@ describe('EditBinding without featureFlag', () => {
);
});

it('should call handleComponentChange 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({
Expand All @@ -291,94 +297,24 @@ describe('EditBinding without featureFlag', () => {
screen.queryByTitle(textMock('ux_editor.modal_properties_loading')),
);

const deleteButton = screen.getByRole('button', {
name: textMock('general.delete'),
});
await user.click(deleteButton);

expect(handleComponentChange).toHaveBeenCalledTimes(1);
expect(handleComponentChange).toHaveBeenCalledWith(
{
...componentMocks[ComponentType.Input],
dataModelBindings: {
simpleBinding: '',
},
maxCount: undefined,
required: undefined,
timeStamp: undefined,
},
{
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<string[]>('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<string[]>('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);
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: 'field2',
dataType: defaultDataModel,
field: '',
dataType: secondDataModel,
},
},
maxCount: undefined,
required: true,
required: undefined,
timeStamp: undefined,
},
{
Expand All @@ -387,8 +323,8 @@ describe('EditBinding with featureFlag', () => {
);
});

it('should call handleComponentChange with new binding format when data model is changed', async () => {
typedLocalStorage.setItem<string[]>('featureFlags', ['multipleDataModelsPerTask']);
it('should call handleComponentChange when click on delete button', async () => {
window.confirm = jest.fn(() => true);
const user = userEvent.setup();
const handleComponentChange = jest.fn();
renderEditBinding({
Expand All @@ -406,20 +342,19 @@ describe('EditBinding with featureFlag', () => {
screen.queryByTitle(textMock('ux_editor.modal_properties_loading')),
);

const dataModelSelector = screen.getByRole('combobox', {
name: textMock('ux_editor.modal_properties_data_model_binding'),
const deleteButton = screen.getByRole('button', {
name: textMock('general.delete'),
});
const option2 = screen.getByRole('option', { name: secondDataModel });
await user.selectOptions(dataModelSelector, option2);
await user.click(deleteButton);

expect(handleComponentChange).toHaveBeenCalledTimes(1);
expect(handleComponentChange).toHaveBeenCalledWith(
{
...componentMocks[ComponentType.Input],
dataModelBindings: {
[defaultEditBinding.bindingKey]: {
simpleBinding: {
dataType: '',
field: '',
dataType: secondDataModel,
},
},
maxCount: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -50,9 +49,7 @@ export const EditBinding = ({
...component,
dataModelBindings: {
...component.dataModelBindings,
[bindingKey]: shouldDisplayFeature(FeatureFlag.MultipleDataModelsPerTask)
? updatedBinding
: selectedDataFieldElement,
[bindingKey]: updatedBinding,
},
required: getMinOccursFromDataModelFields(selectedDataFieldElement, dataModelMetadata),
timeStamp: getXsdDataTypeFromDataModelFields(
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -41,7 +40,7 @@ export const SelectDataModelBinding = ({
handleBindingChange(dataModelBinding);
};

return shouldDisplayFeature(FeatureFlag.MultipleDataModelsPerTask) ? (
return (
<FormField
id={id}
onChange={handleDataModelChange}
Expand Down Expand Up @@ -70,11 +69,5 @@ export const SelectDataModelBinding = ({
</StudioNativeSelect>
)}
/>
) : (
<StudioDisplayTile
label={t('ux_editor.modal_properties_data_model_binding')}
value={selectedDataModel}
className={classes.displayTileContainer}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -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();
};
Expand Down Expand Up @@ -192,7 +194,10 @@ describe('EditDataModelBinding', () => {
expect(handleComponentChange).toHaveBeenCalledWith(
expect.objectContaining({
dataModelBindings: {
simpleBinding: '',
simpleBinding: {
dataType: '',
field: '',
},
},
}),
expect.anything(),
Expand Down
Loading
Loading