Skip to content

Commit

Permalink
Remove headingLevel bugfix components from branch - they belong in a …
Browse files Browse the repository at this point in the history
…different branch
  • Loading branch information
ErlingHauan committed Oct 4, 2024
1 parent df413e9 commit 23da349
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ export const FormComponentConfig = ({
propertyKey={propertyKey}
key={propertyKey}
helpText={properties[propertyKey]?.description}
enumValues={properties[propertyKey]?.enum}
/>
);
})}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { screen, waitFor } from '@testing-library/react';

import { EditNumberValue } from './EditNumberValue';
import { renderWithProviders, renderHookWithProviders } from '../../../testing/mocks';
import { useLayoutSchemaQuery } from '../../../hooks/queries/useLayoutSchemaQuery';
Expand All @@ -14,18 +15,13 @@ const waitForData = async () => {
await waitFor(() => expect(layoutSchemaResult.current[0].isSuccess).toBe(true));
};

const renderEditNumberValue = async ({
enumValues = null,
maxLength = undefined,
handleComponentChange = jest.fn(),
} = {}) => {
const render = async ({ maxLength = undefined, handleComponentChange = jest.fn() } = {}) => {
await waitForData();

return renderWithProviders(
<EditNumberValue
handleComponentChange={handleComponentChange}
propertyKey='maxLength'
enumValues={enumValues}
component={{
id: 'c24d0812-0c34-4582-8f31-ff4ce9795e96',
type: ComponentType.Input,
Expand All @@ -41,69 +37,11 @@ const renderEditNumberValue = async ({
};

describe('EditNumberValue', () => {
afterEach(() => {
jest.resetAllMocks();
});

it('should render component as input field, when not given enum prop', async () => {
await renderEditNumberValue();

expect(
screen.getByRole('textbox', { name: textMock('ux_editor.component_properties.maxLength') }),
).toBeInTheDocument();
expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
});

it('should render component as select, when given enum prop', async () => {
await renderEditNumberValue({ enumValues: [1, 2, 3] });

it('should render', async () => {
await render();
expect(
screen.getByRole('combobox', { name: textMock('ux_editor.component_properties.maxLength') }),
screen.getByText(textMock('ux_editor.component_properties.maxLength')),
).toBeInTheDocument();
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
});

it('should call onChange when typing in input field', async () => {
const user = userEvent.setup();
const mockHandleComponentChange = jest.fn((componentProperties, _) => componentProperties);
await renderEditNumberValue({
handleComponentChange: mockHandleComponentChange,
});

await user.type(screen.getByRole('textbox'), '2');

expect(mockHandleComponentChange).toHaveReturnedWith({
id: 'c24d0812-0c34-4582-8f31-ff4ce9795e96',
type: ComponentType.Input,
textResourceBindings: {
title: 'ServiceName',
},
maxLength: 2,
itemType: 'COMPONENT',
dataModelBindings: { simpleBinding: 'some-path' },
});
});

it('should call onChange when choosing option from select', async () => {
const user = userEvent.setup();
const mockHandleComponentChange = jest.fn((componentProperties, _) => componentProperties);
await renderEditNumberValue({
handleComponentChange: mockHandleComponentChange,
enumValues: [1, 2, 3],
});

await user.selectOptions(screen.getByRole('combobox'), '1');

expect(mockHandleComponentChange).toHaveReturnedWith({
id: 'c24d0812-0c34-4582-8f31-ff4ce9795e96',
type: ComponentType.Input,
textResourceBindings: {
title: 'ServiceName',
},
maxLength: 1,
itemType: 'COMPONENT',
dataModelBindings: { simpleBinding: 'some-path' },
});
});

it('should save to backend and reload the preview when changing value, including the case of changing it to undefined/empty', async () => {
Expand All @@ -113,24 +51,25 @@ describe('EditNumberValue', () => {
mutationFn: () => Promise.resolve(),
}),
).result;
const mockHandleComponentChange = jest

const mockhHandleComponentChange = jest
.fn()
.mockImplementation(async (mutationArgs, mutateOptions) => {
await handleSaveMutation.current.mutateAsync(mutationArgs, mutateOptions);
});

await renderEditNumberValue({ handleComponentChange: mockHandleComponentChange });
await render({ handleComponentChange: mockhHandleComponentChange });

const input = screen.getByRole('textbox');
await user.type(input, '12');
// The component is updated for each keystroke, so we expect the mock to be called twice -
// I think it should prevent this behavior with this new issue: https://github.com/Altinn/altinn-studio/issues/11989
expect(mockHandleComponentChange).toHaveBeenCalledTimes(2);
expect(mockhHandleComponentChange).toHaveBeenCalledTimes(2);
expect(appContextMock.refetchLayouts).toHaveBeenCalledTimes(2);
expect(appContextMock.refetchLayouts).toHaveBeenCalledWith('test-layout-set', true);

mockHandleComponentChange.mockClear();
mockhHandleComponentChange.mockClear();
await user.clear(input);
expect(mockHandleComponentChange).toHaveBeenCalledTimes(1);
expect(mockhHandleComponentChange).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import type { IGenericEditComponent } from '../componentConfig';
import { FormField } from '../../FormField';
import { setComponentProperty } from '@altinn/ux-editor/utils/component';
import { StudioDecimalInput, StudioNativeSelect } from '@studio/components';
import { setComponentProperty } from '../../../utils/component';
import { StudioDecimalInput } from '@studio/components';
import type { ComponentType } from 'app-shared/types/ComponentType';
import type { FormItem } from '../../../types/FormItem';
import type { FilterKeysOfType } from 'app-shared/types/FilterKeysOfType';
Expand All @@ -16,20 +16,17 @@ export interface EditNumberValueProps<T extends ComponentType, K extends NumberK
extends IGenericEditComponent<T> {
propertyKey: K;
helpText?: string;
enumValues?: number[];
}

export const EditNumberValue = <T extends ComponentType, K extends NumberKeys<FormItem<T>>>({
component,
handleComponentChange,
propertyKey,
helpText,
enumValues,
}: EditNumberValueProps<T, K>) => {
const { t } = useTranslation();
const componentPropertyLabel = useComponentPropertyLabel();
const { selectedFormLayoutSetName, refetchLayouts } = useAppContext();

const handleValueChange = async (newValue: number) => {
handleComponentChange(setComponentProperty<T, number, K>(component, propertyKey, newValue), {
onSuccess: async () => {
Expand All @@ -41,35 +38,18 @@ export const EditNumberValue = <T extends ComponentType, K extends NumberKeys<Fo
return (
<FormField
id={component.id}
label={componentPropertyLabel(String(propertyKey))}
value={component[propertyKey]}
onChange={handleValueChange}
propertyPath={component.propertyPath}
helpText={helpText}
renderField={({ fieldProps }) =>
enumValues ? (
<StudioNativeSelect
label={fieldProps.label}
value={fieldProps.value}
onChange={(e) => fieldProps.onChange(Number(e.target.value))}
id={`component-${String(propertyKey)}-select${component.id}`}
size='sm'
>
{enumValues.map((value: number) => (
<option key={value} value={value}>
{value}
</option>
))}
</StudioNativeSelect>
) : (
<StudioDecimalInput
{...fieldProps}
onChange={fieldProps.onChange}
description={componentPropertyLabel(propertyKey as string)}
validationErrorMessage={t('validation_errors.numbers_only')}
/>
)
}
renderField={({ fieldProps }) => (
<StudioDecimalInput
{...fieldProps}
onChange={fieldProps.onChange}
description={componentPropertyLabel(propertyKey as string)}
validationErrorMessage={t('validation_errors.numbers_only')}
/>
)}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,12 @@ const renderEditStringValue = ({
);

describe('EditStringValue', () => {
it('should render component as input field, when not given enum prop', () => {
renderEditStringValue();

expect(
screen.getByRole('textbox', { name: textMock('ux_editor.component_properties.maxLength') }),
).toBeInTheDocument();
expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
});

it('should render component as select, when given enum prop', () => {
renderEditStringValue({ enumValues: ['one', 'two', 'three'] });

expect(
screen.getByRole('combobox', { name: textMock('ux_editor.component_properties.maxLength') }),
).toBeInTheDocument();
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
it('should render', () => {
const handleComponentChange = jest.fn();
renderEditStringValue({ handleComponentChange });
});

it('should call onChange handler with the correct arguments', async () => {
it(' Ensure that the onChange handler is called with the correct arguments', async () => {
const handleComponentChange = jest.fn();
renderEditStringValue({ handleComponentChange });
const inputElement = screen.getByLabelText(
Expand Down Expand Up @@ -103,6 +90,7 @@ describe('EditStringValue', () => {
);

await waitFor(() => {
//await user.selectOptions(screen.getByRole('listbox'), screen.getByRole('option', { name: "one" }));
expect(handleComponentChange).toHaveBeenCalledWith({
id: 'c24d0812-0c34-4582-8f31-ff4ce9795e96',
type: ComponentType.Input,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const EditStringValue = ({
<StudioNativeSelect
label={fieldProps.label}
value={fieldProps.value}
onChange={(e) => fieldProps.onChange(e.target.value)}
onChange={(e: any) => fieldProps.onChange(e.target.value)}
id={`component-${propertyKey}-select${component.id}`}
size='sm'
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"title": "Heading level",
"description": "The heading level of the group title.",
"enum": [2, 3, 4, 5, 6],
"type": "number"
"type": "string"
}
},
"required": ["id", "type", "children"],
Expand Down
7 changes: 2 additions & 5 deletions frontend/packages/ux-editor/src/utils/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,8 @@ export const propertyTypeMatcher = (property: KeyValuePairs, propertyType: Prope

switch (propertyType) {
case PropertyTypes.string:
// Not all schemas with enum value explicitly specify type as string
return baseMatch || (!!property.enum && typeof property.enum[0] === 'string');
case PropertyTypes.number:
// Not all schemas with enum value explicitly specify type as number
return baseMatch || (!!property.enum && typeof property.enum[0] === 'number');
// Not all schemas with enum value explicitly specifies type as string
return baseMatch || !!property.enum;
case PropertyTypes.array:
// Currently only supporting array of strings with specified enum values
return baseMatch && !!property.items?.enum;
Expand Down

0 comments on commit 23da349

Please sign in to comment.