Skip to content

Commit

Permalink
fix(kit): Number fails to prevent user insertion of extra spaces on…
Browse files Browse the repository at this point in the history
… invalid positions (#1789)
  • Loading branch information
nsbarsukov authored Oct 17, 2024
1 parent 1733422 commit a40445c
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,17 @@ describe('Number | should drop decimal separator if all digits are erased', () =
.type(`{moveToStart}${'{rightArrow}'.repeat(minusSign.length)}`)
.type('{del}')
.should('have.value', minusSign)
.should('have.prop', 'selectionStart', minusSign.length)
.should('have.prop', 'selectionEnd', minusSign.length)
// and then repeat everything in reversed order
.type('0.12')
.type(`{moveToStart}${'{rightArrow}'.repeat(minusSign.length)}`)
.type('{del}')
.type('{moveToEnd}')
.type('{backspace}'.repeat(2))
.should('have.value', minusSign);
.should('have.value', minusSign)
.should('have.prop', 'selectionStart', minusSign.length)
.should('have.prop', 'selectionEnd', minusSign.length);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {openNumberPage} from './utils';

describe('Number | thousandSeparator', () => {
beforeEach(() => {
openNumberPage('thousandSeparator=-');
});

describe('adds thousand separator after pressing new digit', () => {
beforeEach(() => {
openNumberPage('thousandSeparator=-');
});

const tests = [
// [Typed value, Masked value]
['1', '1'],
Expand All @@ -30,6 +30,7 @@ describe('Number | thousandSeparator', () => {

describe('move thousand separator after deleting a digit (initial: 1-000-000)', () => {
beforeEach(() => {
openNumberPage('thousandSeparator=-');
cy.get('@input').type('1000000');
});

Expand All @@ -55,6 +56,10 @@ describe('Number | thousandSeparator', () => {
});

describe('Editing somewhere in the middle of a value (NOT the last character)', () => {
beforeEach(() => {
openNumberPage('thousandSeparator=-');
});

it('1-00|0-000 => Backspace => 10|0-000 => Type "5" => 1-05|0-000', () => {
cy.get('@input')
.type('1000000')
Expand Down Expand Up @@ -138,6 +143,8 @@ describe('Number | thousandSeparator', () => {
});

it('allows to set empty string as thousand separator', () => {
openNumberPage('thousandSeparator=-');

cy.get('tr').contains('[thousandSeparator]').parents('tr').find('input').clear();

cy.get('@input')
Expand All @@ -146,4 +153,58 @@ describe('Number | thousandSeparator', () => {
.should('have.prop', 'selectionStart', '1000000'.length)
.should('have.prop', 'selectionEnd', '1000000'.length);
});

describe('prevent insertion of extra spaces (thousand separator is equal to non-breaking space) on invalid positions', () => {
beforeEach(() => openNumberPage());

it('paste value with extra leading and trailing spaces', () => {
cy.get('@input')
.paste(' 123456 ')
.should('have.value', '123 456')
.should('have.prop', 'selectionStart', '123 456'.length)
.should('have.prop', 'selectionEnd', '123 456'.length);
});

it('|123 => Press space => |123', () => {
cy.get('@input')
.type('123')
.type('{moveToStart}')
.type(' ')
.should('have.value', '123')
.should('have.prop', 'selectionStart', 0)
.should('have.prop', 'selectionEnd', 0);
});

it('1|23 => Press space => 1|23', () => {
cy.get('@input')
.type('123')
.type('{moveToStart}')
.type('{rightArrow}')
.type(' ')
.should('have.value', '123')
.should('have.prop', 'selectionStart', 1)
.should('have.prop', 'selectionEnd', 1);
});

it('12|3 => Press space => 12|3', () => {
cy.get('@input')
.type('123')
.type('{moveToStart}')
.type('{rightArrow}'.repeat(2))
.type(' ')
.should('have.value', '123')
.should('have.prop', 'selectionStart', 2)
.should('have.prop', 'selectionEnd', 2);
});

it('123| => Press space => 123|', () => {
cy.get('@input')
.type('123')
.type('{moveToEnd}')
.type(' ')
.should('have.value', '123')
.should('have.prop', 'selectionStart', 3)
.should('have.prop', 'selectionEnd', 3);
});
});
});
2 changes: 1 addition & 1 deletion projects/demo-integrations/src/tests/kit/number/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {DemoPath} from '@demo/constants';

export function openNumberPage(queryParams: string): void {
export function openNumberPage(queryParams = ''): void {
cy.visit(`/${DemoPath.Number}/API?${queryParams}`);
cy.get('#demo-content input')
.should('be.visible')
Expand Down
6 changes: 0 additions & 6 deletions projects/demo/src/app/modules/logo/logo.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,3 @@
Maskito
</span>
</a>

<img
alt="by T-Bank"
src="assets/icons/by.svg"
class="by"
/>
35 changes: 0 additions & 35 deletions projects/demo/src/assets/icons/by.svg

This file was deleted.

8 changes: 7 additions & 1 deletion projects/kit/src/lib/masks/number/number-mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export function maskitoNumberOptionsGenerator({
thousandSeparator,
prefix,
postfix,
minusSign,
}),
createDecimalZeroPaddingPostprocessor({
decimalSeparator,
Expand All @@ -152,7 +153,12 @@ export function maskitoNumberOptionsGenerator({
prefix,
postfix,
}),
emptyPostprocessor({prefix, postfix, decimalSeparator, thousandSeparator}),
emptyPostprocessor({
prefix,
postfix,
decimalSeparator,
minusSign,
}),
],
plugins: [
createLeadingZeroesValidationPlugin({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ export function emptyPostprocessor({
prefix,
postfix,
decimalSeparator,
thousandSeparator,
minusSign,
}: {
prefix: string;
postfix: string;
decimalSeparator: string;
thousandSeparator: string;
minusSign: string;
}): MaskitoPostprocessor {
return ({value, selection}) => {
const [caretIndex] = selection;
Expand All @@ -28,7 +28,7 @@ export function emptyPostprocessor({
});
const {minus, integerPart, decimalPart} = toNumberParts(cleanValue, {
decimalSeparator,
thousandSeparator,
minusSign,
});
const aloneDecimalSeparator =
!integerPart && !decimalPart && cleanValue.includes(decimalSeparator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ export function createThousandSeparatorPostprocessor({
decimalSeparator,
prefix,
postfix,
minusSign,
}: {
thousandSeparator: string;
decimalSeparator: string;
prefix: string;
postfix: string;
minusSign: string;
}): MaskitoPostprocessor {
if (!thousandSeparator) {
return identity;
Expand All @@ -25,34 +27,51 @@ export function createThousandSeparatorPostprocessor({
const isAllSpaces = (...chars: string[]): boolean => chars.every((x) => /\s/.test(x));

return ({value, selection}) => {
const [initialFrom, initialTo] = selection;
let [from, to] = selection;

const {cleanValue, extractedPostfix, extractedPrefix} = extractAffixes(value, {
prefix,
postfix,
});

const {minus, integerPart, decimalPart} = toNumberParts(cleanValue, {
decimalSeparator,
thousandSeparator,
minusSign,
});
const [initialFrom, initialTo] = selection;
let [from, to] = selection;
const deletedChars =
cleanValue.length -
(
minus +
integerPart +
(cleanValue.includes(decimalSeparator)
? decimalSeparator + decimalPart
: '')
).length;

if (deletedChars > 0 && initialFrom && initialFrom <= deletedChars) {
from -= deletedChars;
}

if (deletedChars > 0 && initialTo && initialTo <= deletedChars) {
to -= deletedChars;
}

const processedIntegerPart = Array.from(integerPart).reduceRight(
(formattedValuePart, char, i) => {
const isLeadingThousandSeparator = !i && char === thousandSeparator;
const isPositionForSeparator =
!isLeadingThousandSeparator &&
formattedValuePart.length &&
Boolean(formattedValuePart.length) &&
(formattedValuePart.length + 1) % 4 === 0;
const isSeparator =
char === thousandSeparator || isAllSpaces(char, thousandSeparator);

if (
isPositionForSeparator &&
(char === thousandSeparator || isAllSpaces(char, thousandSeparator))
) {
if (isPositionForSeparator && isSeparator) {
return thousandSeparator + formattedValuePart;
}

if (char === thousandSeparator && !isPositionForSeparator) {
if (!isPositionForSeparator && isSeparator) {
if (i && i <= initialFrom) {
from--;
}
Expand Down
8 changes: 8 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 @@ -397,4 +397,12 @@ describe('Number (maskitoTransform)', () => {
});
});
});

it('autofill value with extra leading and trailing whitespace (thousand separator is equal to whitespace too)', () => {
const options = maskitoNumberOptionsGenerator({
thousandSeparator: ' ',
});

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

0 comments on commit a40445c

Please sign in to comment.