Skip to content

Commit

Permalink
Add handleClose to ManualOptionsEditor to clear options if the user…
Browse files Browse the repository at this point in the history
… does not enter any.
  • Loading branch information
Konrad-Simso committed Jan 8, 2025
1 parent a9c6c59 commit 33a3b93
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { useTranslation } from 'react-i18next';
import { StudioCodeListEditor, StudioModal } from '@studio/components';
import { useForwardedRef } from '@studio/hooks';
import { useOptionListEditorTexts } from '../../../hooks';
import { handleOptionsChange, updateComponentOptions } from '../../../utils/optionsUtils';
import {
handleOptionsChange,
resetComponentOptions,
updateComponentOptions,
} from '../../../utils/optionsUtils';
import { OptionListLabels } from '../OptionListLabels';
import { OptionListButtons } from '../OptionListButtons';
import type { Option } from 'app-shared/types/Option';
Expand All @@ -30,6 +34,13 @@ export const ManualOptionsEditor = forwardRef<HTMLDialogElement, ManualOptionsEd
modalRef.current?.showModal();
};

const handleClose = () => {
if (component.options?.length === 0) {
const updatedComponent = resetComponentOptions(component);
handleOptionsChange(updatedComponent, handleComponentChange);
}
};

return (
<>
<OptionListLabels optionsId={component.optionsId} optionsList={component.options} />
Expand All @@ -39,6 +50,7 @@ export const ManualOptionsEditor = forwardRef<HTMLDialogElement, ManualOptionsEd
className={classes.editOptionTabModal}
contentClassName={classes.content}
closeButtonTitle={t('general.close')}
onBeforeClose={handleClose}
heading={t('ux_editor.options.modal_header_manual_code_list')}
>
<StudioCodeListEditor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { OptionsList } from 'app-shared/types/api/OptionsLists';
import type { Option } from 'app-shared/types/Option';
import { ComponentType } from 'app-shared/types/ComponentType';
import type { OptionListEditorProps } from './OptionListEditor';
import { ObjectUtils } from '@studio/pure-functions';
import { OptionListEditor } from './OptionListEditor';
import { textMock } from '@studio/testing/mocks/i18nMock';
import { renderWithProviders } from '../../../../../../../testing/mocks';
Expand All @@ -24,6 +25,7 @@ const apiResult: OptionsList = [
const getOptionListMock = jest
.fn()
.mockImplementation(() => Promise.resolve<OptionsList>(apiResult));
const componentWithOptionsId = { ...mockComponent, options: undefined, optionsId: 'some-id' };

describe('OptionListEditor', () => {
afterEach(() => jest.clearAllMocks());
Expand All @@ -49,18 +51,34 @@ describe('OptionListEditor', () => {
it('should close Dialog', async () => {
const user = userEvent.setup();
renderOptionListEditor();
await user.click(getOptionModalButton());

expect(screen.getByRole('dialog')).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'close modal' })); // Todo: Replace "close modal" with defaultDialogProps.closeButtonTitle when we upgrade to Designsystemet v1
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});

it('should call handleComponentChange with correct parameters when closing Dialog and options is empty', async () => {
const user = userEvent.setup();
renderOptionListEditor({
props: { component: { ...mockComponent, options: [], optionsId: undefined } },
});
const expectedArgs = ObjectUtils.deepCopy(mockComponent);
expectedArgs.options = undefined;
expectedArgs.optionsId = undefined;

await user.click(getOptionModalButton());
await user.click(screen.getByRole('button', { name: 'close modal' })); // Todo: Replace "close modal" with defaultDialogProps.closeButtonTitle when we upgrade to Designsystemet v1

expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
expect(handleComponentChange).toHaveBeenCalledTimes(1);
expect(handleComponentChange).toHaveBeenCalledWith(expectedArgs);
});

it('should call handleComponentChange when editing', async () => {
it('should call handleComponentChange with correct parameters when editing', async () => {
const user = userEvent.setup();
renderOptionListEditor();
const text = 'test';
const expectedArgs = mockComponent;
const expectedArgs = ObjectUtils.deepCopy(mockComponent);
expectedArgs.optionsId = undefined;
expectedArgs.options[0].description = text;

Expand All @@ -74,16 +92,22 @@ describe('OptionListEditor', () => {
});

it('should show placeholder for option label when option list label is empty', () => {
mockComponent.options = [{ value: 2, label: '', description: 'test', helpText: null }];
renderOptionListEditor();
renderOptionListEditor({
props: {
component: {
...mockComponent,
options: [{ value: 2, label: '', description: 'test', helpText: null }],
},
},
});

expect(screen.getByText(textMock('general.empty_string'))).toBeInTheDocument();
});

it('should call handleComponentChange with correct parameters when removing chosen options', async () => {
const user = userEvent.setup();
renderOptionListEditor();
const expectedResult = mockComponent;
const expectedResult = ObjectUtils.deepCopy(mockComponent);
expectedResult.options = undefined;
expectedResult.optionsId = undefined;

Expand All @@ -101,7 +125,7 @@ describe('OptionListEditor', () => {
queries: {
getOptionList: jest.fn().mockImplementation(() => Promise.resolve<OptionsList>([])),
},
props: { component: { ...mockComponent, options: undefined } },
props: { component: componentWithOptionsId },
});

expect(
Expand All @@ -114,7 +138,6 @@ describe('OptionListEditor', () => {
queries: {
getOptionList: jest.fn().mockImplementation(() => Promise.reject()),
},
props: { component: { ...mockComponent, options: undefined } },
});

expect(
Expand All @@ -123,17 +146,13 @@ describe('OptionListEditor', () => {
});

it('should render the open Dialog button', async () => {
await renderOptionListEditorAndWaitForSpinnerToBeRemoved({
props: { component: { ...mockComponent, options: undefined } },
});
await renderOptionListEditorAndWaitForSpinnerToBeRemoved();
expect(getOptionModalButton()).toBeInTheDocument();
});

it('should open Dialog', async () => {
const user = userEvent.setup();
await renderOptionListEditorAndWaitForSpinnerToBeRemoved({
props: { component: { ...mockComponent, options: undefined } },
});
await renderOptionListEditorAndWaitForSpinnerToBeRemoved();

await user.click(getOptionModalButton());

Expand All @@ -142,13 +161,11 @@ describe('OptionListEditor', () => {

it('should close Dialog', async () => {
const user = userEvent.setup();
await renderOptionListEditorAndWaitForSpinnerToBeRemoved({
props: { component: { ...mockComponent, options: undefined } },
});

await renderOptionListEditorAndWaitForSpinnerToBeRemoved();
await user.click(getOptionModalButton());
await user.click(screen.getByRole('button', { name: 'close modal' })); // Todo: Replace "close modal" with defaultDialogProps.closeButtonTitle when we upgrade to Designsystemet v1

expect(screen.getByRole('dialog')).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'close modal' })); // Todo: Replace "close modal" with defaultDialogProps.closeButtonTitle when we upgrade to Designsystemet v1
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});

Expand All @@ -157,7 +174,6 @@ describe('OptionListEditor', () => {
const doReloadPreview = jest.fn();
await renderOptionListEditorAndWaitForSpinnerToBeRemoved({
previewContextProps: { doReloadPreview },
props: { component: { ...mockComponent, options: undefined } },
});

await user.click(getOptionModalButton());
Expand All @@ -170,9 +186,7 @@ describe('OptionListEditor', () => {

it('should call updateOptionList with correct parameters when closing Dialog', async () => {
const user = userEvent.setup();
await renderOptionListEditorAndWaitForSpinnerToBeRemoved({
props: { component: { ...mockComponent, options: undefined } },
});
await renderOptionListEditorAndWaitForSpinnerToBeRemoved();
const expectedResultAfterEdit: Option[] = [
{ value: 'test', label: 'label text', description: 'description', helpText: 'help text' },
{ value: 2, label: 'label number', description: 'test', helpText: null },
Expand All @@ -188,7 +202,7 @@ describe('OptionListEditor', () => {
expect(queriesMock.updateOptionList).toHaveBeenCalledWith(
org,
app,
mockComponent.optionsId,
componentWithOptionsId.optionsId,
expectedResultAfterEdit,
);
});
Expand Down Expand Up @@ -237,12 +251,12 @@ function getTextBoxInput(number: number) {
});
}

const defaultProps: OptionListEditorProps = {
component: mockComponent,
handleComponentChange,
};

const renderOptionListEditor = ({ previewContextProps = {}, queries = {}, props = {} } = {}) => {
const defaultProps: OptionListEditorProps = {
component: mockComponent,
handleComponentChange,
};

return renderWithProviders(<OptionListEditor {...defaultProps} {...props} />, {
queries: { getOptionList: getOptionListMock, ...queries },
queryClient: createQueryClientMock(),
Expand All @@ -253,7 +267,7 @@ const renderOptionListEditor = ({ previewContextProps = {}, queries = {}, props
const renderOptionListEditorAndWaitForSpinnerToBeRemoved = async ({
previewContextProps = {},
queries = {},
props = {},
props = { component: componentWithOptionsId },
} = {}) => {
const view = renderOptionListEditor({
previewContextProps,
Expand Down

0 comments on commit 33a3b93

Please sign in to comment.