Skip to content

Commit d456cb0

Browse files
committed
test(ExpenseFlow): Add E2E for edit expense
1 parent 72a33d8 commit d456cb0

8 files changed

+76
-7
lines changed

components/CollectiveTypePicker.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,15 @@ const CollectiveTypePicker = ({ types, onChange }) => {
3838
return (
3939
<Container display="flex" background="white" justifyContent="space-between">
4040
{types.map(type => (
41-
<StyledButton key={type} flex={buttonFlex} px={2} py={4} borderRadius={8} onClick={() => onChange(type)}>
41+
<StyledButton
42+
key={type}
43+
flex={buttonFlex}
44+
px={2}
45+
py={4}
46+
borderRadius={8}
47+
onClick={() => onChange(type)}
48+
data-cy={`collective-type-picker-${type}`}
49+
>
4250
<Box mb={2}>{getTypeIcon(type)}</Box>
4351
<Span fontSize="Caption">{formatCollectiveType(formatMessage, type)}</Span>
4452
</StyledButton>

components/CreateCollectiveMiniForm.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ const CreateCollectiveMiniForm = ({ type, onCancel, onSuccess, addLoggedInUserAs
206206
const { values, handleSubmit, errors, touched, isSubmitting } = formik;
207207

208208
return (
209-
<Form>
209+
<Form data-cy="create-collective-mini-form">
210210
<H5 fontWeight={600}>{CreateNewMessages[type] ? formatMessage(CreateNewMessages[type]) : null}</H5>
211211
<Box mt={3}>
212212
{(isUser || isOrganization) && (

components/StyledDropzone.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const StyledDropzone = ({
101101
accept,
102102
minSize,
103103
maxSize,
104+
name,
104105
error,
105106
value,
106107
isMulti,
@@ -156,7 +157,7 @@ const StyledDropzone = ({
156157
size={size}
157158
error={error}
158159
>
159-
<input {...getInputProps()} />
160+
<input name={name} {...getInputProps()} />
160161
{isLoading || isUploading ? (
161162
<Container
162163
position="relative"
@@ -230,6 +231,8 @@ const StyledDropzone = ({
230231
StyledDropzone.propTypes = {
231232
/** Called back with the uploaded files on success */
232233
onSuccess: PropTypes.func,
234+
/** Name for the input */
235+
name: PropTypes.string,
233236
/** Called back with the rejectd files */
234237
onReject: PropTypes.func,
235238
/** Content to show inside the dropzone. Defaults to message "Drag and drop one or..." */

components/TemporaryNotification.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,13 @@ const TemporaryNotification = ({ children, position, onDismiss }) => {
4848
}
4949

5050
return (
51-
<Notification position={position}>
51+
<Notification position={position} data-cy="temporary-notification">
5252
<Box mr="auto" />
5353
<Box>{children}</Box>
5454
<Box ml="auto">
5555
<DismissButton
5656
ml={2}
57+
data-cy="dismiss-temporary-notification-btn"
5758
onClick={() => {
5859
setDismissed(true);
5960
if (onDismiss) {

components/expenses/ExpenseAdminActions.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const ExpenseAdminActions = ({ expense, collective, permissions, onError, onEdit
8080
</ButtonLabel>
8181
</ButtonWithLabel>
8282
{permissions?.canEdit && (
83-
<ButtonWithLabel onClick={onEdit} disabled={isDisabled}>
83+
<ButtonWithLabel onClick={onEdit} disabled={isDisabled} data-cy="edit-expense-btn">
8484
<IconEdit size={16} />
8585
<ButtonLabel>
8686
<FormattedMessage id="Edit" defaultMessage="Edit" />

components/expenses/ExpenseForm.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,13 @@ const ExpenseFormBody = ({ formik, payoutProfiles, collective, autoFocusTitle, o
220220
{formatMessage(isReceipt ? msg.step1 : msg.step1Invoice)}
221221
</Span>
222222
<StyledHr flex="1" borderColor="black.300" mx={2} />
223-
<StyledButton buttonSize="tiny" type="button" onClick={() => addNewExpenseItem(formik)} minWidth={135}>
223+
<StyledButton
224+
buttonSize="tiny"
225+
type="button"
226+
onClick={() => addNewExpenseItem(formik)}
227+
minWidth={135}
228+
data-cy="expense-add-item-btn"
229+
>
224230
+&nbsp;{formatMessage(isReceipt ? msg.addNewReceipt : msg.addNewItem)}
225231
</StyledButton>
226232
</Flex>
@@ -259,6 +265,7 @@ const ExpenseFormBody = ({ formik, payoutProfiles, collective, autoFocusTitle, o
259265
inputId={id}
260266
collectives={payoutProfiles}
261267
getDefaultOptions={build => values.payee && build(values.payee)}
268+
data-cy="select-expense-payee"
262269
onChange={({ value }) => {
263270
formik.setFieldValue('payee', value);
264271
formik.setFieldValue('payoutMethod', null);

components/expenses/ExpenseItemForm.js

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ const ExpenseItemForm = ({ attachment, errors, onRemove, currency, requireFile,
106106
>
107107
<StyledDropzone
108108
{...attachmentDropzoneParams}
109+
data-cy={`${field.name}-dropzone`}
110+
name={field.name}
109111
isMulti={false}
110112
error={meta.error}
111113
onSuccess={url => form.setFieldValue(field.name, url)}

test/cypress/integration/27-expenses.create.test.js renamed to test/cypress/integration/27-expenses.test.js

+49-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'cypress-file-upload';
2+
import { randomEmail } from '../support/faker';
23
const random = Math.round(Math.random() * 100000);
34
const expenseDescription = `New expense ${random}`;
45

@@ -47,7 +48,7 @@ describe('New expense flow', () => {
4748
cy.getByDataCy('expense-create-help').should('not.exist');
4849
});
4950

50-
it('submits new expense ', () => {
51+
it('submits new expense then edit it', () => {
5152
cy.getByDataCy('radio-expense-type-RECEIPT').click();
5253
cy.get('input[name="description"]').type('Brussels January team retreat');
5354

@@ -92,8 +93,55 @@ describe('New expense flow', () => {
9293
cy.getByDataCy('expense-summary-items').should('contain', 'Fancy restaurant');
9394
cy.getByDataCy('expense-summary-items').should('contain', 'Potatoes for the giant raclette');
9495

96+
// Submit!
9597
cy.getByDataCy('submit-expense-btn').click();
98+
cy.contains('[data-cy="temporary-notification"]', 'Expense submited!');
9699
cy.contains('[data-cy="expense-page-content"]', 'Brussels January team retreat');
100+
cy.getByDataCy('dismiss-temporary-notification-btn').click();
101+
cy.getByDataCy('temporary-notification').should('not.exist');
102+
103+
// Start editing
104+
cy.getByDataCy('edit-expense-btn').click();
105+
cy.get('input[name="description"]').type(' edited');
106+
cy.get('input[name="items[0].description"]').type(' but not too expensive');
107+
cy.get('input[name="items[0].amount"]').type('{selectall}111');
108+
// Add new item
109+
cy.getByDataCy('expense-add-item-btn').click();
110+
cy.get('input[name="items[2].description"]').type('Some more delicious stuff');
111+
cy.get('input[name="items[2].amount"]').type('{selectall}34');
112+
cy.fixture('images/receipt.jpg').then(fileContent => {
113+
cy.getByDataCy('items[2].url-dropzone').upload(
114+
[{ fileContent, fileName: `receipt2.jpg`, mimeType: 'image/jpeg' }],
115+
{ subjectType: 'drag-n-drop' },
116+
);
117+
});
118+
// Change payee - use a new organization
119+
cy.getByDataCy('select-expense-payee').click();
120+
cy.getByDataCy('collective-type-picker-ORGANIZATION').click();
121+
cy.getByDataCy('create-collective-mini-form').then($form => {
122+
cy.wrap($form).find('input[name="members[0].member.email"]').type(randomEmail());
123+
cy.wrap($form).find('input[name="members[0].member.name"]').type('Jack');
124+
cy.wrap($form).find('input[name="name"]').type('PayeeOrg');
125+
cy.wrap($form).find('button[type="submit"]').click();
126+
});
127+
cy.getByDataCy('create-collective-mini-form').should('not.exist'); // Wait for form to be submitted
128+
cy.getByDataCy('payout-method-select').click();
129+
cy.contains('[data-cy="select-option"]', 'New PayPal account').click();
130+
cy.get('input[name="payoutMethod.data.email"]').type('paypal-test-2@opencollective.com');
131+
cy.getByDataCy('expense-summary-btn').click();
132+
cy.getByDataCy('submit-expense-btn').click();
133+
cy.getByDataCy('submit-expense-btn').should('not.exist'); // wait for form to be submitted
134+
135+
// Check final expense page
136+
cy.contains('[data-cy="expense-page-content"]', 'Brussels January team retreat edited');
137+
cy.getByDataCy('expense-summary-payee').should('contain', 'PayeeOrg');
138+
cy.getByDataCy('expense-summary-host').should('contain', 'Open Source Collective org');
139+
cy.getByDataCy('expense-summary-payout-method-data').should('contain', 'paypal-test-2@opencollective.com');
140+
cy.getByDataCy('expense-summary-payout-method-type').should('contain', 'PayPal');
141+
cy.getByDataCy('expense-items-total-amount').should('contain', '$237.50 USD');
142+
cy.getByDataCy('expense-summary-items').should('contain', 'Fancy restaurant');
143+
cy.getByDataCy('expense-summary-items').should('contain', 'Potatoes for the giant raclette');
144+
cy.getByDataCy('expense-summary-items').should('contain', 'Some more delicious stuff');
97145
});
98146

99147
// This can happen if you start with an invoice then switch to receipts

0 commit comments

Comments
 (0)