Skip to content

Commit

Permalink
feat(input): inclusão da propriedade p-mask-no-length-validation
Browse files Browse the repository at this point in the history
Adicionada a propriedade `p-mask-no-length-validation` ao componente `po-input` para permitir que caracteres especiais definidos na máscara sejam ignorados ao validar os comprimentos mínimos (minLength) e máximos (maxLength).

Essa funcionalidade garante maior flexibilidade ao lidar com máscaras, como no exemplo de números de telefone ou CEP, onde os caracteres especiais não devem interferir na validação do comprimento do valor.

Fixes DTHFUI-10421
  • Loading branch information
bruno-severino authored and anderson-gregorio-totvs committed Dec 13, 2024
1 parent 9452c68 commit 2db26fd
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,153 @@ describe('PoInputBase:', () => {
const validValues = [true, 'true', 1, ' '];
expectPropertiesValues(component, 'noAutocomplete', validValues, true);
});

describe('p-mask-no-length-validation:', () => {
describe('with p-maxlength:', () => {
it('validate: should return maxlength false when `maskNoLengthValidation` is false and value exceeds maxlength', () => {
component.maxlength = 5;
component.maskNoLengthValidation = false;
component.getScreenValue = () => '123456';

const result = component.validate(new FormControl('123456'));

expect(result).toEqual({
maxlength: {
valid: false
}
});
});

it('validate: should return null when `maskNoLengthValidation` is false and value is within maxlength', () => {
component.maxlength = 6;
component.maskNoLengthValidation = false;
component.getScreenValue = () => '123456';

const result = component.validate(new FormControl('123456'));

expect(result).toBeNull();
});

it('validate: should return maxlength false when `maskNoLengthValidation` is true, ignoring special characters, and value exceeds maxlength', () => {
component.maxlength = 5;
component.maskNoLengthValidation = true;
component.getScreenValue = () => '12-3456';

const result = component.validate(new FormControl('12-3456'));

expect(result).toEqual({
maxlength: {
valid: false
}
});
});

it('validate: should return null when `maskNoLengthValidation` is true and alphanumeric value is within maxlength ignoring special characters', () => {
component.maxlength = 6;
component.maskNoLengthValidation = true;
component.getScreenValue = () => '12-345';

const result = component.validate(new FormControl('12-345'));

expect(result).toBeNull();
});

it('validate: should handle special characters-only input correctly when `maskNoLengthValidation` is true', () => {
component.maxlength = 1;
component.maskNoLengthValidation = true;
component.getScreenValue = () => '---';

const result = component.validate(new FormControl('---'));

expect(result).toBeNull();
});

it('validate: should handle null or undefined values gracefully', () => {
component.maxlength = 5;
component.maskNoLengthValidation = true;

let result = component.validate(new FormControl(null));
expect(result).toBeNull();

result = component.validate(new FormControl(undefined));
expect(result).toBeNull();
});
});
describe('with p-minlength:', () => {
it('validate: should return minlength false when `maskNoLengthValidation` is false and value is below minlength', () => {
component.minlength = 5;
component.maskNoLengthValidation = false;
component.getScreenValue = () => '123';

const result = component.validate(new FormControl('123'));

expect(result).toEqual({
minlength: {
valid: false
}
});
});

it('validate: should return null when `maskNoLengthValidation` is false and value meets minlength', () => {
component.minlength = 3;
component.maskNoLengthValidation = false;
component.getScreenValue = () => '123';

const result = component.validate(new FormControl('123'));

expect(result).toBeNull();
});

it('validate: should return minlength false when `maskNoLengthValidation` is true, ignoring special characters, and value is below minlength', () => {
component.minlength = 5;
component.maskNoLengthValidation = true;
component.getScreenValue = () => '1-2-3';

const result = component.validate(new FormControl('1-2-3'));

expect(result).toEqual({
minlength: {
valid: false
}
});
});

it('validate: should return null when `maskNoLengthValidation` is true and alphanumeric value meets minlength ignoring special characters', () => {
component.minlength = 3;
component.maskNoLengthValidation = true;
component.getScreenValue = () => '1-2-3';

const result = component.validate(new FormControl('1-2-3'));

expect(result).toBeNull();
});

it('validate: should handle special characters-only input correctly when `maskNoLengthValidation` is true', () => {
component.minlength = 1;
component.maskNoLengthValidation = true;
component.getScreenValue = () => '---';

const result = component.validate(new FormControl('---'));

expect(result).toEqual({
minlength: {
valid: false
}
});
});

it('validate: should handle null or undefined values gracefully', () => {
component.minlength = 5;
component.maskNoLengthValidation = true;

let result = component.validate(new FormControl(null));
expect(result).toBeNull();

result = component.validate(new FormControl(undefined));
expect(result).toBeNull();
});
});
});
});

