Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6d720bf
Apply currency default tax rate when currency changes in create flow
MelvinBot Jun 24, 2026
624bad3
Add unit tests for currency-change tax recompute in create flow
MelvinBot Jun 24, 2026
f9b8a90
Fix lint in AmountSubmission tax tests
MelvinBot Jun 24, 2026
03379fd
Re-apply currency default tax on confirmation page for FAB flow
MelvinBot Jul 6, 2026
58a7fad
Revert "Re-apply currency default tax on confirmation page for FAB flow"
MelvinBot Jul 6, 2026
cbb2c74
Resolve participant workspace policy on amount step for FAB flow
MelvinBot Jul 6, 2026
c70c504
Merge remote-tracking branch 'origin/main' into claude-foreignTaxNotA…
MelvinBot Jul 6, 2026
a1b56ec
Fix Oxfmt: sort imports in AmountSubmissionTest
MelvinBot Jul 6, 2026
1e6c3b1
Preserve manually selected tax rate on edit-flow currency change
MelvinBot Jul 6, 2026
29ce74d
Gate create-flow tax recompute on tax tracking and heal invalid tax c…
MelvinBot Jul 6, 2026
6bd27a3
Recognize FAB-flow workspace via participant in tax recompute gate
MelvinBot Jul 6, 2026
56d8dbc
Re-apply currency default tax rate on confirmation page for the FAB c…
MelvinBot Jul 6, 2026
0060acc
Revert "Re-apply currency default tax rate on confirmation page for t…
MelvinBot Jul 6, 2026
f82d957
Extract isTaxCodeAutoDefaultForCurrency helper to dedupe tax-default …
MelvinBot Jul 6, 2026
a01f421
Heal only missing tax codes on edit, preserving codes with drifted va…
MelvinBot Jul 6, 2026
37106dd
Preserve intentionally-cleared tax on amount edit
MelvinBot Jul 6, 2026
7ab258e
Preserve intentionally-cleared tax on currency change in shared heal
MelvinBot Jul 7, 2026
cd71be8
Trim helper JSDoc to explain the why, not where it is used
MelvinBot Jul 7, 2026
edd77b0
Remove verbose tax-tracking gate comment per review
MelvinBot Jul 7, 2026
2aa7c6c
Remove verbose comment on create-path tax recompute
MelvinBot Jul 7, 2026
7117f3d
Remove verbose edit-path and policyID comments per review
MelvinBot Jul 7, 2026
c166047
Merge remote-tracking branch 'origin/main' into claude-foreignTaxNotA…
MelvinBot Jul 7, 2026
dd52b39
Merge remote-tracking branch 'origin/main' into claude-foreignTaxNotA…
MelvinBot Jul 15, 2026
1ee4be6
Merge remote-tracking branch 'origin/main' into claude-foreignTaxNotA…
MelvinBot Jul 20, 2026
927d463
Include track-expense tax contexts in the currency-change tax recompu…
MelvinBot Jul 20, 2026
5696f8b
Add empty line before tax contexts comment per review feedback
MelvinBot Jul 21, 2026
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
52 changes: 46 additions & 6 deletions src/libs/IOUAmountSubmission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ import {rand64} from './NumberUtils';
import {getParticipantsOption, getReportOption} from './OptionsListUtils';
import Permissions from './Permissions';
import {getLoginByAccountID} from './PersonalDetailsUtils';
import {getPolicyExpenseChat, getTransactionDetails, isMoneyRequestReport, isSelfDM, shouldEnableNegative} from './ReportUtils';
import {isTaxTrackingEnabled} from './PolicyUtils';
import {getPolicyExpenseChat, getTransactionDetails, isMoneyRequestReport, isPolicyExpenseChat, isSelfDM, shouldEnableNegative} from './ReportUtils';
import shouldUseDefaultExpensePolicy from './shouldUseDefaultExpensePolicy';
import {calculateTaxAmount, getAmount, getCurrency, getDefaultTaxCode, getIsFromGlobalCreate, getTaxValue, hasReceipt} from './TransactionUtils';
import {calculateTaxAmount, getAmount, getCurrency, getDefaultTaxCode, getIsFromGlobalCreate, getTaxValue, hasReceipt, isExpenseUnreported} from './TransactionUtils';

