Skip to content

Commit

Permalink
fix(input-amount): do not break when a large amount has been entered
Browse files Browse the repository at this point in the history
  • Loading branch information
gerjanvangeest committed Apr 4, 2024
1 parent 87f864f commit 6e47def
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 11 deletions.
7 changes: 4 additions & 3 deletions packages/ui/components/input-amount/src/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { parseNumber, getFractionDigits } from '@lion/ui/localize-no-side-effect
* @return {number} new value with rounded up decimals
*/
function round(value, decimals) {
if (typeof decimals === 'undefined') {
const numberContainsExponent = value?.toString().includes('e');
if (typeof decimals === 'undefined' || numberContainsExponent) {
return Number(value);
}
return Number(`${Math.round(Number(`${value}e${decimals}`))}e-${decimals}`);
Expand All @@ -31,13 +32,13 @@ function round(value, decimals) {
*/
export function parseAmount(value, givenOptions) {
const unmatchedInput = value.match(/[^0-9,.\- ]/g);
if (unmatchedInput) {
if (unmatchedInput && givenOptions?.mode !== 'pasted') {
return undefined;
}

const number = parseNumber(value, givenOptions);

if (typeof number !== 'number' || Number.isNaN(number) || number?.toString().includes('e')) {
if (typeof number !== 'number' || Number.isNaN(number)) {
return undefined;
}

Expand Down
11 changes: 11 additions & 0 deletions packages/ui/components/input-amount/test/formatters.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,15 @@ describe('formatAmount()', () => {
localizeManager.locale = 'nl-NL';
expect(formatAmount(12345678)).to.equal('12.345.678,00');
});

// TODO: make it work with big numbers, e.g. make use of BigInt
it('rounds up big numbers', async () => {
expect(formatAmount(1e21, { locale: 'en-GB', currency: 'EUR' })).to.equal(
'1,000,000,000,000,000,000,000.00',
);
// eslint-disable-next-line no-loss-of-precision
expect(formatAmount(12345678987654321.42, { locale: 'en-GB', currency: 'EUR' })).to.equal(
'12,345,678,987,654,322.00',
);
});
});
11 changes: 11 additions & 0 deletions packages/ui/components/input-amount/test/lion-input-amount.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { localize } from '@lion/ui/localize.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
import { getInputMembers } from '@lion/ui/input-test-helpers.js';
import { LionInputAmount, formatAmount, parseAmount } from '@lion/ui/input-amount.js';
import { mimicUserInput } from '@lion/ui/form-core-test-helpers.js';

import '@lion/ui/define/lion-input-amount.js';

Expand Down Expand Up @@ -132,6 +133,16 @@ describe('<lion-input-amount>', () => {
expect(_inputNode.value).to.equal('100.12');
});

// TODO: make it work with big numbers, e.g. make use of BigInt
it('sets roundup amount when a big number is inserted', async () => {
const el = /** @type {LionInputAmount} */ (
await fixture(html`<lion-input-amount></lion-input-amount>`)
);
mimicUserInput(el, '999999999999999999999.42');
await el.updateComplete;
expect(el.modelValue).to.equal(1000000000000000000000.0);
});

it('sets inputmode attribute to decimal', async () => {
const el = /** @type {LionInputAmount} */ (
await fixture(`<lion-input-amount></lion-input-amount>`)
Expand Down
29 changes: 22 additions & 7 deletions packages/ui/components/input-amount/test/parsers.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { expect } from '@open-wc/testing';
import { localize } from '@lion/ui/localize.js';
import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
import { parseAmount } from '@lion/ui/input-amount.js';

describe('parseAmount()', async () => {
const localizeManager = getLocalizeManager();

beforeEach(() => {
localizeManager.locale = 'en-GB';
});

afterEach(() => {
localizeTearDown();
});

it('with currency set to correct amount of decimals', async () => {
localize.locale = 'en-GB';
expect(
parseAmount('1.015', {
currency: 'EUR',
Expand All @@ -28,19 +38,24 @@ describe('parseAmount()', async () => {
});

it('with no currency keeps all decimals', async () => {
localize.locale = 'en-GB';
expect(parseAmount('1.015')).to.equal(1.015);
});

// TODO: make it work with big numbers, e.g. make use of BigInt
it('rounds up big numbers', async () => {
expect(parseAmount('999999999999999999999,42')).to.equal(1e21);
expect(parseAmount('12,345,678,987,654,321.42')).to.equal(12345678987654322);
});

it('returns undefined if a invalid value is entered', async () => {
localize.locale = 'en-GB';
expect(parseAmount('foo')).to.equal(undefined);
expect(parseAmount('foo1')).to.equal(undefined);
expect(parseAmount('EUR 1,50')).to.equal(undefined);
expect(parseAmount('--1')).to.equal(undefined);
});

it('returns undefined if the value is too big', async () => {
localize.locale = 'en-GB';
expect(parseAmount('999999999999999999999,42')).to.equal(undefined);
it('ignores letters when "pasted" mode used', async () => {
expect(parseAmount('foo1', { mode: 'pasted' })).to.equal(1);
expect(parseAmount('EUR 1,50', { mode: 'pasted' })).to.equal(1.5);
});
});
2 changes: 1 addition & 1 deletion packages/ui/components/localize/src/number/formatNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function formatNumber(number, options = /** @type {FormatOptions} */ ({})
}
let printNumberOfParts = '';
// update numberOfParts because there may be some parts added
const numberOfParts = formattedToParts && formattedToParts.length;
const numberOfParts = formattedToParts ? formattedToParts.length : 0;
for (let i = 0; i < numberOfParts; i += 1) {
const part = /** @type {FormatNumberPart} */ (formattedToParts[i]);
printNumberOfParts += part.value;
Expand Down
11 changes: 11 additions & 0 deletions packages/ui/components/localize/test/number/formatNumber.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,17 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
});
});

// TODO: make it work with big numbers, e.g. make use of BigInt
it('rounds up big numbers', async () => {
expect(formatNumber(1e21)).to.equal('1,000,000,000,000,000,000,000');
// eslint-disable-next-line no-loss-of-precision
expect(formatNumber(999999999999999999999.42)).to.equal('1,000,000,000,000,000,000,000');
// eslint-disable-next-line no-loss-of-precision
expect(formatNumber(12345678987654321.42)).to.equal('12,345,678,987,654,322');
// eslint-disable-next-line no-loss-of-precision
expect(formatNumber(1234567898765432.42)).to.equal('1,234,567,898,765,432.5');
});

describe('normalization', () => {
describe('en-GB', () => {
it('supports basics', () => {
Expand Down

0 comments on commit 6e47def

Please sign in to comment.