Skip to content

Commit

Permalink
fix: updating trusted address from settings breaks all previous data
Browse files Browse the repository at this point in the history
  • Loading branch information
dhavaldodiya committed Feb 12, 2024
1 parent 799ed58 commit 92908af
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/types/settings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export type UpdateSettingsProps = {
};

export type InputProps = {
settingsObj: PrefsType;
settingsObj: AccountSettingsPrefs;
updateSettings: (arg: UpdateSettingsProps) => void;
};

Expand Down
7 changes: 4 additions & 3 deletions src/views/settings/components/trustee-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
*/

import React, { FC, ReactElement, useCallback, useState } from 'react';

import { Container, Text, Row, Button } from '@zextras/carbonio-design-system';
import styled from 'styled-components';
import { t } from '@zextras/carbonio-shell-ui';
import styled from 'styled-components';

const ListItem = styled(Row)`
border-bottom: 0.0625rem solid ${({ theme }): string => theme.palette.gray2.regular};
Expand All @@ -28,7 +29,7 @@ const TrusteeListItem: FC<any> = ({ item, onRemove }): ReactElement => {
const onMouseLeave = useCallback(() => setHovered(false), []);

const onClick = useCallback(() => {
onRemove(item);
onRemove(item.value);
}, [item, onRemove]);

return (
Expand All @@ -40,7 +41,7 @@ const TrusteeListItem: FC<any> = ({ item, onRemove }): ReactElement => {
>
<Row height="2.5rem" padding={{ all: 'small' }}>
<Container width="80%" crossAlignment="flex-start">
<Text size="small">{item}</Text>
<Text size="small">{item.value}</Text>
</Container>

<Container width="20%" orientation="horizontal" mainAlignment="flex-end">
Expand Down
9 changes: 7 additions & 2 deletions src/views/settings/components/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ export const differenceObject = (object, base) => {
function changes(object, base) {
return transform(object, (result, value, key) => {
if (!isEqual(value, base[key])) {
// eslint-disable-next-line no-param-reassign
result[key] = isObject(value) && isObject(base[key]) ? changes(value, base[key]) : value;
if (key === 'zimbraPrefMailTrustedSenderList') {
// eslint-disable-next-line no-param-reassign
result[key] = value;
} else {
// eslint-disable-next-line no-param-reassign
result[key] = isObject(value) && isObject(base[key]) ? changes(value, base[key]) : value;
}
}
});
}
Expand Down
3 changes: 1 addition & 2 deletions src/views/settings/settings-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const SettingsView: FC = () => {

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const [settingsObj, setSettingsObj] = useState<PrefsType>({ ...prefs });
const [settingsObj, setSettingsObj] = useState<AccountSettingsPrefs>({ ...prefs });
const [updatedSettings, setUpdatedSettings] = useState({});
const originalProps = useMemo(
() =>
Expand Down Expand Up @@ -271,7 +271,6 @@ const SettingsView: FC = () => {
});
}
});
return Promise.allSettled([Promise.resolve()]);
}

if (Object.keys(settingsToUpdate).length > 0) {
Expand Down
158 changes: 158 additions & 0 deletions src/views/settings/tests/trustee-addresses.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* SPDX-FileCopyrightText: 2024 Zextras <https://www.zextras.com>
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React from 'react';

import { faker } from '@faker-js/faker';
import { act } from '@testing-library/react';
import { AccountSettings } from '@zextras/carbonio-shell-ui';
import { times } from 'lodash';

import { generateSettings } from '../../../carbonio-ui-commons/test/mocks/settings/settings-generator';
import { screen, setupTest, within } from '../../../carbonio-ui-commons/test/test-setup';
import { generateStore } from '../../../tests/generators/store';
import type { InputProps } from '../../../types';
import TrusteeAddresses from '../trustee-addresses';

const FIND_TIMEOUT = 2000;
const TRUSTEE_LIST = 'trustee-list';

const buildProps = ({
settingsObj = {},
updateSettings = jest.fn()
}: Partial<InputProps>): InputProps => ({
settingsObj,
updateSettings
});

describe('Trustee addresses settings', () => {
it('should render the section title', () => {
setupTest(<TrusteeAddresses {...buildProps({})} />);
expect(screen.getByText('label.trusted_addresses')).toBeVisible();
});
it('should render the section message', () => {
setupTest(<TrusteeAddresses {...buildProps({})} />);
expect(screen.getByText('messages.trustee_addresses')).toBeVisible();
});
it('should render the "add" button', () => {
setupTest(<TrusteeAddresses {...buildProps({})} />);
expect(screen.getByRole('button', { name: 'label.add' })).toBeVisible();
});

it('should render the input field for the trustee email or domain name', () => {
setupTest(<TrusteeAddresses {...buildProps({})} />);
const nameInput = screen.getByRole('textbox', { name: 'label.enter_email_address' });
expect(nameInput).toBeVisible();
});

it('should render the list of trustee addresses', async () => {
const store = generateStore();
const updateSettings = jest.fn();

const trusteeAddressArray: Array<string> = times(3, () => faker.internet.email());
const customSettings: Partial<AccountSettings> = {
prefs: {
zimbraPrefMailTrustedSenderList: trusteeAddressArray
}
};
const { prefs } = generateSettings(customSettings);
setupTest(<TrusteeAddresses updateSettings={updateSettings} settingsObj={prefs} />, { store });

await screen.findByText(trusteeAddressArray[0], undefined, { timeout: FIND_TIMEOUT });
trusteeAddressArray.forEach((trusteeAdress) => {
expect(screen.getByText(trusteeAdress)).toBeVisible();
});
});

it('should display a delete button when user hover on the trustee address item', async () => {
const store = generateStore();
const updateSettings = jest.fn();

const trusteeAddressArray: Array<string> = times(1, () => faker.internet.email());
const customSettings: Partial<AccountSettings> = {
prefs: {
zimbraPrefMailTrustedSenderList: trusteeAddressArray
}
};
const { prefs } = generateSettings(customSettings);

const { user } = setupTest(
<TrusteeAddresses updateSettings={updateSettings} settingsObj={prefs} />,
{ store }
);

await screen.findByText(trusteeAddressArray[0], undefined, { timeout: FIND_TIMEOUT });
trusteeAddressArray.forEach((trusteeAdress) => {
expect(screen.getByText(trusteeAdress)).toBeVisible();
});

const list = screen.getByTestId(TRUSTEE_LIST);
const listItem = await within(list).findByText(trusteeAddressArray[0]);
await act(async () => {
await user.hover(listItem);
});
const button = await screen.findByRole('button', { name: 'label.remove' });
expect(button).toBeVisible();
});

it('should remove the trustee address from the list if the remove button is clicked', async () => {
const store = generateStore();
const updateSettings = jest.fn();
const trusteeAddressArray: Array<string> = times(1, () => faker.internet.email());
const customSettings: Partial<AccountSettings> = {
prefs: {
zimbraPrefMailTrustedSenderList: trusteeAddressArray
}
};
const { prefs } = generateSettings(customSettings);
const { user } = setupTest(
<TrusteeAddresses updateSettings={updateSettings} settingsObj={prefs} />,
{ store }
);

await screen.findByText(trusteeAddressArray[0], undefined, { timeout: FIND_TIMEOUT });
trusteeAddressArray.forEach((trusteeAdress) => {
expect(screen.getByText(trusteeAdress)).toBeVisible();
});
const list = screen.getByTestId(TRUSTEE_LIST);
const listItem = await within(list).findByText(trusteeAddressArray[0]);
await act(async () => {
await user.hover(listItem);
});
const button = await screen.findByRole('button', { name: 'label.remove' });
expect(button).toBeVisible();
user.click(button);
});

it('should add new trustee address in the list of trustee addresses', async () => {
const store = generateStore();
const updateSettings = jest.fn();
const newTrusteeAddress = faker.internet.email();

const trusteeAddressArray: Array<string> = times(3, () => faker.internet.email());
const customSettings: Partial<AccountSettings> = {
prefs: {
zimbraPrefMailTrustedSenderList: trusteeAddressArray
}
};
const { prefs } = generateSettings(customSettings);
const { user } = setupTest(
<TrusteeAddresses updateSettings={updateSettings} settingsObj={prefs} />,
{ store }
);
trusteeAddressArray.forEach((trusteeAdress) => {
expect(screen.getByText(trusteeAdress)).toBeVisible();
});
const nameInput = screen.getByRole('textbox', { name: 'label.enter_email_address' });
expect(nameInput).toBeVisible();
await user.type(nameInput, newTrusteeAddress);
const addButton = screen.getByRole('button', { name: 'label.add' });
await act(() => user.click(addButton));

const list = screen.getByTestId(TRUSTEE_LIST);
const listItem = await within(list).findByText(newTrusteeAddress);
expect(listItem).toBeVisible();
});
});
24 changes: 18 additions & 6 deletions src/views/settings/trustee-addresses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { useMemo, FC, useState, useCallback, useEffect } from 'react';
import React, { useMemo, useState, useCallback, useEffect } from 'react';

import {
Container,
Input,
Expand All @@ -16,19 +17,19 @@ import {
Row
} from '@zextras/carbonio-design-system';
import { t } from '@zextras/carbonio-shell-ui';
import { filter, find } from 'lodash';
import { filter, find, map } from 'lodash';

import Heading from './components/settings-heading';
import { domainWhitelistSubSection } from './subsections';
import TrusteeListItem from './components/trustee-list-item';
import LoadingShimmer from './filters/parts/loading-shimmer';
import { domainWhitelistSubSection } from './subsections';
import type { InputProps } from '../../types';

const NonSupportedCharacters = /[!#$%^&*()+=[\]{};':"\\|,<>/?|/^\s*$/]+/;
const TrusteeAddresses: FC<InputProps> = ({ settingsObj, updateSettings }) => {
const TrusteeAddresses = ({ settingsObj, updateSettings }: InputProps): React.JSX.Element => {
const [address, setAddress] = useState('');
const [isLoading, setIsLoading] = useState(true);
const [trusteeAddressesList, setTrusteeAddressList] = useState<string[]>([]);

const sectionTitle = useMemo(() => domainWhitelistSubSection(), []);
const message = useMemo(
() =>
Expand Down Expand Up @@ -87,6 +88,16 @@ const TrusteeAddresses: FC<InputProps> = ({ settingsObj, updateSettings }) => {
[isInvalid]
);

const trusteeAddressesListItems = useMemo(
() =>
map(trusteeAddressesList, (el) => ({
id: el,
value: el,
label: el
})),
[trusteeAddressesList]
);

return (
<Container background="gray6" padding={{ horizontal: 'medium', bottom: 'large' }}>
<Container orientation="horizontal" padding={{ horizontal: 'medium', top: 'medium' }}>
Expand Down Expand Up @@ -133,9 +144,10 @@ const TrusteeAddresses: FC<InputProps> = ({ settingsObj, updateSettings }) => {
<LoadingShimmer />
) : (
<List
items={trusteeAddressesList}
items={trusteeAddressesListItems}
ItemComponent={TrusteeListItem}
itemProps={{ onRemove }}
data-testid={'trustee-list'}
/>
)}
</Container>
Expand Down

0 comments on commit 92908af

Please sign in to comment.