Skip to content

Commit 7f33634

Browse files
committed
Merge branch 'frontend-amount-refactor'
2 parents 60dc332 + cb4aa7f commit 7f33634

File tree

20 files changed

+566
-138
lines changed

20 files changed

+566
-138
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- New feature in advanced settings: Export logs
55
- Add specific titles to guides replacing the generic "Guide" previously used on all pages
66
- Android: enable transactions export feature
7+
- Format amounts using localized decimal and group separator
78

89
## 4.42.0
910
- Preselect backup when there's only one backup available
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/**
2+
* Copyright 2024 Shift Crypto AG
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { useContext } from 'react';
18+
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
19+
import { render } from '@testing-library/react';
20+
import { Amount } from './amount';
21+
import { ConversionUnit } from '../../api/account';
22+
23+
vi.mock('react', async () => ({
24+
...(await vi.importActual('react')),
25+
useMemo: vi.fn().mockImplementation((fn) => fn()), // not really needed here, but in balance.test.tsx
26+
useContext: vi.fn(),
27+
createContext: vi.fn()
28+
}));
29+
30+
31+
describe.only('Fiat amount formatting', () => {
32+
beforeEach(() => {
33+
(useContext as Mock).mockReturnValue({ hideAmounts: false });
34+
});
35+
36+
describe('de-AT', () => {
37+
it('should use dot for thousand and comma for decimal', () => {
38+
(useContext as Mock).mockReturnValue({ nativeLocale: 'de-AT' });
39+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
40+
expect(container).toHaveTextContent('1.234.567,89');
41+
});
42+
});
43+
44+
describe('de-CH', () => {
45+
it('should use apostrophe for thousand and dot for decimal', () => {
46+
(useContext as Mock).mockReturnValue({ nativeLocale: 'de-CH' });
47+
const { container } = render(<Amount amount="1'234'567.89" unit="USD" />);
48+
expect(container).toHaveTextContent('1’234’567.89');
49+
});
50+
it('should use apostrophe for thousand and dot for decimal and remove trailing zeros', () => {
51+
(useContext as Mock).mockReturnValue({ nativeLocale: 'de-CH' });
52+
const { container } = render(<Amount amount="1'234.56789000" unit="BTC" removeBtcTrailingZeroes />);
53+
expect(container).toHaveTextContent('1’234.56789');
54+
});
55+
});
56+
57+
describe('de-DE', () => {
58+
it('should use apostrophe for thousand and dot for decimal', () => {
59+
(useContext as Mock).mockReturnValue({ nativeLocale: 'de-DE' });
60+
const { container } = render(<Amount amount="1'000" unit="USD" />);
61+
expect(container).toHaveTextContent('1.000');
62+
});
63+
it('should use dot for thousand and comma for decimal', () => {
64+
(useContext as Mock).mockReturnValue({ nativeLocale: 'de-DE' });
65+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
66+
expect(container).toHaveTextContent('1.234.567,89');
67+
});
68+
});
69+
70+
describe('en-GB', () => {
71+
it('should use comma for thousand and dot for decimal', () => {
72+
(useContext as Mock).mockReturnValue({ nativeLocale: 'en-GB' });
73+
const { container } = render(<Amount amount="1'234'567.89" unit="GBP" />);
74+
expect(container).toHaveTextContent('1,234,567.89');
75+
});
76+
});
77+
78+
describe('en-CA', () => {
79+
it('should use comma for thousand and dot for decimal', () => {
80+
(useContext as Mock).mockReturnValue({ nativeLocale: 'en-CA' });
81+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
82+
expect(container).toHaveTextContent('1,234,567.89');
83+
});
84+
});
85+
86+
// describe('en-IN', () => {
87+
// beforeEach(() => {
88+
// vi.mocked(i18n).language = 'en-IN';
89+
// });
90+
// it('should use Indian numbering system using comma and dot for decimal', () => {
91+
// const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
92+
// expect(container).toHaveTextContent('12,34,567.89');
93+
// });
94+
// });
95+
96+
describe('en-UK', () => {
97+
it('should use comma for thousand and dot for decimal and remove trailing zeros', () => {
98+
(useContext as Mock).mockReturnValue({ nativeLocale: 'en-UK' });
99+
const { container } = render(<Amount amount="1'234.56789000" unit="BTC" removeBtcTrailingZeroes />);
100+
expect(container).toHaveTextContent('1,234.56789');
101+
});
102+
});
103+
104+
describe('en-US', () => {
105+
const fiatCoins: ConversionUnit[] = ['USD', 'EUR', 'CHF'];
106+
fiatCoins.forEach(coin => {
107+
it('should use comma for thousand and dot for decimal', () => {
108+
(useContext as Mock).mockReturnValue({ nativeLocale: 'en-US' });
109+
const { container } = render(<Amount amount="1'234'567.89" unit={coin} />);
110+
expect(container).toHaveTextContent('1,234,567.89');
111+
});
112+
});
113+
});
114+
115+
describe('es-ES', () => {
116+
it('should use dot for thousand and comma for decimal', () => {
117+
(useContext as Mock).mockReturnValue({ nativeLocale: 'es-ES' });
118+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
119+
expect(container).toHaveTextContent('1.234.567,89');
120+
});
121+
it('should use space for thousand and comma for decimal', () => {
122+
(useContext as Mock).mockReturnValue({ nativeLocale: 'es-ES' });
123+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
124+
expect(container).toHaveTextContent('1.234.567,89');
125+
});
126+
});
127+
128+
describe('es-419', () => {
129+
it('should use space for thousand and comma for decimal', () => {
130+
(useContext as Mock).mockReturnValue({ nativeLocale: 'es-419' });
131+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
132+
expect(container).toHaveTextContent('1,234,567.89');
133+
});
134+
});
135+
136+
describe('fr-CA', () => {
137+
it('should use space for thousand and comma for decimal', () => {
138+
(useContext as Mock).mockReturnValue({ nativeLocale: 'fr-CA' });
139+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
140+
expect(container).toHaveTextContent('1 234 567,89');
141+
});
142+
});
143+
144+
describe('fr-FR', () => {
145+
it('should use space for thousand and comma for decimal', () => {
146+
(useContext as Mock).mockReturnValue({ nativeLocale: 'fr-FR' });
147+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
148+
expect(container).toHaveTextContent('1 234 567,89');
149+
});
150+
});
151+
152+
describe('id-ID', () => {
153+
it('should use dot for thousand and comma for decimal', () => {
154+
(useContext as Mock).mockReturnValue({ nativeLocale: 'id-ID' });
155+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
156+
expect(container).toHaveTextContent('1.234.567,89');
157+
});
158+
});
159+
160+
describe('it-IT', () => {
161+
it('should use dot for thousand and comma for decimal', () => {
162+
(useContext as Mock).mockReturnValue({ nativeLocale: 'it-IT' });
163+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
164+
expect(container).toHaveTextContent('1.234.567,89');
165+
});
166+
});
167+
168+
describe('ja-JP', () => {
169+
it('should use comma for thousand and dot for decimal', () => {
170+
(useContext as Mock).mockReturnValue({ nativeLocale: 'ja-JP' });
171+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
172+
expect(container).toHaveTextContent('1,234,567.89');
173+
});
174+
});
175+
176+
describe('ko-KR', () => {
177+
it('should use comma for thousand and dot for decimal', () => {
178+
(useContext as Mock).mockReturnValue({ nativeLocale: 'ko-KR' });
179+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
180+
expect(container).toHaveTextContent('1,234,567.89');
181+
});
182+
});
183+
184+
describe('nl-NL', () => {
185+
it('should use dot for thousand and comma for decimal', () => {
186+
(useContext as Mock).mockReturnValue({ nativeLocale: 'nl-NL' });
187+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
188+
expect(container).toHaveTextContent('1.234.567,89');
189+
});
190+
});
191+
192+
describe('pt-BR', () => {
193+
it('should use dot for thousand and comma for decimal', () => {
194+
(useContext as Mock).mockReturnValue({ nativeLocale: 'pt-BR' });
195+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
196+
expect(container).toHaveTextContent('1.234.567,89');
197+
});
198+
});
199+
200+
describe('ru-RU', () => {
201+
it('should use space for thousand and comma for decimal', () => {
202+
(useContext as Mock).mockReturnValue({ nativeLocale: 'ru-RU' });
203+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
204+
expect(container).toHaveTextContent('1 234 567,89');
205+
});
206+
});
207+
208+
describe('tr-TR', () => {
209+
it('should use space for thousand and comma for decimal', () => {
210+
(useContext as Mock).mockReturnValue({ nativeLocale: 'tr-TR' });
211+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
212+
expect(container).toHaveTextContent('1.234.567,89');
213+
});
214+
});
215+
216+
describe('zh-CN', () => {
217+
it('should use comma for thousand and dot for decimal', () => {
218+
(useContext as Mock).mockReturnValue({ nativeLocale: 'zh-CN' });
219+
const { container } = render(<Amount amount="1'234'567.89" unit="EUR" />);
220+
expect(container).toHaveTextContent('1,234,567.89');
221+
});
222+
});
223+
224+
});

frontends/web/src/components/amount/amount.test.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2023 Shift Crypto AG
2+
* Copyright 2023-2024 Shift Crypto AG
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,18 +13,22 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
import { useContext } from 'react';
1718
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
1819
import { render } from '@testing-library/react';
1920
import { Amount } from './amount';
2021
import { CoinUnit, ConversionUnit } from './../../api/account';
2122

22-
vi.mock('react', () => ({
23-
...vi.importActual('react'),
23+
vi.mock('react', async () => ({
24+
...(await vi.importActual('react')),
2425
useContext: vi.fn(),
2526
createContext: vi.fn()
2627
}));
2728

29+
vi.mock('../../i18n/i18n', () => ({
30+
i18n: { language: 'de-CH' },
31+
}));
2832

2933
const validateSpacing = (values: string[], elements: Element[]) => {
3034
// each element in `values` is an expected
@@ -49,7 +53,10 @@ const validateSpacing = (values: string[], elements: Element[]) => {
4953
describe('Amount formatting', () => {
5054

5155
beforeEach(() => {
52-
(useContext as Mock).mockReturnValue({ hideAmounts: false });
56+
(useContext as Mock).mockReturnValue({
57+
hideAmounts: false,
58+
nativeLocale: 'de-CH'
59+
});
5360
});
5461

5562
describe('hide amounts', () => {
@@ -261,15 +268,15 @@ describe('Amount formatting', () => {
261268
fiatCoins.forEach(coin => {
262269
it('1\'340.25 ' + coin + ' with removeBtcTrailingZeroes enabled stays 1\'340.25', () => {
263270
const { container } = render(<Amount amount="1'340.25" unit={coin} removeBtcTrailingZeroes/>);
264-
expect(container).toHaveTextContent('1\'340.25');
271+
expect(container).toHaveTextContent('1340.25');
265272
});
266273
it('218.00 ' + coin + ' with removeBtcTrailingZeroes enabled stays 218.00', () => {
267274
const { container } = render(<Amount amount="218.00" unit={coin} removeBtcTrailingZeroes/>);
268275
expect(container).toHaveTextContent('218.00');
269276
});
270277
it('1\'340.25 ' + coin + ' with removeBtcTrailingZeroes disabled stays 1\'340.25', () => {
271278
const { container } = render(<Amount amount="1'340.25" unit={coin}/>);
272-
expect(container).toHaveTextContent('1\'340.25');
279+
expect(container).toHaveTextContent('1340.25');
273280
});
274281
it('218.00 ' + coin + ' with removeBtcTrailingZeroes disabled stays 218.00', () => {
275282
const { container } = render(<Amount amount="218.00" unit={coin}/>);

0 commit comments

Comments
 (0)