Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Appeal list contact row functionality #1013

Merged
merged 4 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import {
DialogContent,
FormControl,
FormHelperText,
FormLabel,
Grid,
MenuItem,
Select,
TextField,
Theme,
useMediaQuery,
} from '@mui/material';
import { styled } from '@mui/material/styles';
import { FastField, Field, FieldProps, Form, Formik } from 'formik';
import { DateTime } from 'luxon';
import { useSnackbar } from 'notistack';
Expand All @@ -35,6 +33,7 @@ import {
useAddDonationMutation,
useGetDonationModalQuery,
} from './AddDonation.generated';
import { FormTextField, LogFormLabel } from './StyledComponents';

interface AddDonationProps {
accountListId: string;
Expand Down Expand Up @@ -83,21 +82,6 @@ const donationSchema = yup.object({

type Attributes = yup.InferType<typeof donationSchema>;

const LogFormLabel = styled(FormLabel)(({ theme }) => ({
margin: theme.spacing(1, 0),
fontWeight: 'bold',
color: theme.palette.primary.dark,
'& span': {
color: theme.palette.error.main,
},
}));

const FormTextField = styled(TextField)(({ theme }) => ({
'& .MuiInputBase-root.Mui-disabled': {
backgroundColor: theme.palette.cruGrayLight.main,
},
}));

export const AddDonation = ({
accountListId,
handleClose,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FormLabel, TextField } from '@mui/material';
import { styled } from '@mui/material/styles';

export const LogFormLabel = styled(FormLabel)(({ theme }) => ({
margin: theme.spacing(1, 0),
fontWeight: 'bold',
color: theme.palette.primary.dark,
'& span': {
color: theme.palette.error.main,
},
}));

export const FormTextField = styled(TextField)(({ theme }) => ({
'& .MuiInputBase-root.Mui-disabled': {
backgroundColor: theme.palette.cruGrayLight.main,
},
}));
41 changes: 35 additions & 6 deletions src/components/Tool/Appeal/AppealsContext/contacts.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ query Contacts(
first: $first
) {
nodes {
name
id
pledgeAmount
pledgeCurrency
pledgeFrequency
pledgeReceived
...AppealContactInfo
}
pageInfo {
hasNextPage
Expand All @@ -25,3 +20,37 @@ query Contacts(
totalCount
}
}

fragment AppealContactInfo on Contact {
id
name
pledgeAmount
pledgeCurrency
pledgeFrequency
pledgeReceived
pledgeStartDate
pledges {
id
amount
amountCurrency
appeal {
id
}
expectedDate
status
}
donations {
nodes {
appeal {
id
}
id
donationDate
appealAmount {
amount
convertedAmount
convertedCurrency
}
}
}
}
138 changes: 92 additions & 46 deletions src/components/Tool/Appeal/List/ContactRow/ContactRow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,81 +3,55 @@ import { ThemeProvider } from '@mui/material/styles';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import TestRouter from '__tests__/util/TestRouter';
import { GqlMockedProvider, gqlMock } from '__tests__/util/graphqlMocking';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { AppealsWrapper } from 'pages/accountLists/[accountListId]/tools/appeals/AppealsWrapper';
import {
ContactRowFragment,
ContactRowFragmentDoc,
} from 'src/components/Contacts/ContactRow/ContactRow.generated';
import theme from 'src/theme';
import {
AppealStatusEnum,
AppealsContext,
AppealsType,
} from '../../AppealsContext/AppealsContext';
import { AppealContactInfoFragment } from '../../AppealsContext/contacts.generated';
import { ContactRow } from './ContactRow';
import { defaultContact } from './ContactRowMock';

const accountListId = 'account-list-1';
const appealId = 'appealId';

const router = {
query: { accountListId },
isReady: true,
};

const contactMock = {
id: 'test-id',
lateAt: null,
name: 'Test, Name',
people: {
nodes: [
{
anniversaryDay: null,
anniversaryMonth: null,
birthdayDay: null,
birthdayMonth: null,
},
],
},
pledgeAmount: null,
pledgeCurrency: 'CAD',
pledgeFrequency: null,
primaryAddress: {
city: 'Any City',
country: null,
postalCode: 'Test',
state: 'TT',
street: '1111 Test Street',
updatedAt: new Date('2021-06-21T03:40:05-06:00').toISOString(),
},
starred: false,
status: null,
uncompletedTasksCount: 0,
};

const contact = gqlMock<ContactRowFragment>(ContactRowFragmentDoc, {
mocks: contactMock,
});

const setContactFocus = jest.fn();
const contactDetailsOpen = true;
const toggleSelectionById = jest.fn();
const isRowChecked = jest.fn();

const Components = () => (
type ComponentsProps = {
appealStatus?: AppealStatusEnum;
contact?: AppealContactInfoFragment;
};
const Components = ({
appealStatus = AppealStatusEnum.Asked,
contact = defaultContact,
}: ComponentsProps) => (
<TestRouter router={router}>
<GqlMockedProvider>
<ThemeProvider theme={theme}>
<AppealsWrapper>
<AppealsContext.Provider
value={
{
appealId,
setContactFocus,
isRowChecked,
contactDetailsOpen,
toggleSelectionById,
} as unknown as AppealsType
}
>
<ContactRow contact={contact} />
<ContactRow contact={contact} appealStatus={appealStatus} />
</AppealsContext.Provider>
</AppealsWrapper>
</ThemeProvider>
Expand All @@ -90,7 +64,7 @@ describe('ContactsRow', () => {
const { getByText } = render(<Components />);

expect(getByText('Test, Name')).toBeInTheDocument();
expect(getByText('CA$0')).toBeInTheDocument();
expect(getByText('CA$500 Monthly')).toBeInTheDocument();
});

it('should render check event', async () => {
Expand All @@ -103,7 +77,7 @@ describe('ContactsRow', () => {
});

it('should open contact on click', () => {
isRowChecked.mockImplementationOnce((id) => id === contact.id);
isRowChecked.mockImplementationOnce((id) => id === defaultContact.id);

const { getByTestId } = render(<Components />);

Expand All @@ -112,11 +86,11 @@ describe('ContactsRow', () => {
const rowButton = getByTestId('rowButton');
userEvent.click(rowButton);

expect(setContactFocus).toHaveBeenCalledWith(contact.id);
expect(setContactFocus).toHaveBeenCalledWith(defaultContact.id);
});

it('should render contact select event', () => {
isRowChecked.mockImplementationOnce((id) => id === contact.id);
isRowChecked.mockImplementationOnce((id) => id === defaultContact.id);

const { getByTestId } = render(<Components />);

Expand All @@ -125,6 +99,78 @@ describe('ContactsRow', () => {
const rowButton = getByTestId('rowButton');
userEvent.click(rowButton);

expect(setContactFocus).toHaveBeenCalledWith(contact.id);
expect(setContactFocus).toHaveBeenCalledWith(defaultContact.id);
});

describe('Contact Row by status type', () => {
it('Excluded', () => {
isRowChecked.mockImplementationOnce(() => true);

const { getByText } = render(
<Components appealStatus={AppealStatusEnum.Excluded} />,
);

expect(getByText('Reason')).toBeInTheDocument();
expect(getByText('CA$500 Monthly')).toBeInTheDocument();
});

it('Asked', () => {
isRowChecked.mockImplementationOnce(() => true);

const { getByText, queryByText } = render(
<Components appealStatus={AppealStatusEnum.Asked} />,
);

expect(queryByText('Reason')).not.toBeInTheDocument();
expect(getByText('CA$500 Monthly')).toBeInTheDocument();
});

it('Committed', () => {
isRowChecked.mockImplementationOnce(() => true);

const { getByText, queryByText } = render(
<Components appealStatus={AppealStatusEnum.NotReceived} />,
);

expect(queryByText('Reason')).not.toBeInTheDocument();
expect(getByText('$3,000 (Aug 8, 2024)')).toBeInTheDocument();
});

it('Committed - with no pledges', () => {
isRowChecked.mockImplementationOnce(() => true);

const { getByText } = render(
<Components
appealStatus={AppealStatusEnum.NotReceived}
contact={{
...defaultContact,
pledges: [],
}}
/>,
);
expect(getByText('$0')).toBeInTheDocument();
});

it('Received', () => {
isRowChecked.mockImplementationOnce(() => true);

const { getByText, queryByText } = render(
<Components appealStatus={AppealStatusEnum.ReceivedNotProcessed} />,
);

expect(queryByText('Reason')).not.toBeInTheDocument();
expect(getByText('$3,000 (Aug 8, 2024)')).toBeInTheDocument();
});

it('Given', () => {
isRowChecked.mockImplementationOnce(() => true);

const { getByText, queryByText } = render(
<Components appealStatus={AppealStatusEnum.Processed} />,
);

expect(queryByText('Reason')).not.toBeInTheDocument();
expect(getByText('$3,000 ($50) (Jun 25, 2019)')).toBeInTheDocument();
});
});
});
Loading
Loading