@@ -3,11 +3,7 @@ import { useSelector } from 'react-redux';
33
44import { useAssetFiatFormatter } from './useAssetFiatFormatter' ;
55import { useTransactionPayCurrency } from './useTransactionPayCurrency' ;
6- import {
7- selectCurrencyRates ,
8- selectCurrentCurrency ,
9- } from '../../../../../selectors/currencyRateController' ;
10- import { selectEvmNetworkConfigurationsByChainId } from '../../../../../selectors/networkController' ;
6+ import { selectCurrentCurrency } from '../../../../../selectors/currencyRateController' ;
117import { getIntlNumberFormatter } from '../../../../../util/intl' ;
128
139jest . mock ( 'react-redux' , ( ) => ( {
@@ -20,11 +16,6 @@ jest.mock('./useTransactionPayCurrency', () => ({
2016
2117jest . mock ( '../../../../../selectors/currencyRateController' , ( ) => ( {
2218 selectCurrentCurrency : jest . fn ( ) ,
23- selectCurrencyRates : jest . fn ( ) ,
24- } ) ) ;
25-
26- jest . mock ( '../../../../../selectors/networkController' , ( ) => ( {
27- selectEvmNetworkConfigurationsByChainId : jest . fn ( ) ,
2819} ) ) ;
2920
3021jest . mock ( '../../../../../util/intl' , ( ) => ( {
@@ -42,19 +33,9 @@ const mockGetIntlNumberFormatter = jest.mocked(getIntlNumberFormatter);
4233
4334const mockFormatter = { format : jest . fn ( ) } ;
4435
45- function buildState ( {
46- preferredCurrency = 'usd' ,
47- currencyRates = { } as Record <
48- string ,
49- { conversionRate ?: number ; usdConversionRate ?: number }
50- > ,
51- networkConfigs = { } as Record < string , { nativeCurrency : string } > ,
52- } = { } ) {
36+ function buildState ( { preferredCurrency = 'usd' } = { } ) {
5337 mockUseSelector . mockImplementation ( ( selector ) => {
5438 if ( selector === selectCurrentCurrency ) return preferredCurrency ;
55- if ( selector === selectCurrencyRates ) return currencyRates ;
56- if ( selector === selectEvmNetworkConfigurationsByChainId )
57- return networkConfigs ;
5839 return undefined ;
5940 } ) ;
6041}
@@ -69,212 +50,94 @@ describe('useAssetFiatFormatter', () => {
6950 mockFormatter . format . mockImplementation ( ( n ) => `formatted:${ String ( n ) } ` ) ;
7051 } ) ;
7152
72- describe ( 'outside pay flow ' , ( ) => {
73- it ( 'formats using the preferred currency' , ( ) => {
53+ describe ( 'fiatCurrency selection ' , ( ) => {
54+ it ( 'uses the preferred currency outside pay flow ' , ( ) => {
7455 buildState ( { preferredCurrency : 'eur' } ) ;
7556
7657 const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
77- const output = result . current . format ( '100' , '0x1' ) ;
7858
79- expect ( mockGetIntlNumberFormatter ) . toHaveBeenCalledWith (
80- 'en-US' ,
81- expect . objectContaining ( { style : 'currency' , currency : 'eur' } ) ,
82- ) ;
83- expect ( mockFormatter . format ) . toHaveBeenCalledWith ( '100' ) ;
84- expect ( output ) . toBe ( 'formatted:100' ) ;
59+ expect ( result . current . fiatCurrency ) . toBe ( 'eur' ) ;
8560 } ) ;
8661
87- it ( 'exposes the fiatCurrency being used ' , ( ) => {
62+ it ( 'uses the pay currency when useTransactionPayCurrency returns a value ' , ( ) => {
8863 buildState ( { preferredCurrency : 'eur' } ) ;
64+ mockUseTransactionPayCurrency . mockReturnValue ( 'USD' ) ;
8965
9066 const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
91- expect ( result . current . fiatCurrency ) . toBe ( 'eur' ) ;
67+
68+ expect ( result . current . fiatCurrency ) . toBe ( 'USD' ) ;
9269 } ) ;
70+ } ) ;
9371
94- it ( 'uses minimumFractionDigits=0 for integer amounts' , ( ) => {
72+ describe ( 'format' , ( ) => {
73+ it ( 'formats a numeric amount using Intl currency' , ( ) => {
9574 buildState ( { preferredCurrency : 'eur' } ) ;
9675
97- renderHook ( ( ) => useAssetFiatFormatter ( ) ) . result . current . format (
98- '100' ,
99- '0x1' ,
100- ) ;
76+ const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
77+ const output = result . current . format ( '100' ) ;
10178
10279 expect ( mockGetIntlNumberFormatter ) . toHaveBeenCalledWith (
10380 'en-US' ,
104- expect . objectContaining ( { minimumFractionDigits : 0 } ) ,
81+ expect . objectContaining ( { style : 'currency' , currency : 'eur' } ) ,
10582 ) ;
83+ expect ( mockFormatter . format ) . toHaveBeenCalledWith ( '100' ) ;
84+ expect ( output ) . toBe ( 'formatted:100' ) ;
10685 } ) ;
10786
108- it ( 'uses minimumFractionDigits=2 for non-integer amounts ' , ( ) => {
87+ it ( 'formats with the pay currency when in pay flow ' , ( ) => {
10988 buildState ( { preferredCurrency : 'eur' } ) ;
89+ mockUseTransactionPayCurrency . mockReturnValue ( 'USD' ) ;
11090
111- renderHook ( ( ) => useAssetFiatFormatter ( ) ) . result . current . format (
112- '100.5' ,
113- '0x1' ,
114- ) ;
91+ const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
92+ result . current . format ( '110' ) ;
11593
11694 expect ( mockGetIntlNumberFormatter ) . toHaveBeenCalledWith (
11795 'en-US' ,
118- expect . objectContaining ( { minimumFractionDigits : 2 } ) ,
96+ expect . objectContaining ( { currency : 'USD' } ) ,
11997 ) ;
98+ expect ( mockFormatter . format ) . toHaveBeenCalledWith ( '110' ) ;
12099 } ) ;
121100
122- it ( 'treats undefined/null balances as zero ' , ( ) => {
101+ it ( 'uses minimumFractionDigits=0 for integer amounts ' , ( ) => {
123102 buildState ( { preferredCurrency : 'eur' } ) ;
124103
125- renderHook ( ( ) => useAssetFiatFormatter ( ) ) . result . current . format (
126- undefined ,
127- '0x1' ,
128- ) ;
129-
130- expect ( mockFormatter . format ) . toHaveBeenCalledWith ( '0' ) ;
131- } ) ;
132- } ) ;
133-
134- describe ( 'pay flow (USD forced, preferred is EUR)' , ( ) => {
135- const eurUsdRates = {
136- ETH : { conversionRate : 2000 , usdConversionRate : 2200 } ,
137- } ;
138- const ethChainConfig = { '0x1' : { nativeCurrency : 'ETH' } } ;
139-
140- beforeEach ( ( ) => {
141- mockUseTransactionPayCurrency . mockReturnValue ( 'USD' ) ;
142- } ) ;
143-
144- it ( 're-scales the amount by usdRate/preferredRate' , ( ) => {
145- buildState ( {
146- preferredCurrency : 'eur' ,
147- currencyRates : eurUsdRates ,
148- networkConfigs : ethChainConfig ,
149- } ) ;
150-
151- renderHook ( ( ) => useAssetFiatFormatter ( ) ) . result . current . format (
152- '100' ,
153- '0x1' ,
154- ) ;
104+ renderHook ( ( ) => useAssetFiatFormatter ( ) ) . result . current . format ( '100' ) ;
155105
156- // 100 EUR * (2200 USD/ETH / 2000 EUR/ETH) = 110 USD
157- expect ( mockFormatter . format ) . toHaveBeenCalledWith ( '110' ) ;
158106 expect ( mockGetIntlNumberFormatter ) . toHaveBeenCalledWith (
159107 'en-US' ,
160- expect . objectContaining ( { currency : 'USD' } ) ,
108+ expect . objectContaining ( { minimumFractionDigits : 0 } ) ,
161109 ) ;
162110 } ) ;
163111
164- it ( 'exposes fiatCurrency as USD' , ( ) => {
165- buildState ( {
166- preferredCurrency : 'eur' ,
167- currencyRates : eurUsdRates ,
168- networkConfigs : ethChainConfig ,
169- } ) ;
170-
171- const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
172- expect ( result . current . fiatCurrency ) . toBe ( 'USD' ) ;
173- } ) ;
174-
175- it ( 'returns undefined when usdConversionRate is missing' , ( ) => {
176- buildState ( {
177- preferredCurrency : 'eur' ,
178- currencyRates : { ETH : { conversionRate : 2000 } } ,
179- networkConfigs : ethChainConfig ,
180- } ) ;
181-
182- const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
183- const output = result . current . format ( '100' , '0x1' ) ;
184-
185- expect ( output ) . toBeUndefined ( ) ;
186- expect ( mockFormatter . format ) . not . toHaveBeenCalled ( ) ;
187- } ) ;
188-
189- it ( 'returns undefined when preferred conversionRate is missing' , ( ) => {
190- buildState ( {
191- preferredCurrency : 'eur' ,
192- currencyRates : { ETH : { usdConversionRate : 2200 } } ,
193- networkConfigs : ethChainConfig ,
194- } ) ;
195-
196- const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
197- const output = result . current . format ( '100' , '0x1' ) ;
198-
199- expect ( output ) . toBeUndefined ( ) ;
200- expect ( mockFormatter . format ) . not . toHaveBeenCalled ( ) ;
201- } ) ;
202-
203- it ( 'returns undefined when chain has no EVM network config' , ( ) => {
204- buildState ( {
205- preferredCurrency : 'eur' ,
206- currencyRates : eurUsdRates ,
207- networkConfigs : { } ,
208- } ) ;
209-
210- const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
211- const output = result . current . format ( '100' , '0x1' ) ;
212-
213- expect ( output ) . toBeUndefined ( ) ;
214- expect ( mockFormatter . format ) . not . toHaveBeenCalled ( ) ;
215- } ) ;
216-
217- it ( 'formats zero even when rates or chain config are missing' , ( ) => {
218- buildState ( {
219- preferredCurrency : 'eur' ,
220- currencyRates : { } ,
221- networkConfigs : { } ,
222- } ) ;
112+ it ( 'uses minimumFractionDigits=2 for non-integer amounts' , ( ) => {
113+ buildState ( { preferredCurrency : 'eur' } ) ;
223114
224- const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
225- const output = result . current . format ( 0 , undefined ) ;
115+ renderHook ( ( ) => useAssetFiatFormatter ( ) ) . result . current . format ( '100.5' ) ;
226116
227- expect ( output ) . toBe ( 'formatted:0' ) ;
228117 expect ( mockGetIntlNumberFormatter ) . toHaveBeenCalledWith (
229118 'en-US' ,
230- expect . objectContaining ( { currency : 'USD' } ) ,
231- ) ;
232- } ) ;
233- } ) ;
234-
235- describe ( 'pay flow (USD forced, preferred is already USD)' , ( ) => {
236- it ( 'does not re-scale (identity), so numeric value is unchanged' , ( ) => {
237- mockUseTransactionPayCurrency . mockReturnValue ( 'USD' ) ;
238- buildState ( {
239- preferredCurrency : 'usd' ,
240- currencyRates : {
241- ETH : { conversionRate : 2200 , usdConversionRate : 2200 } ,
242- } ,
243- networkConfigs : { '0x1' : { nativeCurrency : 'ETH' } } ,
244- } ) ;
245-
246- renderHook ( ( ) => useAssetFiatFormatter ( ) ) . result . current . format (
247- '100' ,
248- '0x1' ,
119+ expect . objectContaining ( { minimumFractionDigits : 2 } ) ,
249120 ) ;
250-
251- expect ( mockFormatter . format ) . toHaveBeenCalledWith ( '100' ) ;
252121 } ) ;
253122
254- it ( 'still formats when currency rates are missing (no conversion needed)' , ( ) => {
255- mockUseTransactionPayCurrency . mockReturnValue ( 'USD' ) ;
256- buildState ( {
257- preferredCurrency : 'usd' ,
258- currencyRates : { } ,
259- networkConfigs : { } ,
260- } ) ;
123+ it ( 'returns undefined when input is undefined' , ( ) => {
124+ buildState ( { preferredCurrency : 'eur' } ) ;
261125
262126 const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
263- const output = result . current . format ( '100' , '0x1' ) ;
127+ const output = result . current . format ( undefined ) ;
264128
265- expect ( output ) . toBe ( 'formatted:100' ) ;
129+ expect ( output ) . toBeUndefined ( ) ;
130+ expect ( mockFormatter . format ) . not . toHaveBeenCalled ( ) ;
266131 } ) ;
267- } ) ;
268132
269- describe ( 'formatter error fallback' , ( ) => {
270133 it ( 'falls back to `${value} ${currency}` when Intl throws' , ( ) => {
271134 buildState ( { preferredCurrency : 'eur' } ) ;
272135 mockGetIntlNumberFormatter . mockImplementation ( ( ) => {
273136 throw new Error ( 'boom' ) ;
274137 } ) ;
275138
276139 const { result } = renderHook ( ( ) => useAssetFiatFormatter ( ) ) ;
277- const output = result . current . format ( '42' , '0x1' ) ;
140+ const output = result . current . format ( '42' ) ;
278141
279142 expect ( output ) . toBe ( '42 eur' ) ;
280143 } ) ;
0 commit comments