From 0e1416bf734e2fe359b3a1cbbfca5ac85b76c467 Mon Sep 17 00:00:00 2001 From: iman Date: Sat, 3 Aug 2024 08:13:01 +0330 Subject: [PATCH 1/3] feat: ArraySize decorator and function --- src/decorator/array/ArraySize.ts | 33 ++++++++++++++++++++++++++++++++ src/decorator/decorators.ts | 1 + 2 files changed, 34 insertions(+) create mode 100644 src/decorator/array/ArraySize.ts diff --git a/src/decorator/array/ArraySize.ts b/src/decorator/array/ArraySize.ts new file mode 100644 index 0000000000..46af758c34 --- /dev/null +++ b/src/decorator/array/ArraySize.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from '../ValidationOptions'; +import { buildMessage, ValidateBy } from '../common/ValidateBy'; + +export const ARRAY_SIZE = 'arraySize'; + +/** + * Checks if the array's length is equal to the specified number. + * If null or undefined is given then this function returns false. + */ +export function arraySize(array: unknown, size: number): boolean { + return Array.isArray(array) && array.length === size; +} + +/** + * Checks if the array's length is equal to the specified number. + * If null or undefined is given then this function returns false. + */ +export function ArraySize(size: number, validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: ARRAY_SIZE, + constraints: [size], + validator: { + validate: (value, args): boolean => arraySize(value, args?.constraints[0]), + defaultMessage: buildMessage( + eachPrefix => eachPrefix + '$property must contain exactly $constraint1 elements', + validationOptions + ), + }, + }, + validationOptions + ); +} diff --git a/src/decorator/decorators.ts b/src/decorator/decorators.ts index d449e9301a..8b07389a6b 100644 --- a/src/decorator/decorators.ts +++ b/src/decorator/decorators.ts @@ -140,6 +140,7 @@ export * from './array/ArrayNotEmpty'; export * from './array/ArrayMinSize'; export * from './array/ArrayMaxSize'; export * from './array/ArrayUnique'; +export * from './array/ArraySize'; // ------------------------------------------------------------------------- // Object checkers From 02d610aee9ea701f21d76b26df7ac70e01baa5e9 Mon Sep 17 00:00:00 2001 From: iman Date: Sat, 3 Aug 2024 08:13:28 +0330 Subject: [PATCH 2/3] test: add test for ArraySize and arraySize --- ...alidation-functions-and-decorators.spec.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/functional/validation-functions-and-decorators.spec.ts b/test/functional/validation-functions-and-decorators.spec.ts index 78ceddcd6d..7c0cbd852b 100644 --- a/test/functional/validation-functions-and-decorators.spec.ts +++ b/test/functional/validation-functions-and-decorators.spec.ts @@ -193,6 +193,8 @@ import { isTaxId, IsTaxId, IsISO4217CurrencyCode, + ArraySize, + arraySize, } from '../../src/decorator/decorators'; import { Validator } from '../../src/validation/Validator'; import { ValidatorOptions } from '../../src/validation/ValidatorOptions'; @@ -4523,6 +4525,39 @@ describe('ArrayMaxSize', () => { }); }); +describe('ArraySize', () => { + const constraint = 2; + const validValues = [['world', 'hello']]; + const invalidValues = [null, undefined, ['hi', 'typescript', 'javascript'], { test: 'me' }]; + + class MyClass { + @ArraySize(constraint) + someProperty: string; + } + + it('should not fail if validator.validate said that its valid', () => { + return checkValidValues(new MyClass(), validValues); + }); + + it('should fail if validator.validate said that its invalid', () => { + return checkInvalidValues(new MyClass(), invalidValues); + }); + + it('should not fail if method in validator said that its valid', () => { + validValues.forEach(value => expect(arraySize(value, constraint)).toBeTruthy()); + }); + + it('should fail if method in validator said that its invalid', () => { + invalidValues.forEach(value => expect(arraySize(value, constraint)).toBeFalsy()); + }); + + it('should return error object with proper data', () => { + const validationType = 'arraySize'; + const message = 'someProperty must contain exactly ' + constraintToString(constraint) + ' elements'; + return checkReturnedError(new MyClass(), invalidValues, validationType, message); + }); +}); + describe('ArrayUnique', () => { const validValues = [ ['world', 'hello', 'superman'], From 80b979ff4a287c2b5c7302eb9d8ccab7eb681c90 Mon Sep 17 00:00:00 2001 From: iman Date: Sat, 3 Aug 2024 08:14:06 +0330 Subject: [PATCH 3/3] docs: update documentation add ArraySize --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 886712dd76..825fcc801a 100644 --- a/README.md +++ b/README.md @@ -907,6 +907,7 @@ isBoolean(value); | `@ArrayNotEmpty()` | Checks if given array is not empty. | | `@ArrayMinSize(min: number)` | Checks if the array's length is greater than or equal to the specified number. | | `@ArrayMaxSize(max: number)` | Checks if the array's length is less or equal to the specified number. | +| `@ArraySize(size: number)` | Checks if the array's length is equal to the specified number. | | `@ArrayUnique(identifier?: (o) => any)` | Checks if all array's values are unique. Comparison for objects is reference-based. Optional function can be speciefied which return value will be used for the comparsion. | | **Object validation decorators** | | `@IsInstance(value: any)` | Checks if the property is an instance of the passed value. |