@transferwise/comparison-components 22.1.3 → 22.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +4 -2
  2. package/dist/es/{ComparisonTableHeroContainer-d9ad65c4.js → ComparisonTableHeroContainer-de132861.js} +2 -2
  3. package/dist/es/{ComparisonTableHeroContainer-d9ad65c4.js.map → ComparisonTableHeroContainer-de132861.js.map} +1 -1
  4. package/dist/es/{ErrorTemplate-7db673bd.js → ErrorTemplate-4cd72347.js} +2 -2
  5. package/dist/es/{ErrorTemplate-7db673bd.js.map → ErrorTemplate-4cd72347.js.map} +1 -1
  6. package/dist/es/{ProviderComparisonTable-ad9f0690.js → ProviderComparisonTable-99cc4186.js} +2 -2
  7. package/dist/es/{ProviderComparisonTable-ad9f0690.js.map → ProviderComparisonTable-99cc4186.js.map} +1 -1
  8. package/dist/es/{ReceiveAmount-4ca0b7e8.js → ReceiveAmount-504a3f01.js} +2 -2
  9. package/dist/es/{ReceiveAmount-4ca0b7e8.js.map → ReceiveAmount-504a3f01.js.map} +1 -1
  10. package/dist/es/TravelMoney-b9c1a100.js +2 -0
  11. package/dist/es/{TravelMoney-984ec2de.js.map → TravelMoney-b9c1a100.js.map} +1 -1
  12. package/dist/es/comparison/index.js +1 -1
  13. package/dist/es/comparison-table/index.js +1 -1
  14. package/dist/es/comparison-table-hero/index.js +1 -1
  15. package/dist/es/{index-2651b4fb.js → index-12e593f4.js} +2 -2
  16. package/dist/es/{index-2651b4fb.js.map → index-12e593f4.js.map} +1 -1
  17. package/dist/es/index.js +1 -1
  18. package/dist/es/parseAmount-b0a195e6.js +2 -0
  19. package/dist/es/{useDebounce-05bd2742.js.map → parseAmount-b0a195e6.js.map} +1 -1
  20. package/dist/es/provider-comparison-table/index.js +1 -1
  21. package/dist/es/provider-comparison-widget/index.js +1 -1
  22. package/dist/es/provider-comparison-widget/index.js.map +1 -1
  23. package/dist/es/travel-money/index.js +1 -1
  24. package/dist/umd/comparison-components.css +1 -1
  25. package/dist/umd/comparison-components.js +7 -7
  26. package/dist/umd/comparison-components.js.map +1 -1
  27. package/dist/umd/provider-comparison-widget/provider-comparison-widget.js +6 -6
  28. package/dist/umd/provider-comparison-widget/provider-comparison-widget.js.map +1 -1
  29. package/dist/umd/travel-money/travel-money.js +6 -6
  30. package/dist/umd/travel-money/travel-money.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/common/parseAmount/index.js +1 -0
  33. package/src/common/parseAmount/parseAmount.spec.ts +36 -0
  34. package/src/common/parseAmount/parseAmount.ts +81 -0
  35. package/src/provider-comparison-widget/__test__/AmountInput.spec.jsx +6 -7
  36. package/src/provider-comparison-widget/components/AmountInput.jsx +1 -1
  37. package/src/travel-money/components/AmountInput.jsx +1 -1
  38. package/dist/es/TravelMoney-984ec2de.js +0 -2
  39. package/dist/es/useDebounce-05bd2742.js +0 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/comparison-components",
3
- "version": "22.1.3",
3
+ "version": "22.1.4",
4
4
  "description": "Display a comparison table of providers given a route and amount.",
5
5
  "homepage": "https://wise.com/gb/compare/",
6
6
  "main": "dist/umd/comparison-components.js",