describe('Methods:', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,29 @@ export abstract class PoInputBaseComponent implements ControlValueAccessor, Vali
*/
@Input({ alias: 'p-upper-case', transform: convertToBoolean }) upperCase: boolean = false;

/**
* @description
*
* Define se os caracteres especiais da máscara devem ser ignorados ao validar os comprimentos mínimo (`minLength`) e máximo (`maxLength`) do campo.
*
* - Quando `true`, apenas os caracteres alfanuméricos serão contabilizados para a validação dos comprimentos.
* - Quando `false`, todos os caracteres, incluindo os especiais da máscara, serão considerados na validação.
*
* Exemplo:
* ```
* <po-input
* p-mask="999-999"
* p-maxlength="6"
* p-minlength="4"
* p-mask-no-length-validation="true"
* ></po-input>
* ```
* - Entrada: `123-456` → Validação será aplicada somente aos números, ignorando o caractere especial `-`.
*
* @default `false`
*/
@Input({ alias: 'p-mask-no-length-validation', transform: convertToBoolean }) maskNoLengthValidation: boolean = false;

/**
* @optional
*
Expand Down Expand Up @@ -487,7 +510,7 @@ export abstract class PoInputBaseComponent implements ControlValueAccessor, Vali
};
}

if (maxlengpoailed(this.maxlength, this.getScreenValue())) {
if (maxlengpoailed(this.maxlength, this.getScreenValue(), this.maskNoLengthValidation)) {
this.isInvalid = true;
return {
maxlength: {
Expand All @@ -496,7 +519,7 @@ export abstract class PoInputBaseComponent implements ControlValueAccessor, Vali
};
}

if (minlengpoailed(this.minlength, this.getScreenValue())) {
if (minlengpoailed(this.minlength, this.getScreenValue(), this.maskNoLengthValidation)) {
this.isInvalid = true;
return {
minlength: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
[p-readonly]="properties?.includes('readonly')"
[p-upper-case]="properties?.includes('uppercase')"
[p-show-required]="properties?.includes('showRequired')"
[p-mask-no-length-validation]="properties?.includes('maskNoLengthValidation')"
(p-blur)="changeEvent('p-blur')"
(p-change)="changeEvent('p-change')"
(p-change-model)="changeEvent('p-change-model')"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export class SamplePoInputLabsComponent implements OnInit {
{ value: 'required', label: 'Required' },
{ value: 'requiredFieldErrorMessage', label: 'Required Field Error Message' },
{ value: 'uppercase', label: 'Upper Case' },
{ value: 'showRequired', label: 'Show Required' }
{ value: 'showRequired', label: 'Show Required' },
{ value: 'maskNoLengthValidation', label: 'Mask No Length Validation' }
];

ngOnInit() {
Expand Down
124 changes: 104 additions & 20 deletions projects/ui/src/lib/components/po-field/validators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
patternFailed,
minFailed,
maxFailed,
dateFailed
dateFailed,
validateLength
} from './validators';

describe('requiredFailed: ', () => {
Expand Down Expand Up @@ -41,25 +42,41 @@ describe('requiredFailed: ', () => {
});

describe('Function maxlengpoailed:', () => {
it('should return `true` if value.length is greater than `maxlength`', () => {
expect(maxlengpoailed(3, '1234')).toBeTruthy();
expect(maxlengpoailed(3, '1234567')).toBeTruthy();
expect(maxlengpoailed(5, 'abcdef')).toBeTruthy();
expect(maxlengpoailed(10, 'abcdefghijk')).toBeTruthy();
expect(maxlengpoailed(0, 'abc')).toBeTruthy();
});

it('should return `false` if value.length is less or equal than `maxlength` or value or `maxlength` is invalid', () => {
expect(maxlengpoailed(3, '123')).toBeFalsy();
expect(maxlengpoailed(1, '1')).toBeFalsy();
expect(maxlengpoailed(0, '')).toBeFalsy();
expect(maxlengpoailed(20, null)).toBeFalsy();
expect(maxlengpoailed(20, undefined)).toBeFalsy();
expect(maxlengpoailed(5, 'abcd')).toBeFalsy();
expect(maxlengpoailed(2, 'a')).toBeFalsy();
expect(maxlengpoailed(undefined, 'abc')).toBeFalsy();
expect(maxlengpoailed(null, '123')).toBeFalsy();
expect(maxlengpoailed(NaN, '123')).toBeFalsy();
it('should return `true` if value.length is greater than `maxlength` without ignoring special characters', () => {
expect(maxlengpoailed(3, '1234', false)).toBeTruthy();
expect(maxlengpoailed(5, 'abc-de', false)).toBeTruthy();
expect(maxlengpoailed(7, 'abc@def!', false)).toBeTruthy();
});

it('should return `false` if value.length is less or equal than `maxlength` without ignoring special characters', () => {
expect(maxlengpoailed(3, '123', false)).toBeFalsy();
expect(maxlengpoailed(6, 'abc-def', false)).toBeTruthy();
expect(maxlengpoailed(7, 'abcdef!', false)).toBeFalsy();
});

it('should return `true` if alphanumeric value.length exceeds `maxlength` while ignoring special characters', () => {
expect(maxlengpoailed(3, '123-4', true)).toBeTruthy();
expect(maxlengpoailed(3, 'abc@de!', true)).toBeTruthy();
});

it('should return `false` if alphanumeric value.length is within `maxlength` while ignoring special characters', () => {
expect(maxlengpoailed(4, '123-4', true)).toBeFalsy();
expect(maxlengpoailed(5, 'abc@d!', true)).toBeFalsy();
});

it('should handle null or undefined values gracefully', () => {
expect(maxlengpoailed(3, null, true)).toBeFalsy();
expect(maxlengpoailed(3, undefined, true)).toBeFalsy();
});

it('should handle edge cases for special character-only inputs', () => {
expect(maxlengpoailed(1, '---', true)).toBeFalsy();
expect(maxlengpoailed(1, '@@@', true)).toBeFalsy();
});

it('should consider all characters when ignoring special characters is disabled', () => {
expect(maxlengpoailed(5, '123-4', false)).toBeFalsy();
expect(maxlengpoailed(5, 'abc@!', false)).toBeFalsy();
});
});

Expand All @@ -85,6 +102,73 @@ describe('Function minlengpoailed:', () => {
expect(minlengpoailed(NaN, '123')).toBeFalsy();
expect(minlengpoailed(0, '123')).toBeFalsy();
});

it('should correctly handle maskNoLengthValidation when true', () => {
expect(minlengpoailed(3, '1-2', true)).toBeTruthy();
expect(minlengpoailed(3, '1-2-3', true)).toBeFalsy();
expect(minlengpoailed(5, '12-345', true)).toBeFalsy();
expect(minlengpoailed(5, '12--34', true)).toBeTruthy();
});

it('should correctly handle maskNoLengthValidation when false', () => {
expect(minlengpoailed(3, '1-2', false)).toBeFalsy();
expect(minlengpoailed(3, '1-2-3', false)).toBeFalsy();
expect(minlengpoailed(5, '12-345', false)).toBeFalsy();
expect(minlengpoailed(5, '12--34', false)).toBeFalsy();
});

it('should return `false` for invalid values or limits regardless of maskNoLengthValidation', () => {
expect(minlengpoailed(undefined, '123', true)).toBeFalsy();
expect(minlengpoailed(null, '123', true)).toBeFalsy();
expect(minlengpoailed(3, null, true)).toBeFalsy();
expect(minlengpoailed(3, undefined, true)).toBeFalsy();

expect(minlengpoailed(undefined, '123', false)).toBeFalsy();
expect(minlengpoailed(null, '123', false)).toBeFalsy();
expect(minlengpoailed(3, null, false)).toBeFalsy();
expect(minlengpoailed(3, undefined, false)).toBeFalsy();
});
});

describe('Function validateLength:', () => {
it('should return true if value length exceeds limit and comparison is "max"', () => {
expect(validateLength(3, '1234', 'max')).toBeTruthy();
expect(validateLength(5, 'abcdef', 'max')).toBeTruthy();
});

it('should return false if value length is within limit and comparison is "max"', () => {
expect(validateLength(3, '123', 'max')).toBeFalsy();
expect(validateLength(5, 'abcd', 'max')).toBeFalsy();
});

it('should return true if value length is below limit and comparison is "min"', () => {
expect(validateLength(5, '1234', 'min')).toBeTruthy();
expect(validateLength(3, '12', 'min')).toBeTruthy();
});

it('should return false if value length meets or exceeds limit and comparison is "min"', () => {
expect(validateLength(3, '123', 'min')).toBeFalsy();
expect(validateLength(5, 'abcdef', 'min')).toBeFalsy();
});

it('should correctly handle maskNoLengthValidation when true', () => {
expect(validateLength(5, '1-2-3-4-5', 'max', true)).toBeFalsy();
expect(validateLength(5, '1-2-3', 'min', true)).toBeTruthy();
});

it('should return false for invalid values or limits', () => {
expect(validateLength(undefined, '123', 'max')).toBeFalsy();
expect(validateLength(null, '123', 'max')).toBeFalsy();
expect(validateLength(3, null, 'max')).toBeFalsy();
expect(validateLength(3, undefined, 'max')).toBeFalsy();
});

it('should return false if comparison is not "max" or "min"', () => {
expect(validateLength(3, '1234', 'invalidComparison' as any)).toBeFalsy();
expect(validateLength(3, '1234', '' as any)).toBeFalsy();
expect(validateLength(3, '1234', null)).toBeFalsy();
expect(validateLength(3, '1234', undefined)).toBeFalsy();
});
});

describe('Function patternFailed', () => {
Expand Down
Loading

0 comments on commit 2db26fd

Please sign in to comment.