type SubmitAmountArgs = {
report: OnyxEntry<OnyxTypes.Report>;
Expand Down Expand Up @@ -136,6 +137,23 @@ function getIsP2PForAmount({chatReportForP2P, currentUserAccountID}: GetIsP2PFor
return isParticipantP2P(firstParticipant);
}

/**
* Determines whether a transaction's current tax code is still the auto-applied default for the given currency
* (i.e. the user has not manually picked a different rate).
*/
function isTaxCodeAutoDefaultForCurrency(
policy: OnyxEntry<OnyxTypes.Policy>,
transaction: OnyxEntry<OnyxTypes.Transaction>,
currency: string | undefined,
taxCode: string | undefined,
): boolean {
if (taxCode === '') {
return false;
}
const defaultTaxCodeForCurrency = getDefaultTaxCode(policy, transaction, currency);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we preserve an intentionally cleared tax here? taxCode === '' is how the create flow stores tax cleared, and the edit path below already treats '' as a legitimate cleared tax.

Suggested change
const defaultTaxCodeForCurrency = getDefaultTaxCode(policy, transaction, currency);
if (taxCode === '') {
return false;
}
const defaultTaxCodeForCurrency = getDefaultTaxCode(policy, transaction, currency);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MelvinBot Let's implement this one

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — pushed in 7ab258e.

isTaxCodeAutoDefaultForCurrency now short-circuits on an empty tax code:

if (taxCode === '') {
    return false;
}

An empty string is an intentional "no tax" selection, so treating it as not auto-default means a currency change no longer heals it back to the new currency's default — it's preserved. Without the guard the trailing !taxCode check counted '' as auto-default, which is exactly the wipe you flagged. This matches how the edit path already treats '' as a legitimate cleared tax. Both call sites (create at AmountSubmission.ts:298 and edit at AmountSubmission.ts:567) go through this helper, so the fix applies to both flows.

Heads up: I couldn't run lint/typecheck/jest in this environment (the App ESLint config OOMs here and the test runner is sandbox-gated), so please run npm run typecheck + npx jest tests/unit/AmountSubmissionTest.ts locally before marking ready. The change itself is a 3-line guard on a pure helper with no new imports.

return !taxCode || taxCode === defaultTaxCodeForCurrency;
}

type SubmitAmountContext = {
isEditing: boolean;
isCreateAction: boolean;
Expand Down Expand Up @@ -491,8 +509,26 @@ function submitCreateAmount(args: SubmitAmountArgs, ctx: SubmitAmountContext): v

setMoneyRequestAmount(transactionID, amountInSmallestCurrencyUnits, selectedCurrency || CONST.CURRENCY.USD, shouldKeepUserInput, hasReceipt(transaction));

if (isMovingTransactionFromTrackExpense(action)) {
const taxCode = selectedCurrency !== policy?.outputCurrency ? policy?.taxRates?.foreignTaxDefault : policy?.taxRates?.defaultExternalID;
// When the currency changes, re-apply the default tax rate for the new currency so the confirmation page and the
// created expense reflect the currency-appropriate default (e.g. the foreign default for a foreign currency).
// Only do this when the current tax code is still the auto-applied default for the previous currency, so a tax
// rate the user manually selected is preserved across the currency change.
const previousCurrency = getCurrency(transaction);
const isCurrentTaxAutoDefault = isTaxCodeAutoDefaultForCurrency(policy, transaction, previousCurrency, transaction?.taxCode);
const isPolicyExpenseChatParticipant = transaction?.participants?.some((participant) => participant.isPolicyExpenseChat) ?? false;

// Mirror the tax contexts the confirmation list uses (see MoneyRequestConfirmationList's shouldShowTax): a Track

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: put an empty line before the comment, can you handle that as a follow-up @Eskalifer1 please?

Suggested change
// Mirror the tax contexts the confirmation list uses (see MoneyRequestConfirmationList's shouldShowTax): a Track
// Mirror the tax contexts the confirmation list uses (see MoneyRequestConfirmationList's shouldShowTax): a Track

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

@MelvinBot Let's apply this change

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — pushed in 5696f8b. Added the empty line before the // Mirror the tax contexts… comment as suggested.

// expense from a self-DM/default workspace isn't a policy expense chat, but the confirmation page still shows tax
// for the track flow, so the currency recompute must run for it too. Otherwise Back → change currency → Next would
// leave the stale previous-currency default tax on the draft.
const isTaxEnabled = isTaxTrackingEnabled(
isPolicyExpenseChat(report) || isPolicyExpenseChatParticipant || iouType === CONST.IOU.TYPE.TRACK || isExpenseUnreported(transaction),
policy,
false,
);

if (isMovingTransactionFromTrackExpense(action) || (isTaxEnabled && selectedCurrency !== previousCurrency && isCurrentTaxAutoDefault)) {
const taxCode = getDefaultTaxCode(policy, transaction, selectedCurrency);
if (taxCode) {
setMoneyRequestTaxRate(transactionID, taxCode);
const taxPercentage = getTaxValue(policy, transaction, taxCode) ?? '';
Expand Down Expand Up @@ -551,10 +587,14 @@ function submitEditAmount(args: SubmitAmountArgs, ctx: SubmitAmountContext): voi
return;
}

// If currency has changed, then we get the default tax rate based on currency, otherwise we use the current tax rate selected in transaction, if we have it.
// When the currency changes we re-apply the new currency's default tax rate, but only when the current tax rate is
// still the auto-applied default for the previous currency. A tax rate the user picked manually is preserved across
// the currency change (mirrors the create-flow guard in `submitCreateAmount`).
const transactionTaxCode = getTransactionDetails(currentTransaction)?.taxCode;
const defaultTaxCode = getDefaultTaxCode(policy, currentTransaction, selectedCurrency) ?? '';
const taxCode = (selectedCurrency !== transactionCurrency ? defaultTaxCode : transactionTaxCode) ?? defaultTaxCode;
const isCurrentTaxAutoDefault = isTaxCodeAutoDefaultForCurrency(policy, currentTransaction, transactionCurrency, transactionTaxCode);
const isTransactionTaxCodeValid = transactionTaxCode === '' || getTaxValue(policy, currentTransaction, transactionTaxCode ?? '') !== undefined;
const taxCode = ((selectedCurrency !== transactionCurrency && isCurrentTaxAutoDefault) || !isTransactionTaxCodeValid ? defaultTaxCode : transactionTaxCode) ?? defaultTaxCode;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve intentionally cleared tax codes

When an edited expense has an intentionally blank tax code, e.g. after the tax was cleared from the tax-rate editor, getTaxValue(policy, currentTransaction, '') is undefined, so this new fallback treats the blank value as invalid and sends defaultTaxCode on the next amount/currency save even when the currency did not change. The previous logic preserved '' because it only fell back for nullish values, so this silently re-adds the workspace default tax to expenses whose tax was explicitly cleared.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MelvinBot What do you think about this one? Don't make any changes yet

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the bot — this is a valid P2 regression, not a false positive. No changes made, per your note.

Why it's real: an intentionally-cleared tax (taxCode === '') is a persisted state, reachable from:

At AmountSubmission.ts:567-568, getTaxValue(policy, tx, '') is undefined, so isTransactionTaxCodeValid is false and the new || !isTransactionTaxCodeValid branch forces taxCode = defaultTaxCode — even with no currency change. The old transactionTaxCode ?? defaultTaxCode preserved '' (it's not nullish). So editing only the amount of a cleared-tax expense silently re-adds the workspace default tax. Repro: clear the tax on an expense → edit its amount (same currency) → default tax reappears.

Suggested direction (for when you do change it): treat empty string as a legitimate selection and only "heal" a non-empty code that no longer resolves:

const isTransactionTaxCodeValid = transactionTaxCode === '' || getTaxValue(policy, currentTransaction, transactionTaxCode ?? '') !== undefined;

That keeps the deleted/moved-workspace heal you added (non-empty codes that don't resolve still fall back) while preserving an explicit "no tax". Worth a unit test for the cleared-tax + amount-edit case alongside it.

One thing to decide: whether a cleared tax should also survive a currency change. With the guard above it does ('' isn't the auto-default for the previous currency, so isCurrentTaxAutoDefault is false too) — which I think is the right call, since re-adding tax the user deliberately removed would be surprising. Flag if you'd rather it re-default on currency change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MelvinBot let's implement this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in 37106dd. Applied the suggested guard so an intentionally-cleared tax (taxCode === '') is treated as a legitimate selection and no longer healed back to the workspace default:

AmountSubmission.ts:568

const isTransactionTaxCodeValid = transactionTaxCode === '' || getTaxValue(policy, currentTransaction, transactionTaxCode ?? '') !== undefined;

This keeps the deleted/moved-workspace heal for non-empty codes that no longer resolve, while preserving an explicit "no tax". As you noted, a cleared tax also correctly survives a currency change ('' isn't the previous currency's auto-default, so isCurrentTaxAutoDefault is false) — which is the intended behavior.

Added a regression unit test for the cleared-tax + amount-edit case at AmountSubmissionTest.ts (asserts taxCode: '' is preserved on a same-currency amount edit — it fails on the old logic).

⚠️ Heads up: I couldn't execute the test suite / typecheck / lint locally in this run (the sandbox blocked the Node toolchain), so I'm relying on CI to validate. If anything goes red, ping me and I'll fix it.

const taxPercentage = getTaxValue(policy, currentTransaction, taxCode) ?? '';
const taxAmount = convertToBackendAmount(calculateTaxAmount(taxPercentage, newAmount, decimals));

Expand Down
3 changes: 2 additions & 1 deletion src/pages/iou/request/step/IOURequestStepAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ function IOURequestStepAmount({
const iouRequestType = getRequestType(transaction);
const isTrackExpense = iouType === CONST.IOU.TYPE.TRACK;
const {policyForMovingExpensesID} = usePolicyForMovingExpenses();
const policyID = isTrackExpense ? policyForMovingExpensesID : report?.policyID;
const participantPolicyID = transaction?.participants?.find((participant) => participant.isPolicyExpenseChat)?.policyID;
const policyID = (isTrackExpense ? policyForMovingExpensesID : report?.policyID) ?? participantPolicyID;

const isReportArchived = useReportIsArchived(report?.reportID);
const isIouReport = isMoneyRequestReport(report);
Expand Down
205 changes: 205 additions & 0 deletions tests/unit/IOUAmountSubmissionTest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {getIsP2PForAmount, submitAmount} from '@libs/IOUAmountSubmission';

import {setMoneyRequestTaxAmount, setMoneyRequestTaxRate} from '@userActions/IOU/MoneyRequest';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails, Policy, Report, Transaction} from '@src/types/onyx';
Expand All @@ -8,6 +10,7 @@ import type {OnyxEntry} from 'react-native-onyx';

import Onyx from 'react-native-onyx';

import createRandomPolicy from '../utils/collections/policies';
import {createRandomReport} from '../utils/collections/reports';
import {translateLocal} from '../utils/TestHelper';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
Expand Down Expand Up @@ -228,6 +231,208 @@ describe('AmountSubmission', () => {
mockSetDraftSplitTransaction.mockClear();
mockUpdateMoneyRequestAmountAndCurrency.mockClear();
mockSetTransactionReport.mockClear();
jest.mocked(setMoneyRequestTaxRate).mockClear();
jest.mocked(setMoneyRequestTaxAmount).mockClear();
});

const taxPolicy: Policy = {
...createRandomPolicy(200, CONST.POLICY.TYPE.TEAM, 'Tax Workspace'),
outputCurrency: CONST.CURRENCY.USD,
tax: {trackingEnabled: true},
taxRates: {
name: 'Tax',
defaultExternalID: 'idDefault',
foreignTaxDefault: 'idForeign',
defaultValue: '5%',
taxes: {
idDefault: {name: 'Default', value: '5%'},
idForeign: {name: 'Foreign', value: '10%'},
idManual: {name: 'Manual', value: '7%'},
},
},
};

// The create-flow tax recompute only runs on a policy expense chat with tax tracking enabled, so tax tests
// start from a workspace chat report (mirrors continuing an expense from a tax-enabled workspace chat).
const taxReport: Report = {
...createRandomReport(100, undefined),
reportID: 'report-100',
chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
policyID: '200',
};

const buildTaxTransaction = (taxCode: string): Transaction => ({
transactionID: 'tx-1',
amount: -1000,
currency: CONST.CURRENCY.USD,
created: '2024-01-01',
merchant: 'Test',
reportID: 'report-100',
comment: {},
taxCode,
});

it('applies the new currency default tax rate on create when currency changes and tax is the auto-applied default', () => {
submitAmount(
buildBaseArgs({
report: taxReport,
action: CONST.IOU.ACTION.CREATE,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
transaction: buildTaxTransaction('idDefault'),
selectedCurrency: CONST.CURRENCY.EUR,
amount: '10',
}),
);

expect(setMoneyRequestTaxRate).toHaveBeenCalledWith('tx-1', 'idForeign');
});

it('preserves a manually selected tax rate on create when currency changes', () => {
submitAmount(
buildBaseArgs({
report: taxReport,
action: CONST.IOU.ACTION.CREATE,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
transaction: buildTaxTransaction('idManual'),
selectedCurrency: CONST.CURRENCY.EUR,
amount: '10',
}),
);

expect(setMoneyRequestTaxRate).not.toHaveBeenCalled();
});

it('does not change the tax rate on create when the currency is unchanged', () => {
submitAmount(
buildBaseArgs({
report: taxReport,
action: CONST.IOU.ACTION.CREATE,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
transaction: buildTaxTransaction('idDefault'),
selectedCurrency: CONST.CURRENCY.USD,
amount: '10',
}),
);

expect(setMoneyRequestTaxRate).not.toHaveBeenCalled();
});

it('does not write a tax code or amount on create when the workspace has tax tracking disabled', () => {
submitAmount(
buildBaseArgs({
report: taxReport,
action: CONST.IOU.ACTION.CREATE,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: {...taxPolicy, tax: {trackingEnabled: false}},
transaction: buildTaxTransaction('idDefault'),
selectedCurrency: CONST.CURRENCY.EUR,
amount: '10',
}),
);

expect(setMoneyRequestTaxRate).not.toHaveBeenCalled();
expect(setMoneyRequestTaxAmount).not.toHaveBeenCalled();
});

it('applies the new currency default tax rate on create from the FAB flow (no report) when the workspace is resolved from the participant', () => {
// Global-create (FAB) flow: there is no report context, so the workspace/tax tracking must be recognized
// from the transaction's selected policy-expense-chat participant instead of from `report`.
submitAmount(
buildBaseArgs({
report: undefined,
action: CONST.IOU.ACTION.CREATE,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
transaction: {...buildTaxTransaction('idDefault'), participants: [{isPolicyExpenseChat: true, policyID: '200'}]},
selectedCurrency: CONST.CURRENCY.EUR,
amount: '10',
}),
);

expect(setMoneyRequestTaxRate).toHaveBeenCalledWith('tx-1', 'idForeign');
});

it('applies the new currency default tax rate on edit when currency changes and tax is the auto-applied default', () => {
submitAmount(
buildBaseArgs({
action: CONST.IOU.ACTION.EDIT,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
transaction: buildTaxTransaction('idDefault'),
selectedCurrency: CONST.CURRENCY.EUR,
amount: '10',
}),
);

expect(mockUpdateMoneyRequestAmountAndCurrency).toHaveBeenCalledWith(expect.objectContaining({taxCode: 'idForeign'}));
});

it('preserves a manually selected tax rate on edit when currency changes', () => {
submitAmount(
buildBaseArgs({
action: CONST.IOU.ACTION.EDIT,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
transaction: buildTaxTransaction('idManual'),
selectedCurrency: CONST.CURRENCY.EUR,
amount: '10',
}),
);

expect(mockUpdateMoneyRequestAmountAndCurrency).toHaveBeenCalledWith(expect.objectContaining({taxCode: 'idManual'}));
});

it('heals a tax code that is not a valid policy rate to the currency default on edit', () => {
submitAmount(
buildBaseArgs({
action: CONST.IOU.ACTION.EDIT,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
transaction: buildTaxTransaction('idNoLongerExists'),
selectedCurrency: CONST.CURRENCY.EUR,
amount: '10',
}),
);

expect(mockUpdateMoneyRequestAmountAndCurrency).toHaveBeenCalledWith(expect.objectContaining({taxCode: 'idForeign'}));
});

it('preserves a tax code whose stored value drifted from the policy on edit (heals only missing codes)', () => {
submitAmount(
buildBaseArgs({
action: CONST.IOU.ACTION.EDIT,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
// The code still exists on the policy, but its stored value is stale (e.g. an admin edited the
// rate's percentage after this expense was created). The currency is unchanged, so the only reason
// to swap the code would be an invalid one — but a drifted value is not invalid, so it is preserved.
transaction: {...buildTaxTransaction('idManual'), taxValue: '3%'},
selectedCurrency: CONST.CURRENCY.USD,
amount: '20',
}),
);

expect(mockUpdateMoneyRequestAmountAndCurrency).toHaveBeenCalledWith(expect.objectContaining({taxCode: 'idManual'}));
});

it('preserves an intentionally-cleared tax (empty code) on edit when only the amount changes', () => {
submitAmount(
buildBaseArgs({
action: CONST.IOU.ACTION.EDIT,
iouType: CONST.IOU.TYPE.SUBMIT,
policy: taxPolicy,
// The user deliberately cleared the tax (`taxCode === ''`). Editing only the amount (same currency)
// must not re-add the workspace default tax — an empty code is a legitimate persisted selection.
transaction: buildTaxTransaction(''),
selectedCurrency: CONST.CURRENCY.USD,
amount: '20',
}),
);

expect(mockUpdateMoneyRequestAmountAndCurrency).toHaveBeenCalledWith(expect.objectContaining({taxCode: ''}));
});

it('calls sendMoneyElsewhere on non-edit + skip-confirm + PAY (non-wallet)', () => {
Expand Down
Loading