Skip to content

Commit

Permalink
fix(core): Maskito losses valid characters on invalid insertion (`o…
Browse files Browse the repository at this point in the history
…verwriteMode: replace`) (#208)
  • Loading branch information
nsbarsukov authored Mar 20, 2023
1 parent cbd5479 commit ef183b4
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 11 deletions.
31 changes: 21 additions & 10 deletions projects/core/src/lib/classes/mask-model/mask-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class MaskModel implements ElementState {

constructor(
readonly initialElementState: ElementState,
private readonly maskOptions: MaskitoOptions,
private readonly maskOptions: Required<MaskitoOptions>,
) {
const {value, selection} = calibrateValueByMask(
initialElementState,
Expand All @@ -37,23 +37,34 @@ export class MaskModel implements ElementState {
newCharacters,
this.maskOptions.overwriteMode,
).selection;
const newUnmaskedValue =
unmaskedElementState.value.slice(0, unmaskedFrom) +
newCharacters +
unmaskedElementState.value.slice(unmaskedTo);

const newCaretIndex = unmaskedFrom + newCharacters.length;
const newUnmaskedLeadingValuePart =
unmaskedElementState.value.slice(0, unmaskedFrom) + newCharacters;
const newCaretIndex = newUnmaskedLeadingValuePart.length;
const maskedElementState = calibrateValueByMask(
{
value: newUnmaskedValue,
value:
newUnmaskedLeadingValuePart +
unmaskedElementState.value.slice(unmaskedTo),
selection: [newCaretIndex, newCaretIndex],
},
maskExpression,
initialElementState,
);
const isInvalidCharsInsertion =
value.slice(0, unmaskedFrom) ===
calibrateValueByMask(
{
value: newUnmaskedLeadingValuePart,
selection: [newCaretIndex, newCaretIndex],
},
maskExpression,
initialElementState,
).value;

if (areElementStatesEqual(this, maskedElementState)) {
// If typing new characters does not change value
if (
isInvalidCharsInsertion ||
areElementStatesEqual(this, maskedElementState) // If typing new characters does not change value
) {
throw new Error('Invalid mask value');
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {MASKITO_DEFAULT_OPTIONS} from '../../../constants';
import {MaskitoOptions} from '../../../types';
import {MaskModel} from '../mask-model';

describe('MaskModel | Fixed characters', () => {
describe('New typed character is equal to the previous (already existing) fixed character', () => {
const phoneMaskitoOptions: MaskitoOptions = {
const phoneMaskitoOptions: Required<MaskitoOptions> = {
...MASKITO_DEFAULT_OPTIONS,
mask: [
'+',
'7',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,58 @@ describe('Number | decimalZeroPadding', () => {
.should('have.prop', 'selectionStart', ','.length)
.should('have.prop', 'selectionEnd', ','.length);
});

describe('Extra decimal separator insertion', () => {
it('42,|2700 => Type , => 42,|2700', () => {
cy.get('@input')
.type('42,27')
.type('{leftArrow}'.repeat('27'.length))
.should('have.value', '42,2700')
.should('have.prop', 'selectionStart', '42,'.length)
.should('have.prop', 'selectionEnd', '42,'.length)
.type(',')
.should('have.value', '42,2700')
.should('have.prop', 'selectionStart', '42,'.length)
.should('have.prop', 'selectionEnd', '42,'.length);
});

it('42|,2700 => Type , => 42,|2700', () => {
cy.get('@input')
.type('42,27')
.type('{leftArrow}'.repeat(',27'.length))
.should('have.value', '42,2700')
.should('have.prop', 'selectionStart', '42'.length)
.should('have.prop', 'selectionEnd', '42'.length)
.type(',')
.should('have.value', '42,2700')
.should('have.prop', 'selectionStart', '42,'.length)
.should('have.prop', 'selectionEnd', '42,'.length);
});

it('42,2|700 => Type , => 42,2|700', () => {
cy.get('@input')
.type('42,27')
.type('{leftArrow}')
.should('have.value', '42,2700')
.should('have.prop', 'selectionStart', '42,2'.length)
.should('have.prop', 'selectionEnd', '42,2'.length)
.type(',')
.should('have.value', '42,2700')
.should('have.prop', 'selectionStart', '42,2'.length)
.should('have.prop', 'selectionEnd', '42,2'.length);
});

it('9|9,1234 => Type , => 9,|9123', () => {
cy.get('@input')
.type('99,1234')
.type('{moveToStart}{rightArrow}')
.should('have.value', '99,1234')
.should('have.prop', 'selectionStart', 1)
.should('have.prop', 'selectionEnd', 1)
.type(',')
.should('have.value', '9,9123')
.should('have.prop', 'selectionStart', 2)
.should('have.prop', 'selectionEnd', 2);
});
});
});

0 comments on commit ef183b4

Please sign in to comment.