Skip to content

Commit 8ca1527

Browse files
mountinycursoragent
andcommitted
Fix ESLint import alias and preserve Formula placeholder for invalid currency
- Use relative './Log' / '@libs/Log' instead of '@src/libs/Log' to satisfy @dword-design/import-alias/prefer-alias rule for files inside src/libs. - Extract isValidCurrencyCode helper from sanitizeCurrencyCode in CurrencyUtils.ts and export it for callers that need to gate behavior on currency validity rather than transparently fall back to USD. - Use isValidCurrencyCode in Formula.formatAmount to keep the original semantic of returning an empty string (which surfaces the formula placeholder upstream) when the source or display currency is malformed, instead of silently formatting as USD. Restores the 'invalid source currency - should return placeholder' Jest expectation in FormulaTest that previously relied on Intl.NumberFormat throwing. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent c7a0ee6 commit 8ca1527

3 files changed

Lines changed: 23 additions & 5 deletions

File tree

src/libs/CurrencyUtils.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Onyx from 'react-native-onyx';
22
import CONST from '@src/CONST';
33
import IntlStore from '@src/languages/IntlStore';
4-
import Log from '@src/libs/Log';
54
import type {OnyxValues} from '@src/ONYXKEYS';
65
import ONYXKEYS from '@src/ONYXKEYS';
76
import type {Locale} from '@src/types/onyx';
7+
import Log from './Log';
88
import {format, formatToParts} from './NumberFormatUtils';
99

1010
let currencyList: OnyxValues[typeof ONYXKEYS.CURRENCY_LIST] = {};
@@ -21,12 +21,20 @@ Onyx.connect({
2121
});
2222

2323
/**
24-
* Validates a currency code and returns it unchanged if it is a valid ISO 4217 code (exactly 3 uppercase ASCII letters).
24+
* Returns true when the provided value is a syntactically valid ISO 4217 currency code
25+
* (exactly 3 uppercase ASCII letters).
26+
*/
27+
function isValidCurrencyCode(currencyCode: string | undefined | null): currencyCode is string {
28+
return typeof currencyCode === 'string' && /^[A-Z]{3}$/.test(currencyCode);
29+
}
30+
31+
/**
32+
* Validates a currency code and returns it unchanged if it is a valid ISO 4217 code.
2533
* Returns CONST.CURRENCY.USD and logs a warning when the code is malformed or missing, to prevent Intl.NumberFormat
2634
* from throwing a RangeError. See https://github.com/Expensify/App/issues/91113
2735
*/
2836
function sanitizeCurrencyCode(currencyCode: string): string {
29-
if (/^[A-Z]{3}$/.test(currencyCode)) {
37+
if (isValidCurrencyCode(currencyCode)) {
3038
return currencyCode;
3139
}
3240
Log.warn('CurrencyUtils: invalid currency code, defaulting to USD', {currencyCode});
@@ -209,6 +217,7 @@ function convertToDisplayStringWithoutCurrency(amountInCents: number, currency:
209217
}
210218

211219
export {
220+
isValidCurrencyCode,
212221
sanitizeCurrencyCode,
213222
getCurrencyDecimals,
214223
getCurrencyUnit,

src/libs/Formula.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {ValueOf} from 'type-fest';
44
import CONST from '@src/CONST';
55
import type {PersonalDetails, Policy, PolicyReportField, Report, Transaction} from '@src/types/onyx';
66
import {isEmptyObject} from '@src/types/utils/EmptyObject';
7-
import {convertToDisplayString, convertToDisplayStringWithoutCurrency} from './CurrencyUtils';
7+
import {convertToDisplayString, convertToDisplayStringWithoutCurrency, isValidCurrencyCode} from './CurrencyUtils';
88
import formatDate from './FormulaDatetime';
99
import getBase62ReportID from './getBase62ReportID';
1010
import Log from './Log';
@@ -580,10 +580,19 @@ function formatAmount(amount: number | undefined, currency: string | undefined,
580580
return null;
581581
}
582582

583+
// Return empty string for an unrecognized display currency so the placeholder is preserved upstream.
584+
if (!isValidCurrencyCode(trimmedDisplayCurrency)) {
585+
return '';
586+
}
587+
583588
return convertToDisplayString(absoluteAmount, trimmedDisplayCurrency);
584589
}
585590

586591
if (currency) {
592+
// Return empty string for an unrecognized source currency so the placeholder is preserved upstream.
593+
if (!isValidCurrencyCode(currency)) {
594+
return '';
595+
}
587596
return convertToDisplayString(absoluteAmount, currency, true);
588597
}
589598

src/libs/NumberFormatUtils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import intlPolyfill from '@libs/IntlPolyfill';
2+
import Log from '@libs/Log';
23
import memoize from '@libs/memoize';
34
import CONST from '@src/CONST';
4-
import Log from '@src/libs/Log';
55
import type Locale from '@src/types/onyx/Locale';
66

77
// Polyfill the Intl API if locale data is not as expected

0 commit comments

Comments
 (0)