@@ -0,0 +1 @@
1
+ export { parseAmount as default } from './parseAmount';
@@ -0,0 +1,36 @@
1
+ import { parseAmount } from './parseAmount';
2
+
3
+ describe('Number formatting', () => {
4
+ it('parses localized numbers', () => {
5
+ [
6
+ ['1234.56', 'en-GB'],
7
+ ['1,23,4.56', 'en-US'],
8
+ ].forEach(([number, locale]) => {
9
+ expect(parseAmount(number, 'gbp', locale)).toBe(1234.56);
10
+ });
11
+ });
12
+
13
+ it('parses numbers with invalid locale', () => {
14
+ expect(parseAmount('123.45', 'gbp', '12345de_DE')).toBe(123.45);
15
+ });
16
+
17
+ it('parses negative numbers into positive ones', () => {
18
+ expect(parseAmount('-123.45', 'gbp', 'en-GB')).toBe(123.45);
19
+ });
20
+
21
+ it.each([
22
+ ['0---9(s.t.r!@#$%^&*()_+^[]{};’,<>?', 9],
23
+ ['$12.341', 12.34],
24
+ ['$12.347', 12.35],
25
+ ['.asd121', 0.12],
26
+ ['.asd129', 0.13],
27
+ [',asd129', 129],
28
+ ['123.123.123', 123.12],
29
+ ['asda', NaN],
30
+ ])(
31
+ "parses strings by removing the non-numerical characters; case: '%s', expected: '%s'",
32
+ (testValue, expectedValue) => {
33
+ expect(parseAmount(testValue, 'gbp', 'en-GB')).toBe(expectedValue);
34
+ },
35
+ );
36
+ });
@@ -0,0 +1,81 @@
1
+ // TODO: This is a dup of https://github.com/transferwise/neptune-web/blob/main/packages/components/src/moneyInput/currencyFormatting.js
2
+ // It's not exported out of neptune-web correctly and cannot get it working with Jest.
3
+
4
+ const currencyDecimals: Record<string, number> = {
5
+ BIF: 0,
6
+ BYR: 0,
7
+ CLP: 0,
8
+ DJF: 0,
9
+ GNF: 0,
10
+ JPY: 0,
11
+ KMF: 0,
12
+ KRW: 0,
13
+ MGA: 0,
14
+ PYG: 0,
15
+ RWF: 0,
16
+ VND: 0,
17
+ VUV: 0,
18
+ XAF: 0,
19
+ XOF: 0,
20
+ XPF: 0,
21
+ // technically HUF does have decimals, but due to the exchange rate banks
22
+ // do not accept decimal amounts
23
+ HUF: 0,
24
+
25
+ BHD: 3,
26
+ JOD: 3,
27
+ KWD: 3,
28
+ OMR: 3,
29
+ TND: 3,
30
+ };
31
+
32
+ const DEFAULT_LOCALE = 'en-GB';
33
+ const DEFAULT_CURRENCY_DECIMALS = 2;
34
+
35
+ function isNumberLocaleSupported() {
36
+ const number = 1234;
37
+ const numberString = number.toLocaleString && number.toLocaleString(DEFAULT_LOCALE);
38
+ return numberString === '1,234';
39
+ }
40
+
41
+ function getValidLocale(locale: string) {
42
+ if (!locale) {
43
+ return DEFAULT_LOCALE;
44
+ }
45
+ try {
46
+ const noUnderscoreLocale = locale.replace(/_/, '-');
47
+
48
+ Intl.NumberFormat(noUnderscoreLocale);
49
+ return noUnderscoreLocale;
50
+ } catch {
51
+ return DEFAULT_LOCALE;
52
+ }
53
+ }
54
+
55
+ const getCurrencyDecimals = (currency = ''): number => {
56
+ const upperCaseCurrency = currency.toUpperCase();
57
+ if (Object.prototype.hasOwnProperty.call(currencyDecimals, upperCaseCurrency)) {
58
+ return currencyDecimals[upperCaseCurrency];
59
+ }
60
+ return DEFAULT_CURRENCY_DECIMALS;
61
+ };
62
+
63
+ const getDecimalSeparator = (locale: string) => {
64
+ return isNumberLocaleSupported() ? (1.1).toLocaleString(locale)[1] : '.';
65
+ };
66
+
67
+ export function parseAmount(number: string, currency: string, locale: string): number {
68
+ const validLocale = getValidLocale(locale);
69
+
70
+ const precision = getCurrencyDecimals(currency);
71
+ const groupSeparator = isNumberLocaleSupported() ? (10000).toLocaleString(validLocale)[2] : ',';
72
+ const decimalSeparator = getDecimalSeparator(validLocale);
73
+ const numberWithStandardDecimalSeparator = (number ? `${number}` : '')
74
+ .replace(new RegExp(`\\${groupSeparator}`, 'g'), '')
75
+ .replace(new RegExp(`\\${decimalSeparator}`, 'g'), '.')
76
+ .replace(/[^0-9.]/g, '');
77
+ const parsedAmount = parseFloat(
78
+ parseFloat(numberWithStandardDecimalSeparator).toFixed(precision),
79
+ );
80
+ return Math.abs(parsedAmount);
81
+ }
@@ -4,15 +4,14 @@ import { mount } from 'enzyme';
4
4
  import React from 'react';
5
5
  import { IntlProvider } from 'react-intl';
6
6
 
7
+ import * as parseAmount from '../../common/parseAmount';
7
8
  import translations from '../assets/translations/translations.json';
8
9
  import AmountInput from '../components/AmountInput';
9
10
 
10
11
  jest.mock('@transferwise/formatting', () => ({
11
12
  formatAmount: jest.fn(),
12
13
  }));
13
- jest.mock('@transferwise/components', () => ({
14
- parseAmount: jest.fn(),
15
- }));
14
+
16
15
  const mountRenderComponent = (renderProps) =>
17
16
  mount(
18
17
  <IntlProvider locale="en" messages={translations.en}>
@@ -24,7 +23,7 @@ const mountRenderComponent = (renderProps) =>
24
23
  },
25
24
  );
26
25
 
27
- const currencyParsing = require('@transferwise/components');
26
+ const parseAmountSpy = jest.spyOn(parseAmount, 'default');
28
27
  const currencyFormatting = require('@transferwise/formatting');
29
28
 
30
29
  describe('AmountInput', () => {
@@ -75,7 +74,7 @@ describe('AmountInput', () => {
75
74
  children: <AmountInput {...{ ...props, locale: 'en-US' }} />,
76
75
  });
77
76
  component.update();
78
- jest.spyOn(currencyParsing, 'parseAmount').mockImplementation(parseFloat);
77
+ parseAmountSpy.mockImplementation(parseFloat);
79
78
  enterAmount('123.45');
80
79
  component.update();
81
80
  expect(amountInput().prop('value')).toBe('123.45');
@@ -94,7 +93,7 @@ describe('AmountInput', () => {
94
93
  });
95
94
 
96
95
  component.update();
97
- jest.spyOn(currencyParsing, 'parseAmount').mockImplementation((amount, currency, locale) => {
96
+ parseAmountSpy.mockImplementation((amount, currency, locale) => {
98
97
  expect(amount).toBe('500.1234');
99
98
  expect(locale).toBe('es-ES');
100
99
  expect(currency).toBe('eur');
@@ -117,7 +116,7 @@ describe('AmountInput', () => {
117
116
  children: <AmountInput {...{ ...props, onAmountChange }} />,
118
117
  });
119
118
  component.update();
120
- jest.spyOn(currencyParsing, 'parseAmount').mockImplementation(() => NaN);
119
+ parseAmountSpy.mockImplementation(() => NaN);
121
120
  enterAmount('cannot parse this yo');
122
121
  expect(onAmountChange).not.toHaveBeenCalled();
123
122
  });
@@ -1,9 +1,9 @@
1
- import { parseAmount } from '@transferwise/components';
2
1
  import { formatAmount } from '@transferwise/formatting';
3
2
  import PropTypes from 'prop-types';
4
3
  import React, { useState, useEffect } from 'react';
5
4
  import { FormattedMessage } from 'react-intl';
6
5
 
6
+ import parseAmount from '../../common/parseAmount';
7
7
  import createClassNamesFromStyles from '../../resources/createClassNamesFromStyles';
8
8
  import style from '../ProviderComparisonWidget.module.less';
9
9
 
@@ -1,9 +1,9 @@
1
- import { parseAmount } from '@transferwise/components';
2
1
  import { formatAmount } from '@transferwise/formatting';
3
2
  import PropTypes from 'prop-types';
4
3
  import React, { useState, useEffect } from 'react';
5
4
  import { FormattedMessage } from 'react-intl';
6
5
 
6
+ import parseAmount from '../../common/parseAmount';
7
7
  import createClassNamesFromStyles from '../../resources/createClassNamesFromStyles';
8
8
  import style from '../TravelMoney.module.less';
9
9