Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(kit): Number fails to prevent user insertion of extra spaces on invalid positions #1789

Merged
merged 2 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading