Skip to content

Commit 8e6b3e2

Browse files
authored
fix: prevent duplicated decimal points (#67)
* fix: prevent decimal point duplication * chore: apply formatting * test: add assertions * chore: cleanup syntax * chore: no single use abstraction
1 parent f25bd6b commit 8e6b3e2

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

src/lib/CurrencyInput.svelte

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { onMount } from "svelte";
2+
import { onMount } from 'svelte';
33
44
const DEFAULT_LOCALE = 'en-US';
55
const DEFAULT_CURRENCY = 'USD';
@@ -61,7 +61,18 @@
6161
const isTab = event.key === 'Tab';
6262
const isInvalidCharacter = !/^\d|,|\.|-$/g.test(event.key); // Keys that are not a digit, comma, period or minus sign
6363
64-
if (!isDeletion && !isModifier && !isArrowKey && isInvalidCharacter && !isTab)
64+
// If there is already a decimal point, don't allow more than one
65+
const isPunctuationDuplicated = () => {
66+
if (event.key !== ',' && event.key !== '.') return false; // Is `false` because it's not a punctuation key
67+
if (isDecimalComma) return formattedValue.split(',').length >= 2;
68+
if (!isDecimalComma) return formattedValue.split('.').length >= 2;
69+
return false;
70+
};
71+
72+
if (
73+
isPunctuationDuplicated() ||
74+
(!isDeletion && !isModifier && !isArrowKey && isInvalidCharacter && !isTab)
75+
)
6576
event.preventDefault();
6677
};
6778

tests/svelte-currency-input.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,41 @@ test.describe('CurrencyInput', () => {
419419
await expect(dinarsFormattedInput).toHaveAttribute('placeholder', 'How many Dinars?');
420420
});
421421

422+
test('Prevent duplicated decimal points', async ({ page }) => {
423+
// Periods as decimals
424+
const poundUnformattedInput = page.locator('.currencyInput__unformatted[name=pound]');
425+
const poundFormattedInput = page.locator('.currencyInput__formatted[name="formatted-pound"]');
426+
await expect(poundUnformattedInput).toHaveValue('1234.56');
427+
await expect(poundFormattedInput).toHaveValue('£1,234.56');
428+
429+
await poundFormattedInput.focus();
430+
await page.keyboard.type('....');
431+
await expect(poundUnformattedInput).toHaveValue('1234.56');
432+
await expect(poundFormattedInput).toHaveValue('£1,234.56');
433+
434+
// Commas as decimals
435+
const colonUnformattedInput = page.locator('.currencyInput__unformatted[name=colon]');
436+
const colonFormattedInput = page.locator('.currencyInput__formatted[name="formatted-colon"]');
437+
await expect(colonUnformattedInput).toHaveValue('0');
438+
await expect(colonFormattedInput).toHaveValue('');
439+
440+
await colonFormattedInput.focus();
441+
await page.keyboard.type('123,,,,,');
442+
await expect(colonUnformattedInput).toHaveValue('123');
443+
await expect(colonFormattedInput).toHaveValue('₡123,');
444+
445+
// Pressing multiple commas when locale for decimals is a period
446+
const dinarsUnformattedInput = page.locator('.currencyInput__unformatted[name="dinars"]');
447+
const dinarsFormattedInput = page.locator('.currencyInput__formatted[name="formatted-dinars"]');
448+
await expect(dinarsUnformattedInput).toHaveValue('0');
449+
await expect(dinarsFormattedInput).toHaveValue('');
450+
451+
await dinarsFormattedInput.focus();
452+
await page.keyboard.type('123,,,,,');
453+
await expect(dinarsUnformattedInput).toHaveValue('123');
454+
await expect(dinarsFormattedInput).toHaveValue('RSD 123.');
455+
});
456+
422457
test.skip('Updating chained inputs have the correct behavior', async () => {
423458
// TODO
424459
});

0 commit comments

Comments
 (0)