Skip to content

Commit

Permalink
fix(kit): Number should ignore [decimalSeparator] value if `[prec…
Browse files Browse the repository at this point in the history
…ision]=0` (#1908)
  • Loading branch information
nsbarsukov authored Dec 26, 2024
1 parent 1aa73a0 commit 19effe2
Show file tree
Hide file tree
Showing 17 changed files with 99 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,42 @@ describe('Number | precision', () => {
});

describe('rejects decimal separator if `precision` is equal to 0', () => {
beforeEach(() => {
openNumberPage('decimalSeparator=,&precision=0');
});

it('empty input => Type "," => Empty input', () => {
openNumberPage('decimalSeparator=,&precision=0');
cy.get('@input').type(',').should('have.value', '');
});

it('Type "5," => "5"', () => {
openNumberPage('decimalSeparator=,&precision=0');

cy.get('@input')
.type('5,')
.should('have.value', '5')
.should('have.prop', 'selectionStart', 1)
.should('have.prop', 'selectionEnd', 1);
});

describe('dont rejects thousand separator if it is equal to decimal separator (for precision=0 value of decimal separator does not matter)', () => {
it('simple typing', () => {
openNumberPage('precision=0&thousandSeparator=.&decimalSeparator=.');

cy.get('@input')
.type('1234')
.should('have.value', '1.234')
.should('have.prop', 'selectionStart', '1.234'.length)
.should('have.prop', 'selectionEnd', '1.234'.length);
});

it('paste from clipboard', () => {
openNumberPage('precision=0&thousandSeparator=.&decimalSeparator=.');

cy.get('@input')
.paste('1.234')
.should('have.value', '1.234')
.should('have.prop', 'selectionStart', '1.234'.length)
.should('have.prop', 'selectionEnd', '1.234'.length);
});
});
});

describe('keeps untouched decimal part if `precision: Infinity`', () => {
Expand Down
21 changes: 13 additions & 8 deletions projects/kit/src/lib/masks/number/number-mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ export function maskitoNumberOptionsGenerator({
? `${unsafePrefix}${CHAR_ZERO_WIDTH_SPACE}`
: unsafePrefix;

const initializationOnlyPreprocessor = createInitializationOnlyPreprocessor({
decimalSeparator,
decimalPseudoSeparators: validatedDecimalPseudoSeparators,
pseudoMinuses,
prefix,
postfix,
minusSign,
});

decimalSeparator =
precision <= 0 && decimalSeparator === thousandSeparator ? '' : decimalSeparator;

return {
...MASKITO_DEFAULT_OPTIONS,
mask: generateMaskExpression({
Expand All @@ -91,14 +103,7 @@ export function maskitoNumberOptionsGenerator({
}),
preprocessors: [
createFullWidthToHalfWidthPreprocessor(),
createInitializationOnlyPreprocessor({
decimalSeparator,
decimalPseudoSeparators: validatedDecimalPseudoSeparators,
pseudoMinuses,
prefix,
postfix,
minusSign,
}),
initializationOnlyPreprocessor,
createAffixesFilterPreprocessor({prefix, postfix}),
createPseudoCharactersPreprocessor({
validCharacter: minusSign,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {MaskitoPlugin} from '@maskito/core';
import {maskitoUpdateElement} from '@maskito/core';

import {maskitoEventHandler} from '../../../plugins';
import {escapeRegExp, extractAffixes} from '../../../utils';
import {escapeRegExp, extractAffixes, noop} from '../../../utils';

/**
* It pads EMPTY integer part with zero if decimal parts exists.
Expand All @@ -18,6 +18,10 @@ export function createNotEmptyIntegerPlugin({
prefix: string;
postfix: string;
}): MaskitoPlugin {
if (!decimalSeparator) {
return noop;
}

return maskitoEventHandler(
'blur',
(element) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export function emptyPostprocessor({
minusSign,
});
const aloneDecimalSeparator =
!integerPart && !decimalPart && cleanValue.includes(decimalSeparator);
!integerPart &&
!decimalPart &&
Boolean(decimalSeparator) &&
cleanValue.includes(decimalSeparator);

if (
(!integerPart &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ export function createLeadingZeroesValidationPostprocessor({
postfix,
});

const hasDecimalSeparator = cleanValue.includes(decimalSeparator);
const [integerPart = '', decimalPart = ''] = cleanValue.split(decimalSeparator);
const hasDecimalSeparator =
Boolean(decimalSeparator) && cleanValue.includes(decimalSeparator);
const [integerPart = '', decimalPart = ''] = decimalSeparator
? cleanValue.split(decimalSeparator)
: [cleanValue];
const zeroTrimmedIntegerPart = trimLeadingZeroes(integerPart);

if (integerPart === zeroTrimmedIntegerPart) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {MaskitoPreprocessor} from '@maskito/core';

import {escapeRegExp, extractAffixes} from '../../../utils';
import {escapeRegExp, extractAffixes, identity} from '../../../utils';

/**
* It rejects new typed decimal separator if it already exists in text field.
Expand All @@ -16,6 +16,10 @@ export function createRepeatedDecimalSeparatorPreprocessor({
prefix: string;
postfix: string;
}): MaskitoPreprocessor {
if (!decimalSeparator) {
return identity;
}

return ({elementState, data}) => {
const {value, selection} = elementState;
const [from, to] = selection;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ export function createThousandSeparatorPostprocessor({
decimalSeparator,
minusSign,
});
const hasDecimalSeparator =
decimalSeparator && cleanValue.includes(decimalSeparator);
const deletedChars =
cleanValue.length -
(
minus +
integerPart +
(cleanValue.includes(decimalSeparator)
? decimalSeparator + decimalPart
: '')
(hasDecimalSeparator ? decimalSeparator + decimalPart : '')
).length;

if (deletedChars > 0 && initialFrom && initialFrom <= deletedChars) {
Expand Down Expand Up @@ -105,7 +105,7 @@ export function createThousandSeparatorPostprocessor({
extractedPrefix +
minus +
processedIntegerPart +
(cleanValue.includes(decimalSeparator) ? decimalSeparator : '') +
(hasDecimalSeparator ? decimalSeparator : '') +
decimalPart +
extractedPostfix,
selection: [from, to],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ export function createZeroPrecisionPreprocessor({
prefix: string;
postfix: string;
}): MaskitoPreprocessor {
if (precision > 0) {
if (
precision > 0 ||
!decimalSeparator // all separators should be treated only as thousand separators
) {
return identity;
}

Expand Down
10 changes: 10 additions & 0 deletions projects/kit/src/lib/masks/number/tests/number-mask.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,4 +405,14 @@ describe('Number (maskitoTransform)', () => {

expect(maskitoTransform(' 123456 ', options)).toBe('123 456');
});

it('[thousandSeparator] is equal to [decimalSeparator] when [precision]=0', () => {
const options = maskitoNumberOptionsGenerator({
thousandSeparator: '.',
decimalSeparator: '.', // default value
precision: 0, // default value
});

expect(maskitoTransform('123.456', options)).toBe('123.456');
});
});
2 changes: 1 addition & 1 deletion projects/kit/src/lib/masks/number/utils/parse-number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function maskitoParseNumber(maskedNumber: string, decimalSeparator = '.')
.replaceAll(new RegExp(`${escapedDecimalSeparator}(?!\\d)`, 'g'), '')
// drop all non-digit characters except decimal separator
.replaceAll(new RegExp(`[^\\d${escapedDecimalSeparator}]`, 'g'), '')
.replace(decimalSeparator, '.');
.replace(decimalSeparator, decimalSeparator && '.');

if (unmaskedNumber) {
const sign = hasNegativeSign ? CHAR_HYPHEN : '';
Expand Down
10 changes: 10 additions & 0 deletions projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ describe('maskitoParseNumber', () => {
});
});

describe('decimal separator is empty string', () => {
it('thousand separator is point', () => {
expect(maskitoParseNumber('123.456.789', '')).toBe(123456789);
});

it('thousand separator is empty string', () => {
expect(maskitoParseNumber('123456', '')).toBe(123456);
});
});

describe('negative numbers', () => {
describe('minus sign', () => {
it('can be minus', () => {
Expand Down
4 changes: 3 additions & 1 deletion projects/kit/src/lib/masks/number/utils/to-number-parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export function toNumberParts(
value: string,
{decimalSeparator, minusSign}: {decimalSeparator: string; minusSign: string},
): {minus: string; integerPart: string; decimalPart: string} {
const [integerWithMinus = '', decimalPart = ''] = value.split(decimalSeparator);
const [integerWithMinus = '', decimalPart = ''] = decimalSeparator
? value.split(decimalSeparator)
: [value];
const escapedMinus = escapeRegExp(minusSign);
const [, minus = '', integerPart = ''] =
new RegExp(`^(?:[^\\d${escapedMinus}])?(${escapedMinus})?(.*)`).exec(
Expand Down
3 changes: 2 additions & 1 deletion projects/kit/src/lib/plugins/time/meridiem-stepping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import type {MaskitoPlugin} from '@maskito/core';
import {maskitoUpdateElement} from '@maskito/core';

import {ANY_MERIDIEM_CHARACTER_RE, CHAR_NO_BREAK_SPACE} from '../../constants';
import {noop} from '../../utils';

export function createMeridiemSteppingPlugin(meridiemStartIndex: number): MaskitoPlugin {
if (meridiemStartIndex < 0) {
return () => {};
return noop;
}

return (element) => {
Expand Down
3 changes: 1 addition & 2 deletions projects/kit/src/lib/plugins/time/time-segments-stepping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import type {MaskitoPlugin} from '@maskito/core';
import {maskitoUpdateElement} from '@maskito/core';

import type {MaskitoTimeSegments} from '../../types';

const noop = (): void => {};
import {noop} from '../../utils';

export function createTimeSegmentsSteppingPlugin({
step,
Expand Down
6 changes: 6 additions & 0 deletions projects/kit/src/lib/utils/dummy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function identity<T>(x: T): T {
return x;
}

// eslint-disable-next-line @typescript-eslint/no-empty-function
export function noop(): void {}
3 changes: 0 additions & 3 deletions projects/kit/src/lib/utils/identity.ts

This file was deleted.

2 changes: 1 addition & 1 deletion projects/kit/src/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export * from './date/parse-date-string';
export * from './date/segments-to-date';
export * from './date/to-date-string';
export * from './date/validate-date-string';
export * from './dummy';
export * from './escape-reg-exp';
export * from './extract-affixes';
export * from './find-common-beginning-substr';
export * from './identity';
export * from './is-empty';
export * from './pad-with-zeroes-until-valid';
export * from './to-half-width-colon';
Expand Down

0 comments on commit 19effe2

Please sign in to comment.