Skip to content

Commit

Permalink
Add tests for the new implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ErlingHauan committed Oct 30, 2024
1 parent 7d91d16 commit 9157cdd
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 110 deletions.
2 changes: 2 additions & 0 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -1629,7 +1629,9 @@
"ux_editor.options.codelist_upload_info.step3": "Filen må ligge i mappen \"App/options\". Sørg for at den blir plassert der ved å oppgi denne stien i opplastingsfeltet. Når du skriver \"App/options/\", blir feltet automatisk oppdatert med mappesti.",
"ux_editor.options.codelist_upload_info.step4": "Velg \"Commit endringer\".",
"ux_editor.options.codelist_upload_info.step5": "Du er nå ferdig i Gitea for denne gang. Gå tilbake til Altinn Studio-fanen, eller klikk på Altinn-logoen øverst til venstre i Gitea for å komme tilbake til Altinn Studio.",
"ux_editor.options.multiple": "{{value}} alternativer",
"ux_editor.options.section_heading": "Valg for kodelister",
"ux_editor.options.single": "{{value}} alternativ",
"ux_editor.options.tab_codelist": "Velg kodeliste",
"ux_editor.options.tab_manual": "Sett opp egne alternativer",
"ux_editor.options.tab_referenceId": "Angi referanse-ID",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const Text = () => {
editFormId={formId}
layoutName={selectedFormLayoutName}
renderOptions={{
onlyCodeListOptions: schema.properties.optionsId && !schema.properties.options,
isLayoutOptionsUnsupported: schema.properties.optionsId && !schema.properties.options,
}}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import type { Option } from 'app-shared/types/Option';
import { useTranslation } from 'react-i18next';

export type EditManualOptionsProps = {
onlyCodeListOptions?: boolean;
isLayoutOptionsUnsupported?: boolean;
} & Pick<IGenericEditComponent<SelectionComponentType>, 'component' | 'handleComponentChange'>;

export function EditManualOptions({
component,
handleComponentChange,
onlyCodeListOptions,
isLayoutOptionsUnsupported,
}: EditManualOptionsProps) {
const { t } = useTranslation();

Expand Down Expand Up @@ -55,7 +55,7 @@ export function EditManualOptions({
handleComponentChange(addOptionToComponent(component, generateRandomOption()));
};

if (onlyCodeListOptions) {
if (isLayoutOptionsUnsupported) {
return <Alert severity='info'>{t('ux_editor.options.codelist_only')}</Alert>;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { screen, waitFor } from '@testing-library/react';
import { EditManualOptionsWithEditor } from './EditManualOptionsWithEditor';
import { renderWithProviders } from '../../../../../testing/mocks';
import { textMock } from '@studio/testing/mocks/i18nMock';
Expand All @@ -20,15 +20,17 @@ const mockComponent: FormComponent<ComponentType.RadioButtons> = {
dataModelBindings: { simpleBinding: '' },
};

const renderEditManualOptions = async <
const renderEditManualOptionsWithEditor = <
T extends ComponentType.Checkboxes | ComponentType.RadioButtons,
>({
componentProps,
handleComponentChange = jest.fn(),
isLayoutOptionsUnsupported = false,
}: {
componentProps?: Partial<FormItem<T>>;
handleComponentChange?: () => void;
queries?: Partial<ServicesContextProps>;
isLayoutOptionsUnsupported?: boolean;
} = {}) => {
const component = {
...mockComponent,
Expand All @@ -38,57 +40,62 @@ const renderEditManualOptions = async <
<EditManualOptionsWithEditor
handleComponentChange={handleComponentChange}
component={component}
isLayoutOptionsUnsupported={isLayoutOptionsUnsupported}
/>,
);
};

describe('EditManualOptions', () => {
it('should show manual input when component has options defined', async () => {
renderEditManualOptions({
componentProps: {
options: [{ label: 'option1', value: 'option1' }],
},
describe('EditManualOptionsWithEditor', () => {
it('should display a button when no code list is defined in the layout', () => {
renderEditManualOptionsWithEditor();

const modalButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_properties_code_list_custom_list'),
});
screen.getByRole('button', { name: textMock('ux_editor.modal_new_option') });
screen.getByRole('button', { name: textMock('ux_editor.radios_option', { optionNumber: 1 }) });

expect(modalButton).toBeInTheDocument();
});

it('should show manual input when options list has length 0', async () => {
renderEditManualOptions({
it('should display a button when a code list is defined in the layout', () => {
renderEditManualOptionsWithEditor({
componentProps: {
options: [],
options: [{ label: 'option1', value: 'option1' }],
},
});
screen.getByRole('button', { name: textMock('ux_editor.modal_new_option') });

const modalButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_properties_code_list_custom_list'),
});

expect(modalButton).toBeInTheDocument();
});

it('should not display how many options have been defined, when no options are defined', () => {
renderEditManualOptionsWithEditor();

const optionText = screen.queryByText(textMock('ux_editor.options.single', { value: 1 }));
const optionsText = screen.queryByText(textMock('ux_editor.options.multiple', { value: 2 }));

expect(optionText).not.toBeInTheDocument();
expect(optionsText).not.toBeInTheDocument();
});

it('should call handleComponentUpdate when adding a new option', async () => {
const handleComponentChangeMock = jest.fn();
renderEditManualOptions({
handleComponentChange: handleComponentChangeMock,
it('should display how many options have been defined, when a single option is defined', () => {
renderEditManualOptionsWithEditor({
componentProps: {
options: [{ label: 'oldOption', value: 'oldOption' }],
options: [{ label: 'option1', value: 'option1' }],
},
});

const addOptionButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_new_option'),
});
addOptionButton.click();
expect(handleComponentChangeMock).toHaveBeenCalledWith({
...mockComponent,
options: [
{ label: 'oldOption', value: 'oldOption' },
{ label: expect.any(String), value: expect.any(String) },
],
});
const optionText = screen.getByText(textMock('ux_editor.options.single', { value: 1 }));
const optionsText = screen.queryByText(textMock('ux_editor.options.multiple', { value: 2 }));

expect(optionText).toBeInTheDocument();
expect(optionsText).not.toBeInTheDocument();
});

it('should call handleComponentUpdate when removing an option', async () => {
const user = userEvent.setup();
const handleComponentChangeMock = jest.fn();
renderEditManualOptions({
handleComponentChange: handleComponentChangeMock,
it('should display how many options have been defined, when multiple options are defined', () => {
renderEditManualOptionsWithEditor({
componentProps: {
options: [
{ label: 'option1', value: 'option1' },
Expand All @@ -97,79 +104,54 @@ describe('EditManualOptions', () => {
},
});

const selectOptionButton = screen.getByRole('button', {
name: textMock('ux_editor.radios_option', { optionNumber: 2 }),
});
await user.click(selectOptionButton);
const removeOptionButton = screen.getByRole('button', {
name: textMock('general.delete'),
});
await user.click(removeOptionButton);
expect(handleComponentChangeMock).toHaveBeenCalledWith({
...mockComponent,
options: [{ label: 'option1', value: 'option1' }],
});
const optionText = screen.queryByText(textMock('ux_editor.options.single', { value: 1 }));
const optionsText = screen.getByText(textMock('ux_editor.options.multiple', { value: 2 }));

expect(optionText).not.toBeInTheDocument();
expect(optionsText).toBeInTheDocument();
});

it('should handle adding new option even if options property has not been set', async () => {
const handleComponentChangeMock = jest.fn();
renderEditManualOptions({
handleComponentChange: handleComponentChangeMock,
componentProps: {
options: undefined,
},
});
it('should open a modal when the trigger button is clicked', async () => {
const user = userEvent.setup();
renderEditManualOptionsWithEditor();

const addOptionButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_new_option'),
});
addOptionButton.click();
expect(handleComponentChangeMock).toHaveBeenCalledWith({
...mockComponent,
options: [{ label: expect.any(String), value: expect.any(String) }],
const modalButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_properties_code_list_custom_list'),
});
});

it('should delete optionsId property if it exists when adding a new option', async () => {
const handleComponentChangeMock = jest.fn();
renderEditManualOptions({
handleComponentChange: handleComponentChangeMock,
componentProps: {
optionsId: 'testId',
},
});
await user.click(modalButton);

const addOptionButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_new_option'),
});
addOptionButton.click();
expect(handleComponentChangeMock).toHaveBeenCalledWith({
...mockComponent,
options: [{ label: expect.any(String), value: expect.any(String) }],
});
const modalDialog = screen.getByRole('dialog');

expect(modalDialog).toBeInTheDocument();
});

it('should call handleComponentUpdate when changing an option', async () => {
it('should call handleComponentChange when there has been a change in the editor', async () => {
const mockHandleComponentChange = jest.fn();
const user = userEvent.setup();
const handleComponentChangeMock = jest.fn();
renderEditManualOptions({
handleComponentChange: handleComponentChangeMock,
componentProps: {
options: [{ label: 'option1', value: 'option1' }],
},
});
renderEditManualOptionsWithEditor({ handleComponentChange: mockHandleComponentChange });

const selectOptionButton = screen.getByRole('button', {
name: textMock('ux_editor.radios_option', { optionNumber: 1 }),
const modalButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_properties_code_list_custom_list'),
});
await user.click(selectOptionButton);
const textField = screen.getByRole('textbox', {
name: textMock('general.value'),

await user.click(modalButton);

const addNewButton = screen.getByRole('button', {
name: textMock('ux_editor.modal_new_option'),
});
await user.type(textField, 'a');
expect(handleComponentChangeMock).toHaveBeenCalledWith({
...mockComponent,
options: [{ label: 'option1', value: 'option1a' }],

await user.click(addNewButton);
await user.click(addNewButton);

await waitFor(() => {
expect(mockHandleComponentChange).toHaveBeenCalledWith({
...mockComponent,
options: [
{ label: '', value: '' },
{ label: '', value: '' },
],
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { EditManualOptionsProps } from '../EditManualOptions';
export function EditManualOptionsWithEditor({
component,
handleComponentChange,
onlyCodeListOptions,
isLayoutOptionsUnsupported,
}: EditManualOptionsProps) {
const { t } = useTranslation();
const manualOptionsModalRef = useRef<HTMLDialogElement>(null);
Expand All @@ -32,7 +32,7 @@ export function EditManualOptionsWithEditor({
});
};

if (onlyCodeListOptions) {
if (isLayoutOptionsUnsupported) {
return <Alert severity='info'>{t('ux_editor.options.codelist_only')}</Alert>;

Check warning on line 36 in frontend/packages/ux-editor/src/components/config/editModal/EditOptions/EditManualOptionsWithEditor/EditManualOptionsWithEditor.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/packages/ux-editor/src/components/config/editModal/EditOptions/EditManualOptionsWithEditor/EditManualOptionsWithEditor.tsx#L36

Added line #L36 was not covered by tests
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const renderEditOptions = async <T extends ComponentType.Checkboxes | ComponentT
handleComponentChange?: () => void;
queries?: Partial<ServicesContextProps>;
renderOptions?: {
onlyCodeListOptions?: boolean;
isLayoutOptionsUnsupported?: boolean;
};
} = {}) => {
const component = {
Expand Down Expand Up @@ -204,11 +204,11 @@ describe('EditOptions', () => {
).toBeInTheDocument();
});

it('should show alert message in Manual tab when prop onlyCodeListOptions is true', async () => {
it('should show alert message in Manual tab when prop isLayoutOptionsUnsupported is true', async () => {
const user = userEvent.setup();
await renderEditOptions({
componentProps: { optionsId: '' },
renderOptions: { onlyCodeListOptions: true },
renderOptions: { isLayoutOptionsUnsupported: true },
queries: {
getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve<string[]>([])),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { EditManualOptionsWithEditor } from '@altinn/ux-editor/components/config
export interface ISelectionEditComponentProvidedProps<T extends SelectionComponentType>
extends IGenericEditComponent<T> {
renderOptions?: {
onlyCodeListOptions?: boolean;
isLayoutOptionsUnsupported?: boolean;
};
}

Expand Down Expand Up @@ -107,13 +107,13 @@ export function EditOptions<T extends SelectionComponentType>({
<EditManualOptionsWithEditor
component={component}
handleComponentChange={handleComponentChange}
onlyCodeListOptions={renderOptions.onlyCodeListOptions}
isLayoutOptionsUnsupported={renderOptions.isLayoutOptionsUnsupported}
/>
) : (
<EditManualOptions
component={component}
handleComponentChange={handleComponentChange}
onlyCodeListOptions={renderOptions.onlyCodeListOptions}
isLayoutOptionsUnsupported={renderOptions.isLayoutOptionsUnsupported}
/>
)}
</StudioTabs.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ export const useCodeListButtonValue = (options: Option[] | undefined) => {
const { t } = useTranslation();

if (options?.length > 1) {
return options.length + ' ' + t('general.options').toLowerCase();
return t('ux_editor.options.multiple', { value: options.length });
} else if (options?.length > 0) {
return options.length + ' ' + t('general.option').toLowerCase();
return t('ux_editor.options.single', { value: options.length });
} else {
return undefined;
}
Expand Down

0 comments on commit 9157cdd

Please sign in to comment.