Skip to content

Commit

Permalink
fix: tablecolumns saving/deleting a column affects other columns
Browse files Browse the repository at this point in the history
Removes unecessary state, and dependence on custom text-key for custom
labels

commit-id:2ef223ec
  • Loading branch information
Jondyr committed Feb 6, 2025
1 parent 2e6d8db commit b0cee09
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 159 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react';
import { screen } from '@testing-library/react';
import { ColumnElement, type ColumnElementProps } from './ColumnElement';
import { textMock } from '@studio/testing/mocks/i18nMock';
import { renderWithProviders } from 'dashboard/testing/mocks';
import { renderWithProviders } from '../../../../testing/mocks';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { queriesMock } from 'app-shared/mocks/queriesMock';
import userEvent from '@testing-library/user-event';
import { type TableColumn } from '../types/TableColumn';
import type { TableColumn } from '../types/TableColumn';
import { layoutSet3SubformNameMock } from '../../../../testing/layoutSetsMock';
import { QueryKey } from 'app-shared/types/QueryKey';
import { app, org } from '@studio/testing/testids';
Expand All @@ -16,6 +16,8 @@ const headerContentMock: string = 'Header';
const cellContentQueryMock: string = 'Query';
const cellContentDefaultMock: string = 'Default';
const columnNumberMock: number = 1;
const textKeyMock = 'textkeymock1';
const textValueMock = 'textkeymock1';

const mockTableColumn: TableColumn = {
headerContent: headerContentMock,
Expand All @@ -30,21 +32,25 @@ const defaultProps: ColumnElementProps = {
columnNumber: columnNumberMock,
isInitialOpenForEdit: false,
onDeleteColumn: jest.fn(),
onEdit: jest.fn(),
onChange: jest.fn(),
subformLayout: layoutSet3SubformNameMock,
};

describe('ColumnElement', () => {
afterEach(() => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should call onEdit with updated header content when click on save button', async () => {
const onEditMock = jest.fn();
it('should call onChange with component values when selecting component', async () => {
const onChangeMock = jest.fn();

const user = userEvent.setup();
renderColumnElement({
onEdit: onEditMock,
onChange: onChangeMock,
tableColumn: {
headerContent: subformLayoutMock.component4.textResourceBindings.title,
cellContent: { query: subformLayoutMock.component4.dataModelBindings.address },
},
});

const editButton = screen.getByRole('button', {
Expand All @@ -58,35 +64,60 @@ describe('ColumnElement', () => {

await user.click(componentSelect);
await user.click(
screen.getByRole('option', { name: new RegExp(`${subformLayoutMock.component3Id}`) }),
screen.getByRole('option', { name: new RegExp(`${subformLayoutMock.component4Id}`) }),
);

await screen.findByText(
textMock(
'ux_editor.properties_panel.subform_table_columns.column_multiple_data_model_bindings_label',
),
);
const saveButton = await screen.findByRole('button', { name: textMock('general.save') });
await user.click(saveButton);

expect(onChangeMock).toHaveBeenCalledWith({
...mockTableColumn,
cellContent: {
query: subformLayoutMock.component4.dataModelBindings.address,
},
headerContent: subformLayoutMock.component4.textResourceBindings.title,
});
});

it('should call onChange with updated header content on changing text key', async () => {
const onChangeMock = jest.fn();

const user = userEvent.setup();
renderColumnElement({
onChange: onChangeMock,
});

const editButton = screen.getByRole('button', {
name: /ux_editor.properties_panel.subform_table_columns.column_header/,
});
await user.click(editButton);

await user.click(
await screen.findByText(
textMock('ux_editor.properties_panel.subform_table_columns.column_title_unedit'),
),
screen.getByRole('button', {
name: textMock('ux_editor.properties_panel.subform_table_columns.column_title_edit'),
}),
);
await user.type(
screen.getByText(
textMock('ux_editor.properties_panel.subform_table_columns.column_title_edit'),
),
'New Title',
await user.click(
screen.getByRole('tab', {
name: textMock('ux_editor.text_resource_binding_search'),
}),
);
await user.selectOptions(
screen.getByRole('combobox', { name: textMock('ux_editor.search_text_resources_label') }),
textKeyMock,
);
await user.click(
screen.getByRole('button', {
name: textMock('general.close'),
}),
);

const saveButton = await screen.findByRole('button', { name: textMock('general.save') });
await user.click(saveButton);

expect(onEditMock).toHaveBeenCalledTimes(1);
expect(onEditMock).toHaveBeenCalledWith({
expect(onChangeMock).toHaveBeenCalledWith({
...mockTableColumn,
headerContent: expect.stringContaining('subform_table_column_title_'),
cellContent: { query: subformLayoutMock.component3.dataModelBindings.simpleBinding },
headerContent: textKeyMock,
});
});

Expand Down Expand Up @@ -133,6 +164,10 @@ const renderColumnElement = (props: Partial<ColumnElementProps> = {}) => {
[QueryKey.FormLayouts, org, app, layoutSet3SubformNameMock],
subformLayoutMock.layoutSet,
);
queryClient.setQueryData([QueryKey.TextResources, org, app], {
nb: [{ id: textKeyMock, value: textValueMock }],
});

return renderWithProviders(<ColumnElement {...defaultProps} {...props} />, {
...queriesMock,
queryClient,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
import React, { useState, type ReactElement } from 'react';
import classes from './ColumnElement.module.css';
import { type TableColumn } from '../types/TableColumn';
import type { TableColumn } from '../types/TableColumn';
import { useTranslation } from 'react-i18next';
import { StudioProperty } from '@studio/components';
import { EditColumnElement } from './EditColumnElement';
import { useTextResourcesQuery } from 'app-shared/hooks/queries';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import { textResourceByLanguageAndIdSelector } from '../../../../selectors/textResourceSelectors';
import { DEFAULT_LANGUAGE } from 'app-shared/constants';

export type ColumnElementProps = {
subformLayout: string;
tableColumn: TableColumn;
columnNumber: number;
isInitialOpenForEdit: boolean;
onDeleteColumn: () => void;
onEdit: (tableColumn: TableColumn) => void;
onChange: (tableColumn: TableColumn) => void;
};

export const ColumnElement = ({
tableColumn,
columnNumber,
isInitialOpenForEdit,
onDeleteColumn,
onEdit,
onChange,
subformLayout,
}: ColumnElementProps): ReactElement => {
const { t } = useTranslation();
const [editing, setEditing] = useState(isInitialOpenForEdit);
const { org, app } = useStudioEnvironmentParams();
const { data: textResources } = useTextResourcesQuery(org, app);

const textKeyValue = textResourceByLanguageAndIdSelector(
'nb',
tableColumn.headerContent,
)(textResources)?.value;
const textKeyValue =
textResourceByLanguageAndIdSelector(DEFAULT_LANGUAGE, tableColumn?.headerContent)(textResources)
?.value || tableColumn?.headerContent;

if (editing) {
return (
<EditColumnElement
subformLayout={subformLayout}
sourceColumn={tableColumn}
tableColumn={tableColumn}
columnNumber={columnNumber}
onDeleteColumn={onDeleteColumn}
onEdit={(col) => {
onChange={onChange}
onClose={() => {
setEditing(false);
onEdit(col);
}}
/>
);
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 { act, screen } from '@testing-library/react';
import { textMock } from '@studio/testing/mocks/i18nMock';
import userEvent from '@testing-library/user-event';
import { subformLayoutMock } from '../../../../../testing/subformLayoutMock';
Expand All @@ -14,10 +14,11 @@ import { app, org } from '@studio/testing/testids';
const subformComponentMock = componentMocks[ComponentType.Subform];

const defaultProps: EditColumnElementProps = {
sourceColumn: subformComponentMock.tableColumns[0],
tableColumn: subformComponentMock.tableColumns[0],
columnNumber: 1,
onDeleteColumn: jest.fn(),
onEdit: jest.fn(),
onChange: jest.fn(),
onClose: jest.fn(),
subformLayout: subformLayoutMock.layoutSetName,
};

Expand Down Expand Up @@ -112,16 +113,21 @@ describe('EditColumnElementComponentSelect', () => {

it('should render multiple data model bindings label when there are multiple data model bindings', async () => {
const user = userEvent.setup();
renderEditColumnElement();
renderEditColumnElement({
tableColumn: {
headerContent: subformLayoutMock.component4.textResourceBindings.title,
cellContent: { query: subformLayoutMock.component4.dataModelBindings.address },
},
});
const componentSelect = screen.getByRole('combobox', {
name: textMock('ux_editor.properties_panel.subform_table_columns.choose_component'),
});
expect(componentSelect).toBeInTheDocument();
await user.click(componentSelect);
const componentWitMultipleBindings = screen.getByRole('option', {
name: new RegExp(`${subformLayoutMock.component3Id}`),
const componentWithMultipleBindings = screen.getByRole('option', {
name: new RegExp(`${subformLayoutMock.component4Id}`),
});
await user.click(componentWitMultipleBindings);
await user.click(componentWithMultipleBindings);
expect(
await screen.findByText(
textMock(
Expand All @@ -133,7 +139,12 @@ describe('EditColumnElementComponentSelect', () => {

it('should only render data model bindings that have a value', async () => {
const user = userEvent.setup();
renderEditColumnElement();
renderEditColumnElement({
tableColumn: {
headerContent: subformLayoutMock.component4.textResourceBindings.title,
cellContent: { query: subformLayoutMock.component4.dataModelBindings.address },
},
});
const componentSelect = screen.getByRole('combobox', {
name: textMock('ux_editor.properties_panel.subform_table_columns.choose_component'),
});
Expand Down Expand Up @@ -170,12 +181,12 @@ describe('EditColumnElementComponentSelect', () => {
).not.toBeInTheDocument();
});

it('should call onEdit with updated query when selecting a simple data model binding and clicking on save button', async () => {
it('should call onChange with updated query when selecting a simple data model binding and clicking on save button', async () => {
const user = userEvent.setup();

const onEditMock = jest.fn();
const onChangeMock = jest.fn();
renderEditColumnElement({
onEdit: onEditMock,
onChange: onChangeMock,
});

const componentSelect = screen.getByRole('combobox', {
Expand All @@ -190,28 +201,31 @@ describe('EditColumnElementComponentSelect', () => {
const saveButton = await screen.findByRole('button', { name: textMock('general.save') });
await user.click(saveButton);

expect(onEditMock).toHaveBeenCalledTimes(1);
expect(onEditMock).toHaveBeenCalledWith({
headerContent: expect.stringContaining('subform_table_column_title_'),
expect(onChangeMock).toHaveBeenCalledTimes(1);
expect(onChangeMock).toHaveBeenCalledWith({
headerContent: subformLayoutMock.component1.textResourceBindings.title,
cellContent: { query: subformLayoutMock.component1.dataModelBindings.simpleBinding },
});
});

it('should call onEdit with updated query when selecting a multiple data model binding and clicking on save button', async () => {
it('should call onChange with updated query when selecting a multiple data model binding and clicking on save button', async () => {
const user = userEvent.setup();

const onEditMock = jest.fn();
const onChangeMock = jest.fn();
renderEditColumnElement({
onEdit: onEditMock,
onChange: onChangeMock,
tableColumn: {
headerContent: subformLayoutMock.component4.textResourceBindings.title,
cellContent: { query: subformLayoutMock.component4.dataModelBindings.address },
},
});

const componentSelect = screen.getByRole('combobox', {
name: textMock('ux_editor.properties_panel.subform_table_columns.choose_component'),
});

await user.click(componentSelect);
await user.click(
screen.getByRole('option', { name: new RegExp(`${subformLayoutMock.component3Id}`) }),
screen.getByRole('option', { name: new RegExp(`${subformLayoutMock.component4Id}`) }),
);

const dataModelBindingsSelect = await screen.findByText(
Expand All @@ -220,20 +234,22 @@ describe('EditColumnElementComponentSelect', () => {
),
);

await user.click(dataModelBindingsSelect);
await act(async () => {
await user.click(dataModelBindingsSelect);
});
await user.click(
screen.getByRole('option', {
name: new RegExp(subformLayoutMock.component3.dataModelBindings.simpleBinding.toString()),
name: new RegExp(subformLayoutMock.component4.dataModelBindings.postPlace),
}),
);

const saveButton = await screen.findByRole('button', { name: textMock('general.save') });
await user.click(saveButton);

expect(onEditMock).toHaveBeenCalledTimes(1);
expect(onEditMock).toHaveBeenCalledWith({
headerContent: expect.stringContaining('subform_table_column_title_'),
cellContent: { query: subformLayoutMock.component3.dataModelBindings.simpleBinding },
expect(onChangeMock).toHaveBeenCalledTimes(2);
expect(onChangeMock).toHaveBeenCalledWith({
headerContent: subformLayoutMock.component4.textResourceBindings.title,
cellContent: { query: subformLayoutMock.component4.dataModelBindings.postPlace },
});
});
});
Expand Down
Loading

0 comments on commit b0cee09

Please sign in to comment.