diff --git a/README.md b/README.md index 3eb5258c0..1594e4875 100644 --- a/README.md +++ b/README.md @@ -837,21 +837,34 @@ isBoolean(value); | `@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. | | `@IsBase64()` | 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. | +| `@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. | +| `@IsHSLColor()` | Checks if the string is an HSL (hue, saturation, lightness, optional alpha) 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()` | Check 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. Use the option strict = true for additional checks for a valid date, e.g. invalidates dates like 2019-02-29. | | `@IsJSON()` | Checks if the string is valid JSON. | @@ -865,12 +878,14 @@ isBoolean(value); | `@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](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) officially assigned country code. | | `@IsISO31661Alpha3()` | Checks if the string is a valid [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/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. "region" accepts 2 characters uppercase country code (e.g. DE, US, CH).If users must enter the intl. prefix (e.g. +41), then you may pass "ZZ" or null as region. See [google-libphonenumber, metadata.js:countryCodeToRegionCodeMap on github](https://github.com/ruimarinho/google-libphonenumber/blob/1e46138878cff479aafe2ce62175c6c49cb58720/src/metadata.js#L33) | | `@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. | | `@IsUrl(options?: IsURLOptions)` | Checks if the string is an url. | +| `@IsMagnetURI()` | Checks if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). | | `@IsUUID(version?: "3"\|"4"\|"5"\|"all")` | 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. | @@ -880,7 +895,11 @@ isBoolean(value); | `@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. | | `@IsHash(algorithm: string)` | Checks if the string is a hash of type algorithm.

Algorithm is one of `['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 f the string is a valid [RFC 3339](https://tools.ietf.org/html/rfc3339) date. | | **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. | diff --git a/package-lock.json b/package-lock.json index ae4e938b2..63596f493 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "class-validator", - "version": "0.12.0-refactor.3", + "version": "0.12.0-refactor.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -396,9 +396,9 @@ "dev": true }, "@types/validator": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-12.0.1.tgz", - "integrity": "sha512-l57fIANZLMe8DArz+SDb+7ATXnDm15P7u2wHBw5mb0aSMd+UuvmvhouBF2hdLgQPDMJ39sh9g2MJO4GkZ0VAdQ==" + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.0.0.tgz", + "integrity": "sha512-WAy5txG7aFX8Vw3sloEKp5p/t/Xt8jD3GRD9DacnFv6Vo8ubudAsRTXgxpQwU0mpzY/H8U4db3roDuCMjShBmw==" }, "@types/vinyl": { "version": "2.0.2", @@ -8849,9 +8849,9 @@ } }, "validator": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz", - "integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ==" + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.0.0.tgz", + "integrity": "sha512-anYx5fURbgF04lQV18nEQWZ/3wHGnxiKdG4aL8J+jEDsm98n/sU/bey+tYk6tnGJzm7ioh5FoqrAiQ6m03IgaA==" }, "value-or-function": { "version": "3.0.0", diff --git a/package.json b/package.json index 34bd51741..9d7fb2bf0 100644 --- a/package.json +++ b/package.json @@ -31,9 +31,9 @@ "tslib": ">=1.9.0" }, "dependencies": { - "@types/validator": "12.0.1", + "@types/validator": "13.0.0", "google-libphonenumber": "^3.2.8", - "validator": "12.2.0" + "validator": "13.0.0" }, "devDependencies": { "@types/chai": "^4.2.0", diff --git a/src/decorator/decorators.ts b/src/decorator/decorators.ts index bdff4a8ca..9a02464cd 100644 --- a/src/decorator/decorators.ts +++ b/src/decorator/decorators.ts @@ -92,6 +92,25 @@ export * from "./string/IsISSN"; export * from "./string/IsDateString"; export * from "./string/IsBooleanString"; export * from "./string/IsNumberString"; +export * from "./string/IsBase32"; +export * from "./string/IsBIC"; +export * from "./string/IsBtcAddress"; +export * from "./string/IsDataURI"; +export * from "./string/IsEAN"; +export * from "./string/IsEthereumAddress"; +export * from "./string/IsHSL"; +export * from "./string/IsIBAN"; +export * from "./string/IsIdentityCard"; +export * from "./string/IsISRC"; +export * from "./string/IsLocale"; +export * from "./string/IsMagnetURI"; +export * from "./string/IsMimeType"; +export * from "./string/IsOctal"; +export * from "./string/IsPassportNumber"; +export * from "./string/IsPostalCode"; +export * from "./string/IsRFC3339"; +export * from "./string/IsRgbColor"; +export * from "./string/IsSemVer"; // ------------------------------------------------------------------------- // Type checkers diff --git a/src/decorator/string/IsBIC.ts b/src/decorator/string/IsBIC.ts new file mode 100644 index 000000000..0b05bb54a --- /dev/null +++ b/src/decorator/string/IsBIC.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_BIC = "isBIC"; + +/** + * Check if a string is a BIC (Bank Identification Code) or SWIFT code. + * If given value is not a string, then it returns false. + */ +export function isBIC(value: unknown): boolean { + return typeof value === "string" && validator.isBIC(value); +} + +/** + * Check if a string is a BIC (Bank Identification Code) or SWIFT code. + * If given value is not a string, then it returns false. + */ +export function IsBIC(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_BIC, + validator: { + validate: (value, args) => isBIC(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be a BIC or SWIFT code", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsBase32.ts b/src/decorator/string/IsBase32.ts new file mode 100644 index 000000000..fb46d3015 --- /dev/null +++ b/src/decorator/string/IsBase32.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_BASE32 = "isBase32"; + +/** + * Checks if a string is base32 encoded. + * If given value is not a string, then it returns false. + */ +export function isBase32(value: unknown): boolean { + return typeof value === "string" && validator.isBase32(value); +} + +/** + * Check if a string is base32 encoded. + * If given value is not a string, then it returns false. + */ +export function IsBase32(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_BASE32, + validator: { + validate: (value, args) => isBase32(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be base32 encoded", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsBtcAddress.ts b/src/decorator/string/IsBtcAddress.ts new file mode 100644 index 000000000..d886bb6d8 --- /dev/null +++ b/src/decorator/string/IsBtcAddress.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_BTC_ADDRESS = "isBtcAddress"; + +/** + * Check if the string is a valid BTC address. + * If given value is not a string, then it returns false. + */ +export function isBtcAddress(value: unknown): boolean { + return typeof value === "string" && validator.isBtcAddress(value); +} + +/** + * Check if the string is a valid BTC address. + * If given value is not a string, then it returns false. + */ +export function IsBtcAddress(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_BTC_ADDRESS, + validator: { + validate: (value, args) => isBtcAddress(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be a BTC address", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsDataURI.ts b/src/decorator/string/IsDataURI.ts new file mode 100644 index 000000000..6ac0b879e --- /dev/null +++ b/src/decorator/string/IsDataURI.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_DATA_URI = "isDataURI"; + +/** + * Check if the string is a data uri format. + * If given value is not a string, then it returns false. + */ +export function isDataURI(value: unknown): boolean { + return typeof value === "string" && validator.isDataURI(value); +} + +/** + * Check if the string is a data uri format. + * If given value is not a string, then it returns false. + */ +export function IsDataURI(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_DATA_URI, + validator: { + validate: (value, args) => isDataURI(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be a data uri format", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsEAN.ts b/src/decorator/string/IsEAN.ts new file mode 100644 index 000000000..d73d22610 --- /dev/null +++ b/src/decorator/string/IsEAN.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_EAN = "isEAN"; + +/** + * Check if the string is an EAN (European Article Number). + * If given value is not a string, then it returns false. + */ +export function isEAN(value: unknown): boolean { + return typeof value === "string" && validator.isEAN(value); +} + +/** + * Check if the string is an EAN (European Article Number). + * If given value is not a string, then it returns false. + */ +export function IsEAN(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_EAN, + validator: { + validate: (value, args) => isEAN(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be an EAN (European Article Number)", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsEthereumAddress.ts b/src/decorator/string/IsEthereumAddress.ts new file mode 100644 index 000000000..e0f06ff7b --- /dev/null +++ b/src/decorator/string/IsEthereumAddress.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_ETHEREUM_ADDRESS = "isEthereumAddress"; + +/** + * Check if the string is an Ethereum address using basic regex. Does not validate address checksums. + * If given value is not a string, then it returns false. + */ +export function isEthereumAddress(value: unknown): boolean { + return typeof value === "string" && validator.isEthereumAddress(value); +} + +/** + * Check if the string is an Ethereum address using basic regex. Does not validate address checksums. + * If given value is not a string, then it returns false. + */ +export function IsEthereumAddress(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_ETHEREUM_ADDRESS, + validator: { + validate: (value, args) => isEthereumAddress(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be an Ethereum address", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsHSL.ts b/src/decorator/string/IsHSL.ts new file mode 100644 index 000000000..842a51af2 --- /dev/null +++ b/src/decorator/string/IsHSL.ts @@ -0,0 +1,35 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_HSL = "isHSL"; + +/** +* Check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on CSS Colors Level 4 specification. + * Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: hsl(200grad+.1%62%/1)). + * If given value is not a string, then it returns false. + */ +export function isHSL(value: unknown): boolean { + return typeof value === "string" && validator.isHSL(value); +} + +/** + * Check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on CSS Colors Level 4 specification. + * Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: hsl(200grad+.1%62%/1)). + * If given value is not a string, then it returns false. + */ +export function IsHSL(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_HSL, + validator: { + validate: (value, args) => isHSL(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be a HSL color", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsHash.ts b/src/decorator/string/IsHash.ts index 2a4cac401..cf647bd4c 100644 --- a/src/decorator/string/IsHash.ts +++ b/src/decorator/string/IsHash.ts @@ -5,7 +5,7 @@ import ValidatorJS from "validator"; export const IS_HASH = "isHash"; /** - * check if the string is a hash of type algorithm. + * Check if the string is a hash of type algorithm. * Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', * 'tiger160', 'tiger192', 'crc32', 'crc32b'] */ @@ -14,7 +14,7 @@ export function isHash(value: unknown, algorithm: ValidatorJS.HashAlgorithm): bo } /** - * check if the string is a hash of type algorithm. + * Check if the string is a hash of type algorithm. * Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', * 'tiger160', 'tiger192', 'crc32', 'crc32b'] */ diff --git a/src/decorator/string/IsIBAN.ts b/src/decorator/string/IsIBAN.ts new file mode 100644 index 000000000..511514b40 --- /dev/null +++ b/src/decorator/string/IsIBAN.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_IBAN = "isIBAN"; + +/** + * Check if a string is a IBAN (International Bank Account Number). + * If given value is not a string, then it returns false. + */ +export function isIBAN(value: unknown): boolean { + return typeof value === "string" && validator.isIBAN(value); +} + +/** + * Check if a string is a IBAN (International Bank Account Number). + * If given value is not a string, then it returns false. + */ +export function IsIBAN(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_IBAN, + validator: { + validate: (value, args) => isIBAN(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be an IBAN", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsISRC.ts b/src/decorator/string/IsISRC.ts new file mode 100644 index 000000000..ed6e9a73c --- /dev/null +++ b/src/decorator/string/IsISRC.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_ISRC = "isISRC"; + +/** + * Check if the string is a ISRC. + * If given value is not a string, then it returns false. + */ +export function isISRC(value: unknown): boolean { + return typeof value === "string" && validator.isISRC(value); +} + +/** + * Check if the string is a ISRC. + * If given value is not a string, then it returns false. + */ +export function IsISRC(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_ISRC, + validator: { + validate: (value, args) => isISRC(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be an ISRC", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsIdentityCard.ts b/src/decorator/string/IsIdentityCard.ts new file mode 100644 index 000000000..6da4f8d5f --- /dev/null +++ b/src/decorator/string/IsIdentityCard.ts @@ -0,0 +1,38 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import ValidatorJS from "validator"; + +export const IS_IDENTITY_CARD = "isIdentityCard"; + +/** + * Check if the string is a valid identity card code. + * locale is one of ['ES', 'zh-TW', 'he-IL', 'ar-TN'] OR 'any'. If 'any' is used, function will check if any of the locals match. + * Defaults to 'any'. + * If given value is not a string, then it returns false. + */ +export function isIdentityCard(value: unknown, locale: ValidatorJS.IdentityCardLocale): boolean { + return typeof value === "string" && ValidatorJS.isIdentityCard(value, locale); +} + +/** + * Check if the string is a valid identity card code. + * locale is one of ['ES', 'zh-TW', 'he-IL', 'ar-TN'] OR 'any'. If 'any' is used, function will check if any of the locals match. + * Defaults to 'any'. + * If given value is not a string, then it returns false. + */ +export function IsIdentityCard(locale?: ValidatorJS.IdentityCardLocale, validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_IDENTITY_CARD, + constraints: [locale], + validator: { + validate: (value, args) => isIdentityCard(value, args.constraints[0]), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be a identity card number", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsLocale.ts b/src/decorator/string/IsLocale.ts new file mode 100644 index 000000000..3cd3a93b5 --- /dev/null +++ b/src/decorator/string/IsLocale.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_LOCALE = "isLocale"; + +/** + * Check if the string is a locale. + * If given value is not a string, then it returns false. + */ +export function isLocale(value: unknown): boolean { + return typeof value === "string" && validator.isLocale(value); +} + +/** + * Check if the string is a locale. + * If given value is not a string, then it returns false. + */ +export function IsLocale(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_LOCALE, + validator: { + validate: (value, args) => isLocale(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be locale", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsMagnetURI.ts b/src/decorator/string/IsMagnetURI.ts new file mode 100644 index 000000000..8c2595c83 --- /dev/null +++ b/src/decorator/string/IsMagnetURI.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_MAGNET_URI = "isMagnetURI"; + +/** + * Check if the string is a magnet uri format. + * If given value is not a string, then it returns false. + */ +export function isMagnetURI(value: unknown): boolean { + return typeof value === "string" && validator.isMagnetURI(value); +} + +/** + * Check if the string is a magnet uri format. + * If given value is not a string, then it returns false. + */ +export function IsMagnetURI(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_MAGNET_URI, + validator: { + validate: (value, args) => isMagnetURI(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be magnet uri format", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsMimeType.ts b/src/decorator/string/IsMimeType.ts new file mode 100644 index 000000000..9ae2b5145 --- /dev/null +++ b/src/decorator/string/IsMimeType.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_MIME_TYPE = "isMimeType"; + +/** + * Check if the string matches to a valid MIME type format + * If given value is not a string, then it returns false. + */ +export function isMimeType(value: unknown): boolean { + return typeof value === "string" && validator.isMimeType(value); +} + +/** + * Check if the string matches to a valid MIME type format + * If given value is not a string, then it returns false. + */ +export function IsMimeType(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_MIME_TYPE, + validator: { + validate: (value, args) => isMimeType(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be MIME type format", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsMobilePhone.ts b/src/decorator/string/IsMobilePhone.ts index 61494d8cf..1fa3cebc6 100644 --- a/src/decorator/string/IsMobilePhone.ts +++ b/src/decorator/string/IsMobilePhone.ts @@ -1,30 +1,44 @@ import { ValidationOptions } from "../ValidationOptions"; import { buildMessage, ValidateBy } from "../common/ValidateBy"; -import ValidatorJS from "validator"; +import validator from "validator"; export const IS_MOBILE_PHONE = "isMobilePhone"; /** - * Checks if the string is a mobile phone number (locale is one of ['zh-CN', 'zh-TW', 'en-ZA', 'en-AU', 'en-HK', - * 'pt-PT', 'fr-FR', 'el-GR', 'en-GB', 'en-US', 'en-ZM', 'ru-RU', 'nb-NO', 'nn-NO', 'vi-VN', 'en-NZ']). + * Checks if the string is a mobile phone number (locale is either an array of locales (e.g ['sk-SK', 'sr-RS']) + * OR one of ['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-SA', 'ar-SY', 'ar-TN', 'be-BY', + * 'bg-BG', 'bn-BD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'el-GR', 'en-AU', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-HK', + * 'en-MO', 'en-IE', 'en-IN', 'en-KE', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-UG', + * 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'es-CL', 'es-CR', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-UY', 'et-EE', + * 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-RE', 'he-IL', 'hu-HU', 'id-ID', + * 'it-IT', 'ja-JP', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', 'nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', + * 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'vi-VN', 'zh-CN', + * 'zh-HK', 'zh-MO', 'zh-TW'] * If given value is not a string, then it returns false. */ -export function isMobilePhone(value: unknown, locale: ValidatorJS.MobilePhoneLocale): boolean { - return typeof value === "string" && ValidatorJS.isMobilePhone(value, locale); +export function isMobilePhone(value: unknown, locale?: validator.MobilePhoneLocale, options?: validator.IsMobilePhoneOptions): boolean { + return typeof value === "string" && validator.isMobilePhone(value, locale, options); } /** - * Checks if the string is a mobile phone number (locale is one of ['zh-CN', 'zh-TW', 'en-ZA', 'en-AU', 'en-HK', - * 'pt-PT', 'fr-FR', 'el-GR', 'en-GB', 'en-US', 'en-ZM', 'ru-RU', 'nb-NO', 'nn-NO', 'vi-VN', 'en-NZ']). + * Checks if the string is a mobile phone number (locale is either an array of locales (e.g ['sk-SK', 'sr-RS']) + * OR one of ['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-SA', 'ar-SY', 'ar-TN', 'be-BY', + * 'bg-BG', 'bn-BD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'el-GR', 'en-AU', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-HK', + * 'en-MO', 'en-IE', 'en-IN', 'en-KE', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-UG', + * 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'es-CL', 'es-CR', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-UY', 'et-EE', + * 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-RE', 'he-IL', 'hu-HU', 'id-ID', + * 'it-IT', 'ja-JP', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', 'nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', + * 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'vi-VN', 'zh-CN', + * 'zh-HK', 'zh-MO', 'zh-TW'] * If given value is not a string, then it returns false. */ -export function IsMobilePhone(locale?: ValidatorJS.MobilePhoneLocale, validationOptions?: ValidationOptions): PropertyDecorator { +export function IsMobilePhone(locale?: validator.MobilePhoneLocale, options?: validator.IsMobilePhoneOptions, validationOptions?: ValidationOptions): PropertyDecorator { return ValidateBy( { name: IS_MOBILE_PHONE, - constraints: [locale], + constraints: [locale, options], validator: { - validate: (value, args) => isMobilePhone(value, args.constraints[0]), + validate: (value, args) => isMobilePhone(value, args.constraints[0], args.constraints[1]), defaultMessage: buildMessage( (eachPrefix) => eachPrefix + "$property must be a phone number", validationOptions diff --git a/src/decorator/string/IsOctal.ts b/src/decorator/string/IsOctal.ts new file mode 100644 index 000000000..83b9fd0e8 --- /dev/null +++ b/src/decorator/string/IsOctal.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_OCTAL = "isOctal"; + +/** + * Check if the string is a valid octal number. + * If given value is not a string, then it returns false. + */ +export function isOctal(value: unknown): boolean { + return typeof value === "string" && validator.isOctal(value); +} + +/** + * Check if the string is a valid octal number. + * If given value is not a string, then it returns false. + */ +export function IsOctal(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_OCTAL, + validator: { + validate: (value, args) => isOctal(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be valid octal number", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsPassportNumber.ts b/src/decorator/string/IsPassportNumber.ts new file mode 100644 index 000000000..4f6f1f535 --- /dev/null +++ b/src/decorator/string/IsPassportNumber.ts @@ -0,0 +1,34 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_PASSPORT_NUMBER = "isPassportNumber"; + +/** + * Check if the string is a valid passport number relative to a specific country code. + * If given value is not a string, then it returns false. + */ +export function isPassportNumber(value: unknown, countryCode: string): boolean { + return typeof value === "string" && validator.isPassportNumber(value, countryCode); +} + +/** + * Check if the string is a valid passport number relative to a specific country code. + * If given value is not a string, then it returns false. + */ +export function IsPassportNumber(countryCode: string, validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_PASSPORT_NUMBER, + constraints: [countryCode], + validator: { + validate: (value, args) => isPassportNumber(value, args.constraints[0]), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be valid passport number", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsPostalCode.ts b/src/decorator/string/IsPostalCode.ts new file mode 100644 index 000000000..c7e2c6740 --- /dev/null +++ b/src/decorator/string/IsPostalCode.ts @@ -0,0 +1,36 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_POSTAL_CODE = "isPostalCode"; + +/** + * Check if the string is a postal code, + * (locale is one of [ 'AD', 'AT', 'AU', 'BE', 'BG', 'BR', 'CA', 'CH', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'ID', 'IE' 'IL', 'IN', 'IR', 'IS', 'IT', 'JP', 'KE', 'LI', 'LT', 'LU', 'LV', 'MT', 'MX', 'NL', 'NO', 'NZ', 'PL', 'PR', 'PT', 'RO', 'RU', 'SA', 'SE', 'SI', 'TN', 'TW', 'UA', 'US', 'ZA', 'ZM' ] OR 'any'. If 'any' is used, function will check if any of the locals match. Locale list is validator.isPostalCodeLocales.). + * If given value is not a string, then it returns false. + */ +export function isPostalCode(value: unknown, locale: validator.PostalCodeLocale): boolean { + return typeof value === "string" && validator.isPostalCode(value, locale); +} + +/** + * Check if the string is a postal code, + * (locale is one of [ 'AD', 'AT', 'AU', 'BE', 'BG', 'BR', 'CA', 'CH', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'ID', 'IE' 'IL', 'IN', 'IR', 'IS', 'IT', 'JP', 'KE', 'LI', 'LT', 'LU', 'LV', 'MT', 'MX', 'NL', 'NO', 'NZ', 'PL', 'PR', 'PT', 'RO', 'RU', 'SA', 'SE', 'SI', 'TN', 'TW', 'UA', 'US', 'ZA', 'ZM' ] OR 'any'. If 'any' is used, function will check if any of the locals match. Locale list is validator.isPostalCodeLocales.). + * If given value is not a string, then it returns false. + */ +export function IsPostalCode(locale?: validator.PostalCodeLocale, validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_POSTAL_CODE, + constraints: [locale], + validator: { + validate: (value, args) => isPostalCode(value, args.constraints[0]), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be a postal code", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsRFC3339.ts b/src/decorator/string/IsRFC3339.ts new file mode 100644 index 000000000..792de222f --- /dev/null +++ b/src/decorator/string/IsRFC3339.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_RFC_3339 = "isRFC3339"; + +/** + * Check if the string is a valid RFC 3339 date. + * If given value is not a string, then it returns false. + */ +export function isRFC3339(value: unknown): boolean { + return typeof value === "string" && validator.isRFC3339(value); +} + +/** + * Check if the string is a valid RFC 3339 date. + * If given value is not a string, then it returns false. + */ +export function IsRFC3339(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_RFC_3339, + validator: { + validate: (value, args) => isRFC3339(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be RFC 3339 date", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsRgbColor.ts b/src/decorator/string/IsRgbColor.ts new file mode 100644 index 000000000..85bdbfd87 --- /dev/null +++ b/src/decorator/string/IsRgbColor.ts @@ -0,0 +1,36 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_RGB_COLOR = "isRgbColor"; + +/** +* Check if the string is a rgb or rgba color. + * `includePercentValues` defaults to true. If you don't want to allow to set rgb or rgba values with percents, like rgb(5%,5%,5%), or rgba(90%,90%,90%,.3), then set it to false. + * If given value is not a string, then it returns false. + */ +export function isRgbColor(value: unknown, includePercentValues?: boolean): boolean { + return typeof value === "string" && validator.isRgbColor(value, includePercentValues); +} + +/** + * Check if the string is a rgb or rgba color. + * `includePercentValues` defaults to true. If you don't want to allow to set rgb or rgba values with percents, like rgb(5%,5%,5%), or rgba(90%,90%,90%,.3), then set it to false. + * If given value is not a string, then it returns false. + */ +export function IsRgbColor(includePercentValues?: boolean, validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_RGB_COLOR, + constraints: [includePercentValues], + validator: { + validate: (value, args) => isRgbColor(value, args.constraints[0]), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be RGB color", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/src/decorator/string/IsSemVer.ts b/src/decorator/string/IsSemVer.ts new file mode 100644 index 000000000..2205baebf --- /dev/null +++ b/src/decorator/string/IsSemVer.ts @@ -0,0 +1,33 @@ +import { ValidationOptions } from "../ValidationOptions"; +import { buildMessage, ValidateBy } from "../common/ValidateBy"; +import validator from "validator"; + +export const IS_SEM_VER = "isSemVer"; + +/** + * Check if the string is a Semantic Versioning Specification (SemVer). + * If given value is not a string, then it returns false. + */ +export function isSemVer(value: unknown): boolean { + return typeof value === "string" && validator.isSemVer(value); +} + +/** + * Check if the string is a Semantic Versioning Specification (SemVer). + * If given value is not a string, then it returns false. + */ +export function IsSemVer(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_SEM_VER, + validator: { + validate: (value, args) => isSemVer(value), + defaultMessage: buildMessage( + (eachPrefix) => eachPrefix + "$property must be a Semantic Versioning Specification", + validationOptions + ) + } + }, + validationOptions + ); +} diff --git a/test/functional/validation-functions-and-decorators.spec.ts b/test/functional/validation-functions-and-decorators.spec.ts index a97159212..adf371ec5 100644 --- a/test/functional/validation-functions-and-decorators.spec.ts +++ b/test/functional/validation-functions-and-decorators.spec.ts @@ -147,7 +147,45 @@ import { arrayNotEmpty, minDate, maxDate, - isDate + isDate, + IsEAN, + isEAN, + IsEthereumAddress, + isEthereumAddress, + IsBtcAddress, + isBtcAddress, + IsDataURI, + isDataURI, + IsHSL, + isHSL, + IsRgbColor, + isRgbColor, + isIdentityCard, + IsIdentityCard, + IsBase32, + isBase32, + IsIBAN, + isIBAN, + IsBIC, + isBIC, + IsISRC, + isISRC, + IsRFC3339, + isRFC3339, + IsLocale, + isLocale, + IsMagnetURI, + isMagnetURI, + IsMimeType, + isMimeType, + isOctal, + IsOctal, + IsPassportNumber, + isPassportNumber, + IsPostalCode, + isPostalCode, + IsSemVer, + isSemVer } from "../../src/decorator/decorators"; import {Validator} from "../../src/validation/Validator"; import {ValidatorOptions} from "../../src/validation/ValidatorOptions"; @@ -1603,6 +1641,62 @@ describe("IsDecimal", function() { }); }); + +describe("IsBase32", function() { + + const constraint = ""; + const validValues = [ + "ZG======", + "JBSQ====", + "JBSWY===", + "JBSWY3A=", + "JBSWY3DP", + "JBSWY3DPEA======", + "K5SWYY3PNVSSA5DPEBXG6ZA=", + "K5SWYY3PNVSSA5DPEBXG6===", + ]; + const invalidValues = [ + null, + undefined, + "12345", + "", + "JBSWY3DPtesting123", + "ZG=====", + "Z======", + "Zm=8JBSWY3DP", + "=m9vYg==", + "Zm9vYm/y====", + ]; + + class MyClass { + @IsBase32() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isBase32(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isBase32(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isBase32"; + const message = "someProperty must be base32 encoded"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + describe("IsBase64", function() { const constraint = ""; @@ -1638,6 +1732,636 @@ describe("IsBase64", function() { }); +describe("IsIBAN", function() { + + const constraint = ""; + const validValues = ["GR96 0810 0010 0000 0123 4567 890"]; + const invalidValues = [null, undefined, "XX22YYY1234567890123"]; + + class MyClass { + @IsIBAN() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isIBAN(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isIBAN(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isIBAN"; + const message = "someProperty must be an IBAN"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsBIC", function() { + + const constraint = ""; + const validValues = ["SBICKEN1345"]; + const invalidValues = [null, undefined, "SBIC23NXXX"]; + + class MyClass { + @IsBIC() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isBIC(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isBIC(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isBIC"; + const message = "someProperty must be a BIC or SWIFT code"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsEthereumAddress", function() { + + const constraint = ""; + const validValues = ["0x683E07492fBDfDA84457C16546ac3f433BFaa128"]; + const invalidValues = [null, undefined, "0xFCb5AFB808b5679b4911230Aa41FfCD0cd335b422222"]; + + class MyClass { + @IsEthereumAddress() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isEthereumAddress(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isEthereumAddress(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isEthereumAddress"; + const message = "someProperty must be an Ethereum address"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsBtcAddress", function() { + + const constraint = ""; + const validValues = ["bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq"]; + const invalidValues = [null, undefined, "pp8skudq3x5hzw8ew7vzsw8tn4k8wxsqsv0lt0mf3g"]; + + class MyClass { + @IsBtcAddress() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isBtcAddress(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isBtcAddress(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isBtcAddress"; + const message = "someProperty must be a BTC address"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsDataURI", function() { + + const constraint = ""; + const validValues = ["data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E"]; + const invalidValues = [null, undefined, "data:HelloWorld"]; + + class MyClass { + @IsDataURI() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isDataURI(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isDataURI(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isDataURI"; + const message = "someProperty must be a data uri format"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsHSL", function() { + + const constraint = ""; + const validValues = ["hsl(-540, 03%, 4%)"]; + const invalidValues = [null, undefined, "hsl(-0160, 100%, 100a)"]; + + class MyClass { + @IsHSL() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isHSL(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isHSL(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isHSL"; + const message = "someProperty must be a HSL color"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsRgbColor", function() { + + const constraint = ""; + const validValues = ["rgba(255,255,255,0.1)"]; + const invalidValues = [null, undefined, "rgba(0,0,0)"]; + + class MyClass { + @IsRgbColor() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isRgbColor(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isRgbColor(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isRgbColor"; + const message = "someProperty must be RGB color"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsIdentityCard", function() { + + const constraint = "he-IL"; + const validValues = ["335240479"]; + const invalidValues = [null, undefined, "A1234567L"]; + + class MyClass { + @IsIdentityCard(constraint) + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isIdentityCard(value, constraint).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isIdentityCard(value, constraint).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isIdentityCard"; + const message = "someProperty must be a identity card number"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsEAN", function() { + + const constraint = ""; + const validValues = ["9771234567003"]; + const invalidValues = [null, undefined, "079777681629"]; + + class MyClass { + @IsEAN() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isEAN(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isEAN(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isEAN"; + const message = "someProperty must be an EAN (European Article Number)"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsISRC", function() { + + const constraint = ""; + const validValues = ["GBAYE6800011"]; + const invalidValues = [null, undefined, "SRC15705223"]; + + class MyClass { + @IsISRC() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isISRC(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isISRC(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isISRC"; + const message = "someProperty must be an ISRC"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsRFC3339", function() { + + const constraint = ""; + const validValues = ["2010-02-18t00:23:23.33+06:00"]; + const invalidValues = [null, undefined, "2009-05-31 14:60:55Z"]; + + class MyClass { + @IsRFC3339() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isRFC3339(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isRFC3339(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isRFC3339"; + const message = "someProperty must be RFC 3339 date"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsLocale", function() { + + const constraint = ""; + const validValues = ["en_US_POSIX"]; + const invalidValues = [null, undefined, "lo_POP"]; + + class MyClass { + @IsLocale() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isLocale(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isLocale(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isLocale"; + const message = "someProperty must be locale"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsMagnetURI", function() { + + const constraint = ""; + const validValues = ["magnet:?xt=urn:btih:1GSHJVBDVDVJFYEHKFHEFIO8573898434JBFEGHD&dn=foo&tr=udp://foo.com:1337"]; + const invalidValues = [null, undefined, "magnet:?xt=uarn:btih:MCJDCYUFHEUD6E2752T7UJNEKHSUGEJFGTFHVBJS&dn=bar&tr=udp://bar.com:1337"]; + + class MyClass { + @IsMagnetURI() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isMagnetURI(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isMagnetURI(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isMagnetURI"; + const message = "someProperty must be magnet uri format"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsMimeType", function() { + + const constraint = ""; + const validValues = ["multipart/form-data; boundary=something; charset=utf-8"]; + const invalidValues = [null, undefined, "font/woff2; charset=utf-8"]; + + class MyClass { + @IsMimeType() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isMimeType(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isMimeType(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isMimeType"; + const message = "someProperty must be MIME type format"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsOctal", function() { + + const constraint = ""; + const validValues = ["0o01234567"]; + const invalidValues = [null, undefined, "00c12345670c"]; + + class MyClass { + @IsOctal() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isOctal(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isOctal(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isOctal"; + const message = "someProperty must be valid octal number"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsPassportNumber", function() { + + const constraint = "DE"; + const validValues = ["C26VMVVC3"]; + const invalidValues = [null, undefined, "AS0123456"]; + + class MyClass { + @IsPassportNumber(constraint) + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isPassportNumber(value, constraint).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isPassportNumber(value, constraint).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isPassportNumber"; + const message = "someProperty must be valid passport number"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsPostalCode", function() { + + const constraint = "BR"; + const validValues = ["39100-000"]; + const invalidValues = [null, undefined, "13165-00"]; + + class MyClass { + @IsPostalCode(constraint) + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isPostalCode(value, constraint).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isPostalCode(value, constraint).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isPostalCode"; + const message = "someProperty must be a postal code"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + +describe("IsSemVer", function() { + + const constraint = ""; + const validValues = ["1.1.2+meta-valid"]; + const invalidValues = [null, undefined, "1.0.0-alpha_beta"]; + + class MyClass { + @IsSemVer() + someProperty: string; + } + + it("should not fail if validator.validate said that its valid", function(done) { + checkValidValues(new MyClass(), validValues, done); + }); + + it("should fail if validator.validate said that its invalid", function(done) { + checkInvalidValues(new MyClass(), invalidValues, done); + }); + + it("should not fail if method in validator said that its valid", function() { + validValues.forEach(value => isSemVer(value).should.be.true); + }); + + it("should fail if method in validator said that its invalid", function() { + invalidValues.forEach(value => isSemVer(value).should.be.false); + }); + + it("should return error object with proper data", function(done) { + const validationType = "isSemVer"; + const message = "someProperty must be a Semantic Versioning Specification"; + checkReturnedError(new MyClass(), invalidValues, validationType, message, done); + }); + +}); + describe("IsByteLength", function() { const constraint1 = 2;