Skip to content

Commit

Permalink
Added warning background to id-component in Properties. (#13067)
Browse files Browse the repository at this point in the history
* added warning backgrund to duplicated id-component in Properties.
  • Loading branch information
JamalAlabdullah authored Jul 5, 2024
1 parent a3ac45a commit 81e5f6a
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { formItemContextProviderMock } from '../../testing/formItemContextMocks'
import { renderWithProviders } from '../../testing/mocks';
import { componentMocks } from '../../testing/componentMocks';
import { ComponentType } from 'app-shared/types/ComponentType';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { QueryKey } from 'app-shared/types/QueryKey';
import { app, org } from '@studio/testing/testids';
import { layoutSet1NameMock } from '@altinn/ux-editor/testing/layoutSetsMock';
import { layout1NameMock, layoutMock } from '@altinn/ux-editor/testing/layoutMock';
import type { IFormLayouts } from '@altinn/ux-editor/types/global';

// Test data:
const pageConfigPanelTestId = 'pageConfigPanel';
Expand All @@ -18,6 +24,11 @@ const conditionalRenderingTestId = 'conditionalRendering';
const expressionsTestId = 'expressions';
const calculationsTestId = 'calculations';

const layoutSetName = layoutSet1NameMock;
const layouts: IFormLayouts = {
[layout1NameMock]: layoutMock,
};

// Mocks:
jest.mock('../config/EditFormComponent', () => ({
__esModule: true,
Expand Down Expand Up @@ -52,30 +63,6 @@ describe('Properties', () => {
jest.clearAllMocks();
});

describe('Text', () => {
it('Toggles text when clicked', async () => {
const user = userEvent.setup();
renderProperties();
const button = screen.queryByRole('button', { name: textMock('right_menu.text') });
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'true');
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'false');
});
});
describe('DataModelBindings', () => {
it('Toggles dataModelBindings when clicked', async () => {
const user = userEvent.setup();
renderProperties();
const button = screen.queryByRole('button', {
name: textMock('right_menu.data_model_bindings'),
});
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'true');
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'false');
});
});
describe('Page config', () => {
it('shows page config when formItem is undefined', () => {
renderProperties({ formItem: undefined });
Expand All @@ -84,6 +71,17 @@ describe('Properties', () => {
});
});
describe('Component ID Config', () => {
it('saves the component when changes are made in the component', async () => {
const user = userEvent.setup();
renderProperties();
const button = screen.queryByRole('button', { name: textMock('right_menu.content') });
await user.click(button);
const readOnly = screen.getByText(textMock('ux_editor.component_properties.readOnly'));
await user.click(readOnly);
expect(formItemContextProviderMock.handleUpdate).toHaveBeenCalledTimes(1);
expect(formItemContextProviderMock.debounceSave).toHaveBeenCalledTimes(1);
});

it('saves the component when changes are made in the properties header', async () => {
const user = userEvent.setup();
renderProperties();
Expand All @@ -107,17 +105,6 @@ describe('Properties', () => {
expect(formItemContextProviderMock.debounceSave).toHaveBeenCalledTimes(1);
});

it('saves the component when changes are made in the component', async () => {
const user = userEvent.setup();
renderProperties();
const button = screen.queryByRole('button', { name: textMock('right_menu.content') });
await user.click(button);
const readOnly = screen.getByText(textMock('ux_editor.component_properties.readOnly'));
await user.click(readOnly);
expect(formItemContextProviderMock.handleUpdate).toHaveBeenCalledTimes(1);
expect(formItemContextProviderMock.debounceSave).toHaveBeenCalledTimes(1);
});

it('should not invoke handleUpdate when the id is invalid', async () => {
const user = userEvent.setup();
renderProperties();
Expand Down Expand Up @@ -154,6 +141,32 @@ describe('Properties', () => {
});
});

describe('Text', () => {
it('Toggles text when clicked', async () => {
const user = userEvent.setup();
renderProperties();
const button = screen.queryByRole('button', { name: textMock('right_menu.text') });
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'true');
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'false');
});
});

describe('DataModelBindings', () => {
it('Toggles dataModelBindings when clicked', async () => {
const user = userEvent.setup();
renderProperties();
const button = screen.queryByRole('button', {
name: textMock('right_menu.data_model_bindings'),
});
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'true');
await user.click(button);
expect(button).toHaveAttribute('aria-expanded', 'false');
});
});

describe('Content', () => {
it('Closes content on load', () => {
renderProperties();
Expand Down Expand Up @@ -251,4 +264,11 @@ const renderProperties = (
formItem: componentMocks[ComponentType.Input],
formItemId: componentMocks[ComponentType.Input].id,
},
) => renderWithProviders(getComponent(formItemContextProps));
) => {
const queryClientMock = createQueryClientMock();
queryClientMock.setQueryData([QueryKey.FormLayouts, org, app, layoutSetName], layouts);

return renderWithProviders(getComponent(formItemContextProps), {
queryClient: queryClientMock,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
.idInput {
padding: var(--fds-spacing-5);
}

.duplicatedIdField {
background-color: var(--fds-semantic-surface-danger-subtle) !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Trans, useTranslation } from 'react-i18next';
import type { FormItem } from '../../../../types/FormItem';
import { useLayoutSchemaQuery } from '../../../../hooks/queries/useLayoutSchemaQuery';
import { useFormLayouts } from '../../../../hooks';
import { findLayoutsContainingDuplicateComponents } from '../../../../utils/formLayoutUtils';

export interface EditComponentIdRowProps {
handleComponentUpdate: (component: FormItem) => void;
Expand All @@ -29,6 +30,9 @@ export const EditComponentIdRow = ({

const idInputValue = component.id;

const layoutsWithDuplicateComponents = findLayoutsContainingDuplicateComponents(formLayouts);
const duplicatedId = layoutsWithDuplicateComponents.duplicateComponents.includes(idInputValue);

const saveComponentUpdate = (id: string) => {
if (id !== idInputValue) {
handleComponentUpdate({
Expand Down Expand Up @@ -58,7 +62,7 @@ export const EditComponentIdRow = ({
};

return (
<div className={classes.container}>
<div className={duplicatedId ? classes.duplicatedIdField : classes.container}>
<StudioToggleableTextfieldSchema
onError={handleValidationError}
layoutSchema={layoutSchema}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@ import { textMock } from '@studio/testing/mocks/i18nMock';
import { queryClientMock } from 'app-shared/mocks/queryClientMock';
import { QueryKey } from 'app-shared/types/QueryKey';
import { componentSchemaMocks } from '../../../testing/componentSchemaMocks';
import { layoutSet1NameMock } from '@altinn/ux-editor/testing/layoutSetsMock';
import { layout1NameMock, layoutMock } from '@altinn/ux-editor/testing/layoutMock';
import type { IFormLayouts } from '@altinn/ux-editor/types/global';
import { app, org } from '@studio/testing/testids';

const mockHandleComponentUpdate = jest.fn();

const layoutSetName = layoutSet1NameMock;
const layouts: IFormLayouts = {
[layout1NameMock]: layoutMock,
};

const defaultProps: PropertiesHeaderProps = {
formItem: component1Mock,
handleComponentUpdate: mockHandleComponentUpdate,
Expand Down Expand Up @@ -94,6 +103,7 @@ const renderPropertiesHeader = (props: Partial<PropertiesHeaderProps> = {}) => {
[QueryKey.FormComponent, componentType],
componentSchemaMocks[componentType],
);
queryClientMock.setQueryData([QueryKey.FormLayouts, org, app, layoutSetName], layouts);
return renderWithProviders(
<FormItemContext.Provider
value={{
Expand Down

0 comments on commit 81e5f6a

Please sign in to comment.