Skip to content

Commit

Permalink
Merge pull request #982 from CruGlobal/MPDX-7416-fix-email-addresses-…
Browse files Browse the repository at this point in the history
…confirm-all

MPDX-7416 - Fix Email Addresses - Confirm All Button
  • Loading branch information
wrandall22 authored Aug 12, 2024
2 parents 2dd9c53 + 56503c7 commit 773b5ee
Show file tree
Hide file tree
Showing 8 changed files with 431 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const EmailValidationForm = ({
emailAddressesMutation({
variables: {
input: {
accountListId: accountListId || '',
accountListId: accountListId ?? '',
attributes: {
id: personId,
emailAddresses: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { SnackbarProvider } from 'notistack';
import TestWrapper from '__tests__/util/TestWrapper';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { render, waitFor } from '__tests__/util/testingLibraryReactMock';
import useGetAppSettings from 'src/hooks/useGetAppSettings';
import theme from 'src/theme';
import { EmailAddressesMutation } from '../AddEmailAddress.generated';
import { EmailAddressData, PersonEmailAddresses } from '../FixEmailAddresses';
Expand Down Expand Up @@ -48,6 +49,7 @@ const mutationSpy = jest.fn();
const handleSingleConfirm = jest.fn();
const mockEnqueue = jest.fn();

jest.mock('src/hooks/useGetAppSettings');
jest.mock('notistack', () => ({
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
Expand Down Expand Up @@ -105,6 +107,12 @@ const TestComponent = ({
};

describe('FixEmailAddressPerson', () => {
beforeEach(() => {
(useGetAppSettings as jest.Mock).mockReturnValue({
appName: 'MPDX',
});
});

it('default', () => {
const { getByText, getByTestId, getByDisplayValue } = render(
<TestComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { makeStyles } from 'tss-react/mui';
import { SetContactFocus } from 'pages/accountLists/[accountListId]/tools/useToolsHelper';
import { useUpdateEmailAddressesMutation } from 'src/components/Tool/FixEmailAddresses/FixEmailAddresses.generated';
import { Confirmation } from 'src/components/common/Modal/Confirmation/Confirmation';
import useGetAppSettings from 'src/hooks/useGetAppSettings';
import { useLocale } from 'src/hooks/useLocale';
import { dateFormatShort } from 'src/lib/intlFormat';
import theme from 'src/theme';
Expand Down Expand Up @@ -138,6 +139,7 @@ export const FixEmailAddressPerson: React.FC<FixEmailAddressPersonProps> = ({
handleSingleConfirm,
setContactFocus,
}) => {
const { appName } = useGetAppSettings();
const { t } = useTranslation();
const locale = useLocale();
const { classes } = useStyles();
Expand Down Expand Up @@ -327,10 +329,10 @@ export const FixEmailAddressPerson: React.FC<FixEmailAddressPersonProps> = ({
event: React.ChangeEvent<HTMLInputElement>,
) => handleChange(id, index, event)}
value={email.email}
disabled={email.source !== 'MPDX'}
disabled={email.source !== appName}
/>

{email.source === 'MPDX' ? (
{email.source === appName ? (
<Box
data-testid={`delete-${id}-${index}`}
onClick={() =>
Expand Down Expand Up @@ -360,7 +362,7 @@ export const FixEmailAddressPerson: React.FC<FixEmailAddressPersonProps> = ({
<strong>{t('Source')}: </strong>
</Typography>
</Hidden>
<Typography display="inline">MPDX</Typography>
<Typography display="inline">{appName}</Typography>
</Box>
</Box>
</RowWrapper>
Expand Down
13 changes: 13 additions & 0 deletions src/components/Tool/FixEmailAddresses/FixEmailAddresses.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,16 @@ mutation UpdateEmailAddresses($input: PersonUpdateMutationInput!) {
}
}
}

mutation UpdatePeople($input: PeopleUpdateMutationInput!) {
updatePeople(input: $input) {
people {
emailAddresses {
nodes {
...PersonEmailAddress
validValues
}
}
}
}
}
253 changes: 252 additions & 1 deletion src/components/Tool/FixEmailAddresses/FixEmailAddresses.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import {
GetInvalidEmailAddressesQuery,
UpdateEmailAddressesMutation,
UpdatePeopleMutation,
} from 'src/components/Tool/FixEmailAddresses/FixEmailAddresses.generated';
import useGetAppSettings from 'src/hooks/useGetAppSettings';
import theme from '../../../theme';
import { EmailAddressesMutation } from './AddEmailAddress.generated';
import { FixEmailAddresses } from './FixEmailAddresses';
import {
FixEmailAddresses,
PersonEmailAddresses,
determineBulkDataToSend,
} from './FixEmailAddresses';
import {
contactId,
contactOneEmailAddressNodes,
Expand Down Expand Up @@ -41,6 +47,7 @@ jest.mock('notistack', () => ({
};
},
}));
jest.mock('src/hooks/useGetAppSettings');

const defaultGraphQLMock = {
GetInvalidEmailAddresses: {
Expand All @@ -61,6 +68,7 @@ const Components = ({ mocks = defaultGraphQLMock }: ComponentsProps) => (
GetInvalidEmailAddresses: GetInvalidEmailAddressesQuery;
EmailAddresses: EmailAddressesMutation;
UpdateEmailAddresses: UpdateEmailAddressesMutation;
UpdatePeople: UpdatePeopleMutation;
}>
mocks={mocks}
onCall={mutationSpy}
Expand All @@ -77,6 +85,11 @@ const Components = ({ mocks = defaultGraphQLMock }: ComponentsProps) => (
);

describe('FixEmailAddresses-Home', () => {
beforeEach(() => {
(useGetAppSettings as jest.Mock).mockReturnValue({
appName: 'MPDX',
});
});
it('default with test data', async () => {
const { getByText, getByTestId, queryByTestId } = render(<Components />);

Expand All @@ -97,6 +110,15 @@ describe('FixEmailAddresses-Home', () => {
expect(queryByTestId('no-data')).not.toBeInTheDocument();
});

it('should show the app name as a source value', async () => {
const { getByRole, getByText } = render(<Components />);
await waitFor(() => {
expect(getByText('Fix Email Addresses')).toBeInTheDocument();
expect(getByText('Confirm 2 as MPDX')).toBeInTheDocument();
expect(getByRole('combobox')).toHaveTextContent('MPDX');
});
});

describe('handleChangePrimary()', () => {
it('changes primary of first email', async () => {
const { getByTestId, queryByTestId } = render(<Components />);
Expand Down Expand Up @@ -382,4 +404,233 @@ describe('FixEmailAddresses-Home', () => {
});
});
});

describe('handleBulkConfirm', () => {
it('should save all the email changes for all people', async () => {
const noPeopleMessage = 'No people with email addresses need attention';

const { getByRole, getByText, getByTestId, queryByTestId } = render(
<Components />,
);

await waitFor(() => {
expect(queryByTestId('loading')).not.toBeInTheDocument();
expect(getByTestId('starOutlineIcon-testid-1')).toBeInTheDocument();
});
userEvent.click(getByTestId('starOutlineIcon-testid-1'));

const bulkConfirmButton = getByRole('button', {
name: 'Confirm 2 as MPDX',
});
userEvent.click(bulkConfirmButton);
userEvent.click(getByRole('button', { name: 'Yes' }));

await waitFor(() => {
expect(mockEnqueue).toHaveBeenCalledWith(
`Successfully updated email addresses`,
{ variant: 'success' },
);
expect(getByText(noPeopleMessage)).toBeVisible();
});
});

it('should handle errors', async () => {
const personName1 = 'Test Contact';
const personName2 = 'Simba Lion';

const { getByRole, getByText, queryByTestId } = render(
<Components
mocks={{
GetInvalidEmailAddresses: {
people: {
nodes: mockInvalidEmailAddressesResponse,
},
},
UpdatePeople: () => {
throw new Error('Server error');
},
}}
/>,
);

await waitFor(() =>
expect(queryByTestId('loading')).not.toBeInTheDocument(),
);

const bulkConfirmButton = getByRole('button', {
name: 'Confirm 2 as MPDX',
});
userEvent.click(bulkConfirmButton);
userEvent.click(getByRole('button', { name: 'Yes' }));

await waitFor(() => {
expect(mockEnqueue).toHaveBeenCalledWith(
`Error updating email addresses`,
{ variant: 'error', autoHideDuration: 7000 },
);
expect(getByText(personName1)).toBeVisible();
expect(getByText(personName2)).toBeVisible();
});
});

it('should cancel the bulk confirmation', async () => {
const personName1 = 'Test Contact';
const personName2 = 'Simba Lion';

const { getByRole, getByText, queryByTestId } = render(
<Components
mocks={{
GetInvalidEmailAddresses: {
people: {
nodes: mockInvalidEmailAddressesResponse,
},
},
}}
/>,
);

await waitFor(() =>
expect(queryByTestId('loading')).not.toBeInTheDocument(),
);

const bulkConfirmButton = getByRole('button', {
name: 'Confirm 2 as MPDX',
});
userEvent.click(bulkConfirmButton);
userEvent.click(getByRole('button', { name: 'No' }));

await waitFor(() => {
expect(mockEnqueue).not.toHaveBeenCalled();
expect(getByText(personName1)).toBeVisible();
expect(getByText(personName2)).toBeVisible();
});
});

it('should not update if there is no email for the default source', async () => {
const noPrimaryEmailMessage =
'No MPDX primary email address exists to update';

const { getByRole, queryByTestId } = render(
<Components
mocks={{
GetInvalidEmailAddresses: {
people: {
nodes: [
{
...mockInvalidEmailAddressesResponse[0],
emailAddresses: {
nodes: [
{
...contactOneEmailAddressNodes[0],
source: 'DataServer',
},
{
...contactOneEmailAddressNodes[1],
source: 'DonorHub',
},
],
},
},
{
...mockInvalidEmailAddressesResponse[1],
emailAddresses: {
nodes: [
{
...contactOneEmailAddressNodes[0],
source: 'DataServer',
},
{
...contactOneEmailAddressNodes[1],
source: 'DonorHub',
},
],
},
},
],
},
},
}}
/>,
);

await waitFor(() => {
expect(queryByTestId('loading')).not.toBeInTheDocument();
});
userEvent.click(getByRole('combobox'));
userEvent.click(getByRole('option', { name: 'MPDX' }));

const bulkConfirmButton = getByRole('button', {
name: 'Confirm 2 as MPDX',
});
userEvent.click(bulkConfirmButton);
userEvent.click(getByRole('button', { name: 'Yes' }));

await waitFor(() => {
expect(mockEnqueue).toHaveBeenCalledWith(noPrimaryEmailMessage, {
variant: 'warning',
autoHideDuration: 7000,
});
expect(bulkConfirmButton).toBeVisible();
});
});
});

describe('determineBulkDataToSend', () => {
it('should set the first email of the given source to primary', () => {
const dataState = {
testid: {
emailAddresses: [
{
...contactOneEmailAddressNodes[0],
primary: false,
},
{
...contactOneEmailAddressNodes[1],
},
{
...contactOneEmailAddressNodes[2],
primary: true,
},
],
},
} as { [key: string]: PersonEmailAddresses };
const defaultSource = 'MPDX';

const dataToSend = determineBulkDataToSend(
dataState,
defaultSource,
'MPDX',
);

const emails = dataToSend[0].emailAddresses ?? [];
expect(emails[0].primary).toEqual(true);
expect(emails[2].primary).toEqual(false);
});

it('should be empty if there is no email of the given source', () => {
const dataState = {
testid: {
emailAddresses: [
{
...contactOneEmailAddressNodes[0],
},
{
...contactOneEmailAddressNodes[1],
},
{
...contactOneEmailAddressNodes[2],
},
],
},
} as { [key: string]: PersonEmailAddresses };
const defaultSource = 'DonorHub';

const dataToSend = determineBulkDataToSend(
dataState,
defaultSource,
'MPDX',
);
expect(dataToSend.length).toEqual(0);
});
});
});
Loading

0 comments on commit 773b5ee

Please sign in to comment.