Skip to content

Commit 1bd7fc4

Browse files
MelvinBotrojiphil
andcommitted
Add unit tests for pending-delete transaction filtering
Add tests verifying that action determination functions behave correctly when transactions with pendingAction='delete' are filtered out (as done by MoneyReportHeader): - getReportPrimaryAction returns '' when all transactions are pending-delete (empty filtered array) - getReportPrimaryAction returns SUBMIT when non-pending-delete transactions remain - getReportPrimaryAction returns '' for approve-eligible reports when all transactions are pending-delete - getSecondaryReportActions excludes SUBMIT when all transactions are pending-delete and total is 0 - getSecondaryReportActions excludes APPROVE when all transactions are pending-delete - getSecondaryReportActions includes SUBMIT when non-pending-delete transactions remain Co-authored-by: Roji Philip <rojiphil@users.noreply.github.com>
1 parent 706d39d commit 1bd7fc4

2 files changed

Lines changed: 213 additions & 0 deletions

File tree

tests/unit/ReportPrimaryActionUtilsTest.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,116 @@ describe('getPrimaryAction', () => {
8686
).toBe('');
8787
});
8888

89+
it('should return empty string when all transactions are pending delete', async () => {
90+
const report = {
91+
reportID: REPORT_ID,
92+
type: CONST.REPORT.TYPE.EXPENSE,
93+
ownerAccountID: CURRENT_USER_ACCOUNT_ID,
94+
stateNum: CONST.REPORT.STATE_NUM.OPEN,
95+
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
96+
} as unknown as Report;
97+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report);
98+
const policy = {
99+
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE,
100+
};
101+
// When all transactions are pending delete, passing an empty filtered array should return ''
102+
expect(
103+
getReportPrimaryAction({
104+
currentUserLogin: CURRENT_USER_EMAIL,
105+
currentUserAccountID: CURRENT_USER_ACCOUNT_ID,
106+
report,
107+
chatReport,
108+
reportTransactions: [],
109+
violations: {},
110+
bankAccountList: {},
111+
policy: policy as Policy,
112+
isChatReportArchived: false,
113+
}),
114+
).toBe('');
115+
116+
// Confirm the same report would return SUBMIT if non-pending-delete transactions are present
117+
const normalTransaction = {
118+
reportID: `${REPORT_ID}`,
119+
} as unknown as Transaction;
120+
expect(
121+
getReportPrimaryAction({
122+
currentUserLogin: CURRENT_USER_EMAIL,
123+
currentUserAccountID: CURRENT_USER_ACCOUNT_ID,
124+
report,
125+
chatReport,
126+
reportTransactions: [normalTransaction],
127+
violations: {},
128+
bankAccountList: {},
129+
policy: policy as Policy,
130+
isChatReportArchived: false,
131+
}),
132+
).toBe(CONST.REPORT.PRIMARY_ACTIONS.SUBMIT);
133+
});
134+
135+
it('should return SUBMIT when only non-pending-delete transactions remain after filtering', async () => {
136+
const report = {
137+
reportID: REPORT_ID,
138+
type: CONST.REPORT.TYPE.EXPENSE,
139+
ownerAccountID: CURRENT_USER_ACCOUNT_ID,
140+
stateNum: CONST.REPORT.STATE_NUM.OPEN,
141+
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
142+
} as unknown as Report;
143+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report);
144+
const policy = {
145+
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE,
146+
};
147+
148+
// Simulate the filtering that MoneyReportHeader does: only non-pending-delete transactions are passed
149+
const normalTransaction = {
150+
reportID: `${REPORT_ID}`,
151+
} as unknown as Transaction;
152+
153+
expect(
154+
getReportPrimaryAction({
155+
currentUserLogin: CURRENT_USER_EMAIL,
156+
currentUserAccountID: CURRENT_USER_ACCOUNT_ID,
157+
report,
158+
chatReport,
159+
reportTransactions: [normalTransaction],
160+
violations: {},
161+
bankAccountList: {},
162+
policy: policy as Policy,
163+
isChatReportArchived: false,
164+
}),
165+
).toBe(CONST.REPORT.PRIMARY_ACTIONS.SUBMIT);
166+
});
167+
168+
it('should return empty string for approve-eligible report when all transactions are pending delete', async () => {
169+
const report = {
170+
reportID: REPORT_ID,
171+
type: CONST.REPORT.TYPE.EXPENSE,
172+
ownerAccountID: CURRENT_USER_ACCOUNT_ID,
173+
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
174+
statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
175+
managerID: CURRENT_USER_ACCOUNT_ID,
176+
} as unknown as Report;
177+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report);
178+
const policy = {
179+
approver: CURRENT_USER_EMAIL,
180+
approvalMode: CONST.POLICY.APPROVAL_MODE.BASIC,
181+
};
182+
183+
// When all transactions are pending delete (filtered to empty), approve should not be available
184+
expect(
185+
getReportPrimaryAction({
186+
currentUserLogin: CURRENT_USER_EMAIL,
187+
currentUserAccountID: CURRENT_USER_ACCOUNT_ID,
188+
report,
189+
chatReport,
190+
reportTransactions: [],
191+
violations: {},
192+
bankAccountList: {},
193+
policy: policy as Policy,
194+
isChatReportArchived: false,
195+
}),
196+
).toBe('');
197+
});
198+
89199
it('should return SUBMIT for expense report with manual submit', async () => {
90200
const report = {
91201
reportID: REPORT_ID,

tests/unit/ReportSecondaryActionUtilsTest.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,109 @@ describe('getSecondaryAction', () => {
13011301
expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.HOLD)).toBe(true);
13021302
});
13031303

1304+
it('should not include SUBMIT option when all transactions are pending delete and total is 0', async () => {
1305+
const report = {
1306+
reportID: REPORT_ID,
1307+
type: CONST.REPORT.TYPE.EXPENSE,
1308+
ownerAccountID: EMPLOYEE_ACCOUNT_ID,
1309+
stateNum: CONST.REPORT.STATE_NUM.OPEN,
1310+
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
1311+
total: 0,
1312+
} as unknown as Report;
1313+
const policy = {
1314+
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT,
1315+
harvesting: {
1316+
enabled: true,
1317+
},
1318+
type: CONST.POLICY.TYPE.CORPORATE,
1319+
} as unknown as Policy;
1320+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report);
1321+
1322+
// When all transactions are pending delete (filtered to empty array and total is 0), SUBMIT should not be available
1323+
const result = getSecondaryReportActions({
1324+
currentUserLogin: EMPLOYEE_EMAIL,
1325+
currentUserAccountID: EMPLOYEE_ACCOUNT_ID,
1326+
report,
1327+
chatReport,
1328+
reportTransactions: [],
1329+
originalTransaction: {} as Transaction,
1330+
violations: {},
1331+
bankAccountList: {},
1332+
policy,
1333+
});
1334+
expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.SUBMIT)).toBe(false);
1335+
});
1336+
1337+
it('should not include APPROVE option when all transactions are pending delete', async () => {
1338+
const report = {
1339+
reportID: REPORT_ID,
1340+
type: CONST.REPORT.TYPE.EXPENSE,
1341+
ownerAccountID: EMPLOYEE_ACCOUNT_ID,
1342+
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
1343+
statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
1344+
managerID: EMPLOYEE_ACCOUNT_ID,
1345+
} as unknown as Report;
1346+
const policy = {
1347+
approver: EMPLOYEE_EMAIL,
1348+
} as unknown as Policy;
1349+
1350+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report);
1351+
1352+
// When all transactions are pending delete (filtered to empty array), APPROVE should not be available
1353+
const result = getSecondaryReportActions({
1354+
currentUserLogin: EMPLOYEE_EMAIL,
1355+
currentUserAccountID: EMPLOYEE_ACCOUNT_ID,
1356+
report,
1357+
chatReport,
1358+
reportTransactions: [],
1359+
originalTransaction: {} as Transaction,
1360+
violations: {},
1361+
bankAccountList: {},
1362+
policy,
1363+
});
1364+
expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.APPROVE)).toBe(false);
1365+
});
1366+
1367+
it('should include SUBMIT when some transactions remain after filtering out pending-delete ones', async () => {
1368+
const report = {
1369+
reportID: REPORT_ID,
1370+
type: CONST.REPORT.TYPE.EXPENSE,
1371+
ownerAccountID: EMPLOYEE_ACCOUNT_ID,
1372+
stateNum: CONST.REPORT.STATE_NUM.OPEN,
1373+
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
1374+
total: 10,
1375+
} as unknown as Report;
1376+
const policy = {
1377+
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT,
1378+
harvesting: {
1379+
enabled: true,
1380+
},
1381+
type: CONST.POLICY.TYPE.CORPORATE,
1382+
} as unknown as Policy;
1383+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report);
1384+
1385+
// Simulate the MoneyReportHeader filtering: only non-pending-delete transaction is passed
1386+
const normalTransaction = {
1387+
transactionID: 'TRANSACTION_ID_NORMAL',
1388+
amount: 10,
1389+
merchant: 'Merchant',
1390+
date: '2025-01-01',
1391+
} as unknown as Transaction;
1392+
1393+
const result = getSecondaryReportActions({
1394+
currentUserLogin: EMPLOYEE_EMAIL,
1395+
currentUserAccountID: EMPLOYEE_ACCOUNT_ID,
1396+
report,
1397+
chatReport,
1398+
reportTransactions: [normalTransaction],
1399+
originalTransaction: {} as Transaction,
1400+
violations: {},
1401+
bankAccountList: {},
1402+
policy,
1403+
});
1404+
expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.SUBMIT)).toBe(true);
1405+
});
1406+
13041407
it('does not include CHANGE_WORKSPACE option for submitted IOU report and manager being the payer of the new policy', async () => {
13051408
const report = {
13061409
reportID: REPORT_ID,

0 commit comments

Comments
 (0)