diff --git a/README.md b/README.md index a9e64d882f..996e9dd90a 100644 --- a/README.md +++ b/README.md @@ -606,7 +606,6 @@ If you have custom validation logic you can create a _Constraint class_: Also we defined optional method `defaultMessage` which defines a default error message, in the case that the decorator's implementation doesn't set an error message. - 2. Then you can use your new validation constraint in your class: ```typescript @@ -622,7 +621,6 @@ If you have custom validation logic you can create a _Constraint class_: ``` Here we set our newly created `CustomTextLength` validation constraint for `Post.title`. - 3. And use validator as usual: ```typescript @@ -689,7 +687,6 @@ Lets create a decorator called `@IsLongerThan`: }; } ``` - 2. Put it to use: ```typescript @@ -744,7 +741,6 @@ Lets create another custom validation decorator called `IsUserAlreadyExist`: ``` note that we marked our constraint that it will by async by adding `{ async: true }` in validation options. - 2. And put it to use: ```typescript @@ -794,128 +790,129 @@ isBoolean(value); ## Validation decorators -| Decorator | Description | -| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Common validation decorators** | | -| `@IsDefined(value: any)` | Checks if value is defined (!== undefined, !== null). This is the only decorator that ignores skipMissingProperties option. | -| `@IsOptional()` | Checks if given value is empty (=== null, === undefined) and if so, ignores all the validators on the property. | -| `@Equals(comparison: any)` | Checks if value equals ("===") comparison. | -| `@NotEquals(comparison: any)` | Checks if value not equal ("!==") comparison. | -| `@IsEmpty()` | Checks if given value is empty (=== '', === null, === undefined). | -| `@IsNotEmpty()` | Checks if given value is not empty (!== '', !== null, !== undefined). | -| `@IsIn(values: any[])` | Checks if value is in an array of allowed values. | -| `@IsNotIn(values: any[])` | Checks if value is not in an array of disallowed values. | -| **Type validation decorators** | | -| `@IsBoolean()` | Checks if a value is a boolean. | -| `@IsDate()` | Checks if the value is a date. | -| `@IsString()` | Checks if the value is a string. | -| `@IsNumber(options: IsNumberOptions)` | Checks if the value is a number. | -| `@IsInt()` | Checks if the value is an integer number. | -| `@IsArray()` | Checks if the value is an array | -| `@IsEnum(entity: object)` | Checks if the value is a valid enum | -| **Number validation decorators** | -| `@IsDivisibleBy(num: number)` | Checks if the value is a number that's divisible by another. | -| `@IsPositive()` | Checks if the value is a positive number greater than zero. | -| `@IsNegative()` | Checks if the value is a negative number smaller than zero. | -| `@Min(min: number)` | Checks if the given number is greater than or equal to given number. | -| `@Max(max: number)` | Checks if the given number is less than or equal to given number. | -| **Date validation decorators** | -| `@MinDate(date: Date \| (() => Date))` | Checks if the value is a date that's after the specified date. | -| `@MaxDate(date: Date \| (() => Date))` | Checks if the value is a date that's before the specified date. | -| **String-type validation decorators** | | -| `@IsBooleanString()` | Checks if a string is a boolean (e.g. is "true" or "false" or "1", "0"). | -| `@IsDateString()` | Alias for `@IsISO8601()`. | -| `@IsNumberString(options?: IsNumericOptions)` | Checks if a string is a number. | -| **String validation decorators** | | -| `@Contains(seed: string)` | Checks if the string contains the seed. | -| `@NotContains(seed: string)` | Checks if the string not contains the seed. | -| `@IsAlpha()` | Checks if the string contains only letters (a-zA-Z). | -| `@IsAlphanumeric()` | Checks if the string contains only letters and numbers. | -| `@IsDecimal(options?: IsDecimalOptions)` | Checks if the string is a valid decimal value. Default IsDecimalOptions are `force_decimal=False`, `decimal_digits: '1,'`, `locale: 'en-US'` | -| `@IsAscii()` | Checks if the string contains ASCII chars only. | -| `@IsBase32()` | Checks if a string is base32 encoded. | -| `@IsBase58()` | Checks if a string is base58 encoded. | -| `@IsBase64(options?: IsBase64Options)` | Checks if a string is base64 encoded. | -| `@IsIBAN()` | Checks if a string is a IBAN (International Bank Account Number). | -| `@IsBIC()` | Checks if a string is a BIC (Bank Identification Code) or SWIFT code. | -| `@IsByteLength(min: number, max?: number)` | Checks if the string's length (in bytes) falls in a range. | -| `@IsCreditCard()` | Checks if the string is a credit card. | -| `@IsCurrency(options?: IsCurrencyOptions)` | Checks if the string is a valid currency amount. | -| `@IsISO4217CurrencyCode()` | Checks if the string is an ISO 4217 currency code. | -| `@IsEthereumAddress()` | Checks if the string is an Ethereum address using basic regex. Does not validate address checksums. | -| `@IsBtcAddress()` | Checks if the string is a valid BTC address. | -| `@IsDataURI()` | Checks if the string is a data uri format. | -| `@IsEmail(options?: IsEmailOptions)` | Checks if the string is an email. | -| `@IsFQDN(options?: IsFQDNOptions)` | Checks if the string is a fully qualified domain name (e.g. domain.com). | -| `@IsFullWidth()` | Checks if the string contains any full-width chars. | -| `@IsHalfWidth()` | Checks if the string contains any half-width chars. | -| `@IsVariableWidth()` | Checks if the string contains a mixture of full and half-width chars. | -| `@IsHexColor()` | Checks if the string is a hexadecimal color. | -| `@IsHSL()` | Checks if the string is an HSL color based on [CSS Colors Level 4 specification](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). | -| `@IsRgbColor(options?: IsRgbOptions)` | Checks if the string is a rgb or rgba color. | -| `@IsIdentityCard(locale?: string)` | Checks if the string is a valid identity card code. | -| `@IsPassportNumber(countryCode?: string)` | Checks if the string is a valid passport number relative to a specific country code. | -| `@IsPostalCode(locale?: string)` | Checks if the string is a postal code. | -| `@IsHexadecimal()` | Checks if the string is a hexadecimal number. | -| `@IsOctal()` | Checks if the string is a octal number. | -| `@IsMACAddress(options?: IsMACAddressOptions)` | Checks if the string is a MAC Address. | -| `@IsIP(version?: "4"\|"6")` | Checks if the string is an IP (version 4 or 6). | -| `@IsPort()` | Checks if the string is a valid port number. | -| `@IsISBN(version?: "10"\|"13")` | Checks if the string is an ISBN (version 10 or 13). | -| `@IsEAN()` | Checks if the string is an if the string is an EAN (European Article Number). | -| `@IsISIN()` | Checks if the string is an ISIN (stock/security identifier). | -| `@IsISO8601(options?: IsISO8601Options)` | Checks if the string is a valid ISO 8601 date format. Use the option strict = true for additional checks for a valid date. | -| `@IsJSON()` | Checks if the string is valid JSON. | -| `@IsJWT()` | Checks if the string is valid JWT. | -| `@IsObject()` | Checks if the object is valid Object (null, functions, arrays will return false). | -| `@IsNotEmptyObject()` | Checks if the object is not empty. | -| `@IsLowercase()` | Checks if the string is lowercase. | -| `@IsLatLong()` | Checks if the string is a valid latitude-longitude coordinate in the format lat, long. | -| `@IsLatitude()` | Checks if the string or number is a valid latitude coordinate. | -| `@IsLongitude()` | Checks if the string or number is a valid longitude coordinate. | -| `@IsMobilePhone(locale: string)` | Checks if the string is a mobile phone number. | -| `@IsISO31661Alpha2()` | Checks if the string is a valid ISO 3166-1 alpha-2 officially assigned country code. | -| `@IsISO31661Alpha3()` | Checks if the string is a valid ISO 3166-1 alpha-3 officially assigned country code. | -| `@IsLocale()` | Checks if the string is a locale. | -| `@IsPhoneNumber(region: string)` | Checks if the string is a valid phone number using libphonenumber-js. | -| `@IsMongoId()` | Checks if the string is a valid hex-encoded representation of a MongoDB ObjectId. | -| `@IsMultibyte()` | Checks if the string contains one or more multibyte chars. | -| `@IsNumberString(options?: IsNumericOptions)` | Checks if the string is numeric. | -| `@IsSurrogatePair()` | Checks if the string contains any surrogate pairs chars. | -| `@IsTaxId()` | Checks if the string is a valid tax ID. Default locale is `en-US`. | -| `@IsUrl(options?: IsURLOptions)` | Checks if the string is a URL. | -| `@IsMagnetURI()` | Checks if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). | -| `@IsUUID(version?: UUIDVersion)` | Checks if the string is a UUID (version 3, 4, 5 or all ). | -| `@IsFirebasePushId()` | Checks if the string is a [Firebase Push ID](https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html) | -| `@IsUppercase()` | Checks if the string is uppercase. | -| `@Length(min: number, max?: number)` | Checks if the string's length falls in a range. | -| `@MinLength(min: number)` | Checks if the string's length is not less than given number. | -| `@MaxLength(max: number)` | Checks if the string's length is not more than given number. | -| `@Matches(pattern: RegExp, modifiers?: string)` | Checks if string matches the pattern. Either matches('foo', /foo/i) or matches('foo', 'foo', 'i'). | -| `@IsMilitaryTime()` | Checks if the string is a valid representation of military time in the format HH:MM. | -| `@IsTimeZone()` | Checks if the string represents a valid IANA time-zone. | +| Decorator | Description | +| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Common validation decorators** | | +| `@IsDefined(value: any)` | Checks if value is defined (!== undefined, !== null). This is the only decorator that ignores skipMissingProperties option. | +| `@IsOptional()` | Checks if given value is empty (=== null, === undefined) and if so, ignores all the validators on the property. | +| `@Equals(comparison: any)` | Checks if value equals ("===") comparison. | +| `@NotEquals(comparison: any)` | Checks if value not equal ("!==") comparison. | +| `@IsEmpty()` | Checks if given value is empty (=== '', === null, === undefined). | +| `@IsNotEmpty()` | Checks if given value is not empty (!== '', !== null, !== undefined). | +| `@IsIn(values: any[])` | Checks if value is in an array of allowed values. | +| `@IsNotIn(values: any[])` | Checks if value is not in an array of disallowed values. | +| **Type validation decorators** | | +| `@IsBoolean()` | Checks if a value is a boolean. | +| `@IsDate()` | Checks if the value is a date. | +| `@IsString()` | Checks if the value is a string. | +| `@IsNumber(options: IsNumberOptions)` | Checks if the value is a number. | +| `@IsInt()` | Checks if the value is an integer number. | +| `@IsSafeInt()` | Checks if the value is an safe integer number. | +| `@IsArray()` | Checks if the value is an array | +| `@IsEnum(entity: object)` | Checks if the value is a valid enum | +| **Number validation decorators** | | +| `@IsDivisibleBy(num: number)` | Checks if the value is a number that's divisible by another. | +| `@IsPositive()` | Checks if the value is a positive number greater than zero. | +| `@IsNegative()` | Checks if the value is a negative number smaller than zero. | +| `@Min(min: number)` | Checks if the given number is greater than or equal to given number. | +| `@Max(max: number)` | Checks if the given number is less than or equal to given number. | +| **Date validation decorators** | | +| `@MinDate(date: Date \| (() => Date))` | Checks if the value is a date that's after the specified date. | +| `@MaxDate(date: Date \| (() => Date))` | Checks if the value is a date that's before the specified date. | +| **String-type validation decorators** | | +| `@IsBooleanString()` | Checks if a string is a boolean (e.g. is "true" or "false" or "1", "0"). | +| `@IsDateString()` | Alias for `@IsISO8601()`. | +| `@IsNumberString(options?: IsNumericOptions)` | Checks if a string is a number. | +| **String validation decorators** | | +| `@Contains(seed: string)` | Checks if the string contains the seed. | +| `@NotContains(seed: string)` | Checks if the string not contains the seed. | +| `@IsAlpha()` | Checks if the string contains only letters (a-zA-Z). | +| `@IsAlphanumeric()` | Checks if the string contains only letters and numbers. | +| `@IsDecimal(options?: IsDecimalOptions)` | Checks if the string is a valid decimal value. Default IsDecimalOptions are `force_decimal=False`, `decimal_digits: '1,'`, `locale: 'en-US'` | +| `@IsAscii()` | Checks if the string contains ASCII chars only. | +| `@IsBase32()` | Checks if a string is base32 encoded. | +| `@IsBase58()` | Checks if a string is base58 encoded. | +| `@IsBase64(options?: IsBase64Options)` | Checks if a string is base64 encoded. | +| `@IsIBAN()` | Checks if a string is a IBAN (International Bank Account Number). | +| `@IsBIC()` | Checks if a string is a BIC (Bank Identification Code) or SWIFT code. | +| `@IsByteLength(min: number, max?: number)` | Checks if the string's length (in bytes) falls in a range. | +| `@IsCreditCard()` | Checks if the string is a credit card. | +| `@IsCurrency(options?: IsCurrencyOptions)` | Checks if the string is a valid currency amount. | +| `@IsISO4217CurrencyCode()` | Checks if the string is an ISO 4217 currency code. | +| `@IsEthereumAddress()` | Checks if the string is an Ethereum address using basic regex. Does not validate address checksums. | +| `@IsBtcAddress()` | Checks if the string is a valid BTC address. | +| `@IsDataURI()` | Checks if the string is a data uri format. | +| `@IsEmail(options?: IsEmailOptions)` | Checks if the string is an email. | +| `@IsFQDN(options?: IsFQDNOptions)` | Checks if the string is a fully qualified domain name (e.g. domain.com). | +| `@IsFullWidth()` | Checks if the string contains any full-width chars. | +| `@IsHalfWidth()` | Checks if the string contains any half-width chars. | +| `@IsVariableWidth()` | Checks if the string contains a mixture of full and half-width chars. | +| `@IsHexColor()` | Checks if the string is a hexadecimal color. | +| `@IsHSL()` | Checks if the string is an HSL color based on[CSS Colors Level 4 specification](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). | +| `@IsRgbColor(options?: IsRgbOptions)` | Checks if the string is a rgb or rgba color. | +| `@IsIdentityCard(locale?: string)` | Checks if the string is a valid identity card code. | +| `@IsPassportNumber(countryCode?: string)` | Checks if the string is a valid passport number relative to a specific country code. | +| `@IsPostalCode(locale?: string)` | Checks if the string is a postal code. | +| `@IsHexadecimal()` | Checks if the string is a hexadecimal number. | +| `@IsOctal()` | Checks if the string is a octal number. | +| `@IsMACAddress(options?: IsMACAddressOptions)` | Checks if the string is a MAC Address. | +| `@IsIP(version?: "4"\|"6")` | Checks if the string is an IP (version 4 or 6). | +| `@IsPort()` | Checks if the string is a valid port number. | +| `@IsISBN(version?: "10"\|"13")` | Checks if the string is an ISBN (version 10 or 13). | +| `@IsEAN()` | Checks if the string is an if the string is an EAN (European Article Number). | +| `@IsISIN()` | Checks if the string is an ISIN (stock/security identifier). | +| `@IsISO8601(options?: IsISO8601Options)` | Checks if the string is a valid ISO 8601 date format. Use the option strict = true for additional checks for a valid date. | +| `@IsJSON()` | Checks if the string is valid JSON. | +| `@IsJWT()` | Checks if the string is valid JWT. | +| `@IsObject()` | Checks if the object is valid Object (null, functions, arrays will return false). | +| `@IsNotEmptyObject()` | Checks if the object is not empty. | +| `@IsLowercase()` | Checks if the string is lowercase. | +| `@IsLatLong()` | Checks if the string is a valid latitude-longitude coordinate in the format lat, long. | +| `@IsLatitude()` | Checks if the string or number is a valid latitude coordinate. | +| `@IsLongitude()` | Checks if the string or number is a valid longitude coordinate. | +| `@IsMobilePhone(locale: string)` | Checks if the string is a mobile phone number. | +| `@IsISO31661Alpha2()` | Checks if the string is a valid ISO 3166-1 alpha-2 officially assigned country code. | +| `@IsISO31661Alpha3()` | Checks if the string is a valid ISO 3166-1 alpha-3 officially assigned country code. | +| `@IsLocale()` | Checks if the string is a locale. | +| `@IsPhoneNumber(region: string)` | Checks if the string is a valid phone number using libphonenumber-js. | +| `@IsMongoId()` | Checks if the string is a valid hex-encoded representation of a MongoDB ObjectId. | +| `@IsMultibyte()` | Checks if the string contains one or more multibyte chars. | +| `@IsNumberString(options?: IsNumericOptions)` | Checks if the string is numeric. | +| `@IsSurrogatePair()` | Checks if the string contains any surrogate pairs chars. | +| `@IsTaxId()` | Checks if the string is a valid tax ID. Default locale is `en-US`. | +| `@IsUrl(options?: IsURLOptions)` | Checks if the string is a URL. | +| `@IsMagnetURI()` | Checks if the string is a[magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). | +| `@IsUUID(version?: UUIDVersion)` | Checks if the string is a UUID (version 3, 4, 5 or all ). | +| `@IsFirebasePushId()` | Checks if the string is a[Firebase Push ID](https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html) | +| `@IsUppercase()` | Checks if the string is uppercase. | +| `@Length(min: number, max?: number)` | Checks if the string's length falls in a range. | +| `@MinLength(min: number)` | Checks if the string's length is not less than given number. | +| `@MaxLength(max: number)` | Checks if the string's length is not more than given number. | +| `@Matches(pattern: RegExp, modifiers?: string)` | Checks if string matches the pattern. Either matches('foo', /foo/i) or matches('foo', 'foo', 'i'). | +| `@IsMilitaryTime()` | Checks if the string is a valid representation of military time in the format HH:MM. | +| `@IsTimeZone()` | Checks if the string represents a valid IANA time-zone. | | `@IsHash(algorithm: string)` | Checks if the string is a hash The following types are supported:`md4`, `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `ripemd128`, `ripemd160`, `tiger128`, `tiger160`, `tiger192`, `crc32`, `crc32b`. | -| `@IsMimeType()` | Checks if the string matches to a valid [MIME type](https://en.wikipedia.org/wiki/Media_type) format | -| `@IsSemVer()` | Checks if the string is a Semantic Versioning Specification (SemVer). | -| `@IsISSN(options?: IsISSNOptions)` | Checks if the string is a ISSN. | -| `@IsISRC()` | Checks if the string is a [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code). | -| `@IsRFC3339()` | Checks if the string is a valid [RFC 3339](https://tools.ietf.org/html/rfc3339) date. | -| `@IsStrongPassword(options?: IsStrongPasswordOptions)` | Checks if the string is a strong password. | -| **Array validation decorators** | | -| `@ArrayContains(values: any[])` | Checks if array contains all values from the given array of values. | -| `@ArrayNotContains(values: any[])` | Checks if array does not contain any of the given values. | -| `@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. | -| `@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. | -| **Other decorators** | | -| `@Allow()` | Prevent stripping off the property when no other constraint is specified for it. | +| `@IsMimeType()` | Checks if the string matches to a valid[MIME type](https://en.wikipedia.org/wiki/Media_type) format | +| `@IsSemVer()` | Checks if the string is a Semantic Versioning Specification (SemVer). | +| `@IsISSN(options?: IsISSNOptions)` | Checks if the string is a ISSN. | +| `@IsISRC()` | Checks if the string is a[ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code). | +| `@IsRFC3339()` | Checks if the string is a valid[RFC 3339](https://tools.ietf.org/html/rfc3339) date. | +| `@IsStrongPassword(options?: IsStrongPasswordOptions)` | Checks if the string is a strong password. | +| **Array validation decorators** | | +| `@ArrayContains(values: any[])` | Checks if array contains all values from the given array of values. | +| `@ArrayNotContains(values: any[])` | Checks if array does not contain any of the given values. | +| `@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. | +| `@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. | +| **Other decorators** | | +| `@Allow()` | Prevent stripping off the property when no other constraint is specified for it. | ## Defining validation schema without decorators -Schema-based validation without decorators is no longer supported by `class-validator`. This feature was broken in version 0.12 and it will not be fixed. If you are interested in schema-based validation, you can find several such frameworks in [the zod readme's comparison section](https://github.com/colinhacks/zod#comparison). +Schema-based validation without decorators is no longer supported by `class-validator`. This feature was broken in version 0.12 and it will not be fixed. If you are interested in schema-based validation, you can find several such frameworks in [the zod readme's comparison section](https://github.com/colinhacks/zod#comparison). ## Validating plain objects @@ -939,10 +936,10 @@ There are several extensions that simplify class-validator integration with othe See information about breaking changes and release notes [here][3]. +## Contributing + +For information about how to contribute to this project, see [TypeStack's general contribution guide](https://github.com/typestack/.github/blob/master/CONTRIBUTING.md). + [1]: https://github.com/chriso/validator.js [2]: https://github.com/pleerock/typedi [3]: CHANGELOG.md - -## Contributing - -For information about how to contribute to this project, see [TypeStack's general contribution guide](https://github.com/typestack/.github/blob/master/CONTRIBUTING.md). diff --git a/src/decorator/decorators.ts b/src/decorator/decorators.ts index d449e9301a..3f0c7f6f8f 100644 --- a/src/decorator/decorators.ts +++ b/src/decorator/decorators.ts @@ -33,6 +33,7 @@ export * from './number/IsPositive'; export * from './number/IsNegative'; export * from './number/Max'; export * from './number/Min'; +export * from './number/IsSafeInt'; // ------------------------------------------------------------------------- // Date checkers diff --git a/src/decorator/number/IsSafeInt.ts b/src/decorator/number/IsSafeInt.ts new file mode 100644 index 0000000000..c9c05ab378 --- /dev/null +++ b/src/decorator/number/IsSafeInt.ts @@ -0,0 +1,30 @@ +import { ValidationOptions } from '../ValidationOptions'; +import { buildMessage, ValidateBy } from '../common/ValidateBy'; + +export const IS_Safe_INT = 'isSafeInt'; + +/** + * Checks if value is an safe integer. + */ +export function isSafeInt(val: unknown): val is Number { + return typeof val === 'number' && Number.isSafeInteger(val); +} + +/** + * Checks if value is an safe integer. + */ +export function IsSafeInt(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_Safe_INT, + validator: { + validate: (value, args): boolean => isSafeInt(value), + defaultMessage: buildMessage( + eachPrefix => eachPrefix + '$property must be an safe integer number', + validationOptions + ), + }, + }, + validationOptions + ); +} diff --git a/test/functional/validation-functions-and-decorators.spec.ts b/test/functional/validation-functions-and-decorators.spec.ts index 5144a0db48..f3b628e380 100644 --- a/test/functional/validation-functions-and-decorators.spec.ts +++ b/test/functional/validation-functions-and-decorators.spec.ts @@ -193,6 +193,7 @@ import { isTaxId, IsTaxId, IsISO4217CurrencyCode, + IsSafeInt, } from '../../src/decorator/decorators'; import { Validator } from '../../src/validation/Validator'; import { ValidatorOptions } from '../../src/validation/ValidatorOptions'; @@ -4779,3 +4780,38 @@ describe('IsISO4217', () => { return checkInvalidValues(new MyClass(), invalidValues); }); }); + +describe('IsSafeInt', () => { + const stringValues = ['01', '-01', '000', '100e10', '123.123', ' ', '']; + const decimalValues = [2.5, -0.1]; + const bigIntValues = [BigInt(2), BigInt(4), BigInt(100), BigInt(1000), BigInt(0), BigInt(-0)]; + const invalidValues = [Number.MAX_SAFE_INTEGER + 1, Number.MIN_SAFE_INTEGER - 1, ...stringValues, ...decimalValues, ...bigIntValues]; + const validValues = [2, 4, 100, 1000, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, 0, -0]; + + class MyClass { + @IsSafeInt() + someProperty: number; + } + + 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(isInt(value)).toBeTruthy()); + }); + + it('should fail if method in validator said that its invalid', () => { + invalidValues.forEach(value => expect(isInt(value as any)).toBeFalsy()); + }); + + it('should return error object with proper data', () => { + const validationType = 'isSafeInt'; + const message = 'someProperty must be an safe integer number'; + return checkReturnedError(new MyClass(), invalidValues, validationType, message); + }); +}); \ No newline at end of file