Repository: validatorjs/validator.js
Pull request #2343 (2023-12-08 01:40:36)

feat(isVAT): improved ABN (AU GST/VAT ID) validation
<!--
Add a descriptive title textbox above, e.g.
feat(validatorName): brief title of what has been done
-->

<!--- briefly describe what you have done in this PR --->
<!--- provide some (credible) references showing the structure of the data to be validated, if applicable --->

Implemented correct ABN (AU GST/VAT ID) validation per the [official reference](https://abr.business.gov.au/Help/AbnFormat) (see also [this reference and implementation](http://www.mathgen.ch/codes/abn.html))

## Checklist

- [X] PR contains only changes related; no stray files, etc.
- README updated: N/A
- [X] Tests written (where applicable)
- [X] References provided in PR (where applicable)


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/validatorjs/validator.js/pull/2343?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`b958bd7`)](https://app.codecov.io/gh/validatorjs/validator.js/commit/b958bd7d1026a434ad3bf90064d3dcb8b775f1a9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs) 99.95% compared to head [(`730fbcc`)](https://app.codecov.io/gh/validatorjs/validator.js/pull/2343?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs) 99.95%.


<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #2343   +/-   ##
=======================================
  Coverage   99.95%   99.95%           
=======================================
  Files         107      107           
  Lines        2454     2459    +5     
  Branches      619      621    +2     
=======================================
+ Hits         2453     2458    +5     
  Partials        1        1           
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/validatorjs/validator.js/pull/2343?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs).


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 21686d8..b4e5329 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-20.04
     strategy:
       matrix:
-        node-version: [14, 12, 10, 8, 6]
+        node-version: [20, 18, 16, 14, 12, 10, 8, 6]
     name: Run tests on Node.js ${{ matrix.node-version }}
     steps:
     - name: Setup Node.js ${{ matrix.node-version }}
@@ -20,10 +20,10 @@ jobs:
     - name: Checkout repository
       uses: actions/checkout@v2
     - name: Install dependencies
-      run: npm install
+      run:  npm install --legacy-peer-deps
     - name: Run tests
       run: npm test
-    - if: matrix.node-version == 14
+    - if: matrix.node-version == 20
       name: Send coverage info to Codecov
       uses: codecov/codecov-action@v1
       with:
diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml
index b4b62f1..ccc202c 100644
--- a/.github/workflows/npm-publish.yml
+++ b/.github/workflows/npm-publish.yml
@@ -5,20 +5,23 @@ on:
 jobs:
   publish:
     runs-on: ubuntu-20.04
+    permissions:
+      contents: read
+      id-token: write
     steps:
-    - name: Setup Node.js 14
-      uses: actions/setup-node@v2-beta
+    - name: Setup Node.js 18
+      uses: actions/setup-node@v3
       with:
-        node-version: 14
+        node-version: 18
         check-latest: true
         registry-url: https://registry.npmjs.org/
     - name: Checkout Repository
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
     - name: Install Dependencies
       run: npm install
     - name: Run Tests
       run: npm test
     - name: Publish Package to NPM Registry
-      run: npm publish
+      run: npm publish --provenance
       env:
         NODE_AUTH_TOKEN: ${{secrets.NPM_SECRET}}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..c7da041
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,37 @@
+# Contributing to validator.js
+Welcome to validator.js repository!! We appreciate your interest in contributing to this open library and for helping our community grow. 
+
+## How to Contribute
+### Code Contribution
+In general, we follow the "fork-and-pull" Git workflow.
+
+1. [Fork](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project) the repository on GitHub
+2. Clone the project to your local machine
+3. Work on your fork
+    * Make your changes and additions
+        - Most of your changes should be focused on src/ and test/ folders and/or [README.md](https://github.com/validatorjs/validator.js/blob/master/README.md).
+        - Files such as validator.js, validator.min.js and files in lib/ folder are autogenerated when running tests (npm test) and need not to be changed **manually**.
+    * Change or add tests if needed
+    * Run tests and make sure they pass
+    * Add changes to README.md if needed
+4. Commit changes to your own branch
+5. **Make sure** you merge the latest from "upstream" and resolve conflicts if there is any
+6. Repeat step 3(3) above
+7. Push your work back up to your fork
+8. Submit a Pull request so that we can review your changes
+
+#### Run Tests
+Tests are using mocha. To run the tests use:
+
+```sh
+$ npm test
+```
+
+### Financial Contribution
+We welcome financial contributions on our [open collective](https://opencollective.com/validatorjs).
+
+You can opt to become a [backer](https://opencollective.com/validatorjs#backer) or a [sponsor](https://opencollective.com/validatorjs#sponsor) and help our project sustain over time.
+
+Thank you to the people who have already contributed:
+
+<a href="https://github.com/validatorjs/validator.js/graphs/contributors"><img src="https://opencollective.com/validatorjs/contributors.svg?width=890" /></a>
\ No newline at end of file
diff --git a/README.md b/README.md
index e00b7cf..5b8bb7d 100644
--- a/README.md
+++ b/README.md
@@ -72,16 +72,6 @@ CDN
 <script src="https://unpkg.com/validator@latest/validator.min.js"></script>
 ```
 
-## Contributors
-
-[Become a backer](https://opencollective.com/validatorjs#backer)
-
-[Become a sponsor](https://opencollective.com/validatorjs#sponsor)
-
-Thank you to the people who have already contributed:
-
-<a href="https://github.com/validatorjs/validator.js/graphs/contributors"><img src="https://opencollective.com/validatorjs/contributors.svg?width=890" /></a>
-
 ## Validators
 
 Here is a list of the validators currently available.
@@ -90,16 +80,17 @@ Validator                               | Description
 --------------------------------------- | --------------------------------------
 **contains(str, seed [, options])**    | check if the string contains the seed.<br/><br/>`options` is an object that defaults to `{ ignoreCase: false, minOccurrences: 1 }`.<br />Options: <br/> `ignoreCase`: Ignore case when doing comparison, default false.<br/>`minOccurences`: Minimum number of occurrences for the seed in the string. Defaults to 1.
 **equals(str, comparison)**             | check if the string matches the comparison.
+**isAbaRouting(str)**               | check if the string is an ABA routing number for US bank account / cheque.
 **isAfter(str [, options])**            | check if the string is a date that is after the specified date.<br/><br/>`options` is an object that defaults to `{ comparisonDate: Date().toString() }`.<br/>**Options:**<br/>`comparisonDate`: Date to compare to. Defaults to `Date().toString()` (now).
-**isAlpha(str [, locale, options])**    | check if the string contains only letters (a-zA-Z).<br/><br/>`locale` is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'bn', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'kk-KZ', 'ko-KR', 'ja-JP', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA']` and defaults to `en-US`. Locale list is `validator.isAlphaLocales`. `options` is an optional object that can be supplied with the following key(s): `ignore` which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
-**isAlphanumeric(str [, locale, options])**      | check if the string contains only letters and numbers (a-zA-Z0-9).<br/><br/>`locale` is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bn', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'kk-KZ', 'ko-KR', 'ja-JP','ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphanumericLocales`. `options` is an optional object that can be supplied with the following key(s): `ignore` which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
+**isAlpha(str [, locale, options])**    | check if the string contains only letters (a-zA-Z).<br/><br/>`locale` is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'bn', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'eo', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'kk-KZ', 'ko-KR', 'ja-JP', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA']` and defaults to `en-US`. Locale list is `validator.isAlphaLocales`. `options` is an optional object that can be supplied with the following key(s): `ignore` which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
+**isAlphanumeric(str [, locale, options])**      | check if the string contains only letters and numbers (a-zA-Z0-9).<br/><br/>`locale` is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bn', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'eo', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'kk-KZ', 'ko-KR', 'ja-JP','ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphanumericLocales`. `options` is an optional object that can be supplied with the following key(s): `ignore` which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
 **isAscii(str)**                        | check if the string contains ASCII chars only.
 **isBase32(str [, options])**           | check if the string is base32 encoded. `options` is optional and defaults to `{ crockford: false }`.<br/> When `crockford` is true it tests the given base32 encoded string using [Crockford's base32 alternative][Crockford Base32].
 **isBase58(str)**                       | check if the string is base58 encoded.
 **isBase64(str [, options])**          | check if the string is base64 encoded. `options` is optional and defaults to `{ urlSafe: false }`<br/> when `urlSafe` is true it tests the given base64 encoded string is [url safe][Base64 URL Safe].
 **isBefore(str [, date])**              | check if the string is a date that is before the specified date.
 **isBIC(str)**                          | check if the string is a BIC (Bank Identification Code) or SWIFT code.
-**isBoolean(str [, options])**          | check if the string is a boolean.<br/>`options` is an object which defaults to `{ loose: false }`. If `loose` is is set to false, the validator will strictly match ['true', 'false', '0', '1']. If `loose` is set to true, the validator will also match 'yes', 'no', and will match a valid boolean string of any case. (e.g.: ['true', 'True', 'TRUE']).
+**isBoolean(str [, options])**          | check if the string is a boolean.<br/>`options` is an object which defaults to `{ loose: false }`. If `loose` is set to false, the validator will strictly match ['true', 'false', '0', '1']. If `loose` is set to true, the validator will also match 'yes', 'no', and will match a valid boolean string of any case. (e.g.: ['true', 'True', 'TRUE']).
 **isBtcAddress(str)**            | check if the string is a valid BTC address.
 **isByteLength(str [, options])**          | check if the string's length (in UTF-8 bytes) falls in a range.<br/><br/>`options` is an object which defaults to `{ min: 0, max: undefined }`.
 **isCreditCard(str [, options])**                   | check if the string is a credit card number.<br/><br/> `options` is an optional object that can be supplied with the following key(s): `provider` is an optional key whose value should be a string, and defines the company issuing the credit card. Valid values include `['amex', 'dinersclub', 'discover', 'jcb', 'mastercard', 'unionpay', 'visa']` or blank will check for any provider. 
@@ -142,13 +133,13 @@ Validator                               | Description
 **isJWT(str)**                         | check if the string is valid JWT token.
 **isLatLong(str [, options])**                      | check if the string is a valid latitude-longitude coordinate in the format `lat,long` or `lat, long`.<br/><br/>`options` is an object that defaults to `{ checkDMS: false }`. Pass `checkDMS` as `true` to validate DMS(degrees, minutes, and seconds) latitude-longitude format.
 **isLength(str [, options])**              | check if the string's length falls in a range.<br/><br/>`options` is an object which defaults to `{ min: 0, max: undefined }`. Note: this function takes into account surrogate pairs.
-**isLicensePlate(str, locale)**     | check if the string matches the format of a country's license plate.<br/><br/>`locale` is one of `['cs-CZ', 'de-DE', 'de-LI', 'en-IN', 'es-AR', 'hu-HU', 'pt-BR', 'pt-PT', 'sq-AL', 'sv-SE']` or `'any'`.
+**isLicensePlate(str, locale)**     | check if the string matches the format of a country's license plate.<br/><br/>`locale` is one of `['cs-CZ', 'de-DE', 'de-LI', 'en-IN', 'en-PK', 'es-AR', 'hu-HU', 'pt-BR', 'pt-PT', 'sq-AL', 'sv-SE']` or `'any'`.
 **isLocale(str)**                       | check if the string is a locale.
 **isLowercase(str)**                    | check if the string is lowercase.
 **isLuhnNumber(str)**                    | check if the string passes the [Luhn algorithm check](https://en.wikipedia.org/wiki/Luhn_algorithm).
 **isMACAddress(str [, options])**                   | check if the string is a MAC address.<br/><br/>`options` is an object which defaults to `{ no_separators: false }`. If `no_separators` is true, the validator will allow MAC addresses without separators. Also, it allows the use of hyphens, spaces or dots e.g. '01 02 03 04 05 ab', '01-02-03-04-05-ab' or '0102.0304.05ab'. The options also allow a `eui` property to specify if it needs to be validated against EUI-48 or EUI-64. The accepted values of `eui` are: 48, 64.
 **isMagnetURI(str)**                      | check if the string is a [Magnet URI format][Magnet URI Format].
-**isMailtoURI(str, [, options])**                      | check if the string is a [Magnet URI format][Mailto URI Format].<br/><br/>`options` is an object of validating emails inside the URI (check `isEmail`s options for details).
+**isMailtoURI(str, [, options])**                      | check if the string is a [Mailto URI format][Mailto URI Format].<br/><br/>`options` is an object of validating emails inside the URI (check `isEmail`s options for details).
 **isMD5(str)**                          | check if the string is a MD5 hash.<br/><br/>Please note that you can also use the `isHash(str, 'md5')` function. Keep in mind that MD5 has some collision weaknesses compared to other algorithms (e.g., SHA).
 **isMimeType(str)**                     | check if the string matches to a valid [MIME type][MIME Type] format.
 **isMobilePhone(str [, locale [, options]])**          | check if the string is a mobile phone number,<br/><br/>`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-EH', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'az-AZ', 'az-LB', 'az-LY', 'be-BY', 'bg-BG', 'bn-BD', 'bs-BA', 'ca-AD', 'cs-CZ', 'da-DK', 'de-AT', 'de-CH', 'de-DE', 'de-LU', 'dv-MV', 'dz-BT', 'el-CY', 'el-GR', 'en-AG', 'en-AI', 'en-AU', 'en-BM', 'en-BS', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-IE', 'en-IN', 'en-JM', 'en-KE', 'en-KI', 'en-KN', 'en-LS', 'en-MO', 'en-MT', 'en-MU', 'en-MW', 'en-NG', 'en-NZ', 'en-PG', 'en-PH', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-SS', 'en-TZ', 'en-UG', 'en-US', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-EC', 'es-ES', 'es-HN', 'es-MX', 'es-NI', 'es-PA', 'es-PE', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-AF', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-BJ', 'fr-CD', 'fr-CF', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'fr-WF', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'ir-IR', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'ky-KG', 'lt-LT', 'mg-MG', 'mn-MN', 'ms-MY', 'my-MM', 'mz-MZ', 'nb-NO', 'ne-NP', 'nl-AW', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-AO', 'pt-BR', 'pt-PT', 'ro-Md', 'ro-RO', 'ru-RU', 'si-LK', 'sk-SK', 'sl-SI', 'so-SO', 'sq-AL', 'sr-RS', 'sv-SE', 'tg-TJ', 'th-TH', 'tk-TM', 'tr-TR', 'uk-UA', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-MO', 'zh-TW']` OR defaults to `'any'`. If 'any' or a falsey value is used, function will check if any of the locales match).<br/><br/>`options` is an optional object that can be supplied with the following keys: `strictMode`, if this is set to `true`, the mobile phone number must be supplied with the country code and therefore must start with `+`. Locale list is `validator.isMobilePhoneLocales`.
@@ -167,7 +158,7 @@ Validator                               | Description
 **isSlug(str)**                         | check if the string is of type slug.
 **isStrongPassword(str [, options])**   | check if the string can be considered a strong password or not. Allows for custom requirements or scoring rules. If `returnScore` is true, then the function returns an integer score for the password rather than a boolean.<br/>Default options: <br/>`{ minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1, minSymbols: 1, returnScore: false, pointsPerUnique: 1, pointsPerRepeat: 0.5, pointsForContainingLower: 10, pointsForContainingUpper: 10, pointsForContainingNumber: 10, pointsForContainingSymbol: 10 }`
 **isTime(str [, options])**             | check if the string is a valid time e.g. [`23:01:59`, new Date().toLocaleTimeString()].<br/><br/> `options` is an object which can contain the keys `hourFormat` or `mode`.<br/><br/>`hourFormat` is a key and defaults to `'hour24'`.<br/><br/>`mode` is a key and defaults to `'default'`. <br/><br/>`hourFomat` can contain the values `'hour12'` or `'hour24'`, `'hour24'` will validate hours in 24 format and `'hour12'` will validate hours in 12 format. <br/><br/>`mode` can contain the values `'default'` or `'withSeconds'`, `'default'` will validate `HH:MM` format, `'withSeconds'` will validate the `HH:MM:SS` format.
-**isTaxID(str, locale)**                | check if the string is a valid Tax Identification Number. Default locale is `en-US`.<br/><br/>More info about exact TIN support can be found in `src/lib/isTaxID.js`.<br/><br/>Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-CA', 'en-GB', 'en-IE', 'en-US', 'es-AR', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV', 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE' ]`.
+**isTaxID(str, locale)**                | check if the string is a valid Tax Identification Number. Default locale is `en-US`.<br/><br/>More info about exact TIN support can be found in `src/lib/isTaxID.js`.<br/><br/>Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-CA', 'en-GB', 'en-IE', 'en-US', 'es-AR', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV', 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE', 'uk-UA']`.
 **isURL(str [, options])**              | check if the string is a URL.<br/><br/>`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_port: false, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, allow_fragments: true, allow_query_components: true, disallow_auth: false, validate_length: true }`.<br/><br/>`require_protocol` - if set to true isURL will return false if protocol is not present in the URL.<br/>`require_valid_protocol` - isURL will check if the URL's protocol is present in the protocols option.<br/>`protocols` - valid protocols can be modified with this option.<br/>`require_host` - if set to false isURL will not check if host is present in the URL.<br/>`require_port` - if set to true isURL will check if port is present in the URL.<br/>`allow_protocol_relative_urls` - if set to true protocol relative URLs will be allowed.<br/>`allow_fragments` - if set to false isURL will return false if fragments are present.<br/>`allow_query_components` - if set to false isURL will return false if query components are present.<br/>`validate_length` - if set to false isURL will skip string length validation (2083 characters is IE max URL length).
 **isUUID(str [, version])**             | check if the string is a UUID (version 1, 2, 3, 4 or 5).
 **isVariableWidth(str)**                | check if the string contains a mixture of full and half-width chars.
@@ -201,33 +192,6 @@ XSS sanitization was removed from the library in [2d5d6999](https://github.com/v
 
 For an alternative, have a look at Yahoo's [xss-filters library](https://github.com/yahoo/xss-filters) or at [DOMPurify](https://github.com/cure53/DOMPurify).
 
-## Contributing
-
-In general, we follow the "fork-and-pull" Git workflow.
-
-1. Fork the repo on GitHub
-2. Clone the project to your own machine
-3. Work on your fork
-    1. Make your changes and additions
-        - Most of your changes should be focused on `src/` and `test/` folders and/or `README.md`.
-        - Files such as `validator.js`, `validator.min.js` and files in `lib/` folder are autogenerated when running tests (`npm test`) and need not to be changed **manually**.
-    2. Change or add tests if needed
-    3. Run tests and make sure they pass
-    4. Add changes to README.md if needed
-4. Commit changes to your own branch
-5. **Make sure** you merge the latest from "upstream" and resolve conflicts if there is any
-6. Repeat step 3(3) above
-7. Push your work back up to your fork
-8. Submit a Pull request so that we can review your changes
-
-## Tests
-
-Tests are using mocha, to run the tests use:
-
-```sh
-$ npm test
-```
-
 ## Maintainers
 
 - [chriso](https://github.com/chriso) - **Chris O'Hara** (author)
diff --git a/src/index.js b/src/index.js
index bef4cff..0938110 100644
--- a/src/index.js
+++ b/src/index.js
@@ -18,6 +18,7 @@ import isTime from './lib/isTime';
 import isBoolean from './lib/isBoolean';
 import isLocale from './lib/isLocale';
 
+import isAbaRouting from './lib/isAbaRouting';
 import isAlpha, { locales as isAlphaLocales } from './lib/isAlpha';
 import isAlphanumeric, { locales as isAlphanumericLocales } from './lib/isAlphanumeric';
 import isNumeric from './lib/isNumeric';
@@ -146,6 +147,7 @@ const validator = {
   isBoolean,
   isIBAN,
   isBIC,
+  isAbaRouting,
   isAlpha,
   isAlphaLocales,
   isAlphanumeric,
diff --git a/src/lib/alpha.js b/src/lib/alpha.js
index d540ed1..8c37934 100644
--- a/src/lib/alpha.js
+++ b/src/lib/alpha.js
@@ -35,6 +35,7 @@ export const alpha = {
   he: /^[א-ת]+$/,
   fa: /^['آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی']+$/i,
   bn: /^['ঀঁংঃঅআইঈউঊঋঌএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ়ঽািীুূৃৄেৈোৌ্ৎৗড়ঢ়য়ৠৡৢৣৰৱ৲৳৴৵৶৷৸৹৺৻']+$/,
+  eo: /^[ABCĈD-GĜHĤIJĴK-PRSŜTUŬVZ]+$/i,
   'hi-IN': /^[\u0900-\u0961]+[\u0972-\u097F]*$/i,
   'si-LK': /^[\u0D80-\u0DFF]+$/,
 };
@@ -75,6 +76,7 @@ export const alphanumeric = {
   he: /^[0-9א-ת]+$/,
   fa: /^['0-9آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی۱۲۳۴۵۶۷۸۹۰']+$/i,
   bn: /^['ঀঁংঃঅআইঈউঊঋঌএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ়ঽািীুূৃৄেৈোৌ্ৎৗড়ঢ়য়ৠৡৢৣ০১২৩৪৫৬৭৮৯ৰৱ৲৳৴৵৶৷৸৹৺৻']+$/,
+  eo: /^[0-9ABCĈD-GĜHĤIJĴK-PRSŜTUŬVZ]+$/i,
   'hi-IN': /^[\u0900-\u0963]+[\u0966-\u097F]*$/i,
   'si-LK': /^[0-9\u0D80-\u0DFF]+$/,
 };
@@ -125,7 +127,7 @@ for (let locale, i = 0; i < bengaliLocales.length; i++) {
 // Source: https://en.wikipedia.org/wiki/Decimal_mark
 export const dotDecimal = ['ar-EG', 'ar-LB', 'ar-LY'];
 export const commaDecimal = [
-  'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-ZM', 'es-ES', 'fr-CA', 'fr-FR',
+  'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-ZM', 'eo', 'es-ES', 'fr-CA', 'fr-FR',
   'id-ID', 'it-IT', 'ku-IQ', 'hi-IN', 'hu-HU', 'nb-NO', 'nn-NO', 'nl-NL', 'pl-PL', 'pt-PT',
   'ru-RU', 'kk-KZ', 'si-LK', 'sl-SI', 'sr-RS@latin', 'sr-RS', 'sv-SE', 'tr-TR', 'uk-UA', 'vi-VN',
 ];
diff --git a/src/lib/isAbaRouting.js b/src/lib/isAbaRouting.js
new file mode 100644
index 0000000..0c6fd7f
--- /dev/null
+++ b/src/lib/isAbaRouting.js
@@ -0,0 +1,20 @@
+import assertString from './util/assertString';
+
+// http://www.brainjar.com/js/validation/
+// https://www.aba.com/news-research/research-analysis/routing-number-policy-procedures
+// series reserved for future use are excluded
+const isRoutingReg = /^(?!(1[3-9])|(20)|(3[3-9])|(4[0-9])|(5[0-9])|(60)|(7[3-9])|(8[1-9])|(9[0-2])|(9[3-9]))[0-9]{9}$/;
+
+export default function isAbaRouting(str) {
+  assertString(str);
+
+  if (!isRoutingReg.test(str)) return false;
+
+  let checkSumVal = 0;
+  for (let i = 0; i < str.length; i++) {
+    if (i % 3 === 0) checkSumVal += str[i] * 3;
+    else if (i % 3 === 1) checkSumVal += str[i] * 7;
+    else checkSumVal += str[i] * 1;
+  }
+  return (checkSumVal % 10 === 0);
+}
diff --git a/src/lib/isDate.js b/src/lib/isDate.js
index f0b2891..dc69b3b 100644
--- a/src/lib/isDate.js
+++ b/src/lib/isDate.js
@@ -22,7 +22,7 @@ function zip(date, format) {
 }
 
 export default function isDate(input, options) {
-  if (typeof options === 'string') { // Allow backward compatbility for old format isDate(input [, format])
+  if (typeof options === 'string') { // Allow backward compatibility for old format isDate(input [, format])
     options = merge({ format: options }, default_date_options);
   } else {
     options = merge(options, default_date_options);
@@ -49,6 +49,11 @@ export default function isDate(input, options) {
 
     let fullYear = dateObj.y;
 
+    // Check if the year starts with a hyphen
+    if (fullYear.startsWith('-')) {
+      return false; // Hyphen before year is not allowed
+    }
+
     if (dateObj.y.length === 2) {
       const parsedYear = parseInt(dateObj.y, 10);
 
diff --git a/src/lib/isIBAN.js b/src/lib/isIBAN.js
index dd226b1..5edcf83 100644
--- a/src/lib/isIBAN.js
+++ b/src/lib/isIBAN.js
@@ -24,6 +24,7 @@ const ibanRegexThroughCountryCode = {
   DE: /^(DE[0-9]{2})\d{18}$/,
   DK: /^(DK[0-9]{2})\d{14}$/,
   DO: /^(DO[0-9]{2})[A-Z]{4}\d{20}$/,
+  DZ: /^(DZ\d{24})$/,
   EE: /^(EE[0-9]{2})\d{16}$/,
   EG: /^(EG[0-9]{2})\d{25}$/,
   ES: /^(ES[0-9]{2})\d{20}$/,
diff --git a/src/lib/isISO4217.js b/src/lib/isISO4217.js
index 0738614..076d5a6 100644
--- a/src/lib/isISO4217.js
+++ b/src/lib/isISO4217.js
@@ -20,7 +20,7 @@ const validISO4217CurrencyCodes = new Set([
   'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG',
   'QAR',
   'RON', 'RSD', 'RUB', 'RWF',
-  'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SRD', 'SSP', 'STN', 'SVC', 'SYP', 'SZL',
+  'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLE', 'SLL', 'SOS', 'SRD', 'SSP', 'STN', 'SVC', 'SYP', 'SZL',
   'THB', 'TJS', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TWD', 'TZS',
   'UAH', 'UGX', 'USD', 'USN', 'UYI', 'UYU', 'UYW', 'UZS',
   'VES', 'VND', 'VUV',
diff --git a/src/lib/isInt.js b/src/lib/isInt.js
index 8047a69..edd67f7 100644
--- a/src/lib/isInt.js
+++ b/src/lib/isInt.js
@@ -9,10 +9,7 @@ export default function isInt(str, options) {
 
   // Get the regex to use for testing, based on whether
   // leading zeroes are allowed or not.
-  let regex = (
-    options.hasOwnProperty('allow_leading_zeroes') && !options.allow_leading_zeroes ?
-      int : intLeadingZeroes
-  );
+  const regex = options.allow_leading_zeroes === false ? int : intLeadingZeroes;
 
   // Check min/max/lt/gt
   let minCheckPassed = (!options.hasOwnProperty('min') || str >= options.min);
diff --git a/src/lib/isLicensePlate.js b/src/lib/isLicensePlate.js
index 48f8ebe..8476f2f 100644
--- a/src/lib/isLicensePlate.js
+++ b/src/lib/isLicensePlate.js
@@ -18,6 +18,7 @@ const validators = {
     /^[A-Z]{2}[- ]?((\d{3}[- ]?(([A-Z]{2})|T))|(R[- ]?\d{3}))$/.test(str),
   'sv-SE': str =>
     /^[A-HJ-PR-UW-Z]{3} ?[\d]{2}[A-HJ-PR-UW-Z1-9]$|(^[A-ZÅÄÖ ]{2,7}$)/.test(str.trim()),
+  'en-PK': str => /(^[A-Z]{2}((\s|-){0,1})[0-9]{3,4}((\s|-)[0-9]{2}){0,1}$)|(^[A-Z]{3}((\s|-){0,1})[0-9]{3,4}((\s|-)[0-9]{2}){0,1}$)|(^[A-Z]{4}((\s|-){0,1})[0-9]{3,4}((\s|-)[0-9]{2}){0,1}$)|(^[A-Z]((\s|-){0,1})[0-9]{4}((\s|-)[0-9]{2}){0,1}$)/.test(str.trim()),
 };
 
 export default function isLicensePlate(str, locale) {
diff --git a/src/lib/isMailtoURI.js b/src/lib/isMailtoURI.js
index 0dd95b6..67748a5 100644
--- a/src/lib/isMailtoURI.js
+++ b/src/lib/isMailtoURI.js
@@ -41,7 +41,7 @@ export default function isMailtoURI(url, options) {
     return false;
   }
 
-  const [to = '', queryString = ''] = url.replace('mailto:', '').split('?');
+  const [to, queryString = ''] = url.replace('mailto:', '').split('?');
 
   if (!to && !queryString) {
     return true;
diff --git a/src/lib/isMobilePhone.js b/src/lib/isMobilePhone.js
index 7c9b420..4d81921 100644
--- a/src/lib/isMobilePhone.js
+++ b/src/lib/isMobilePhone.js
@@ -2,7 +2,7 @@ import assertString from './util/assertString';
 
 /* eslint-disable max-len */
 const phones = {
-  'am-AM': /^(\+?374|0)((10|[9|7][0-9])\d{6}$|[2-4]\d{7}$)/,
+  'am-AM': /^(\+?374|0)(33|4[134]|55|77|88|9[13-689])\d{6}$/,
   'ar-AE': /^((\+?971)|0)?5[024568]\d{7}$/,
   'ar-BH': /^(\+?973)?(3|6)\d{7}$/,
   'ar-DZ': /^(\+?213|0)(5|6|7)\d{8}$/,
diff --git a/src/lib/isPassportNumber.js b/src/lib/isPassportNumber.js
index 4763d65..c1803fb 100644
--- a/src/lib/isPassportNumber.js
+++ b/src/lib/isPassportNumber.js
@@ -11,7 +11,7 @@ const passportRegexByCountryCode = {
   AR: /^[A-Z]{3}\d{6}$/, // ARGENTINA
   AT: /^[A-Z]\d{7}$/, // AUSTRIA
   AU: /^[A-Z]\d{7}$/, // AUSTRALIA
-  AZ: /^[A-Z]{2,3}\d{7,8}$/, // AZERBAIJAN
+  AZ: /^[A-Z]{1}\d{8}$/, // AZERBAIJAN
   BE: /^[A-Z]{2}\d{6}$/, // BELGIUM
   BG: /^\d{9}$/, // BULGARIA
   BR: /^[A-Z]{2}\d{6}$/, // BRAZIL
diff --git a/src/lib/isPort.js b/src/lib/isPort.js
index 0b316b7..0a9ddce 100644
--- a/src/lib/isPort.js
+++ b/src/lib/isPort.js
@@ -1,5 +1,5 @@
 import isInt from './isInt';
 
 export default function isPort(str) {
-  return isInt(str, { min: 0, max: 65535 });
+  return isInt(str, { allow_leading_zeroes: false, min: 0, max: 65535 });
 }
diff --git a/src/lib/isPostalCode.js b/src/lib/isPostalCode.js
index e621391..99cba29 100644
--- a/src/lib/isPostalCode.js
+++ b/src/lib/isPostalCode.js
@@ -52,7 +52,7 @@ const patterns = {
   MX: fiveDigit,
   MT: /^[A-Za-z]{3}\s{0,1}\d{4}$/,
   MY: fiveDigit,
-  NL: /^\d{4}\s?[a-z]{2}$/i,
+  NL: /^[1-9]\d{3}\s?(?!sa|sd|ss)[a-z]{2}$/i,
   NO: fourDigit,
   NP: /^(10|21|22|32|33|34|44|45|56|57)\d{3}$|^(977)$/i,
   NZ: fourDigit,
diff --git a/src/lib/isStrongPassword.js b/src/lib/isStrongPassword.js
index 5db901f..8fe9223 100644
--- a/src/lib/isStrongPassword.js
+++ b/src/lib/isStrongPassword.js
@@ -4,7 +4,7 @@ import assertString from './util/assertString';
 const upperCaseRegex = /^[A-Z]$/;
 const lowerCaseRegex = /^[a-z]$/;
 const numberRegex = /^[0-9]$/;
-const symbolRegex = /^[-#!$@£%^&*()_+|~=`{}\[\]:";'<>?,.\/ ]$/;
+const symbolRegex = /^[-#!$@£%^&*()_+|~=`{}\[\]:";'<>?,.\/\\ ]$/;
 
 const defaultOptions = {
   minLength: 8,
diff --git a/src/lib/isTaxID.js b/src/lib/isTaxID.js
index b82156e..d13229f 100644
--- a/src/lib/isTaxID.js
+++ b/src/lib/isTaxID.js
@@ -1141,6 +1141,21 @@ function svSeCheck(tin) {
   return algorithms.luhnCheck(tin.replace(/\W/, ''));
 }
 
+/**
+ * uk-UA validation function
+ * Verify TIN validity by calculating check (last) digit (variant of MOD 11)
+ */
+function ukUaCheck(tin) {
+  // Calculate check digit
+  const digits = tin.split('').map(a => parseInt(a, 10));
+  const multipliers = [-1, 5, 7, 9, 4, 6, 10, 5, 7];
+  let checksum = 0;
+  for (let i = 0; i < multipliers.length; i++) {
+    checksum += digits[i] * multipliers[i];
+  }
+  return checksum % 11 === 10 ? digits[9] === 0 : digits[9] === checksum % 11;
+}
+
 // Locale lookup objects
 
 /*
@@ -1181,6 +1196,7 @@ const taxIdFormat = {
   'sk-SK': /^\d{6}\/{0,1}\d{3,4}$/,
   'sl-SI': /^[1-9]\d{7}$/,
   'sv-SE': /^(\d{6}[-+]{0,1}\d{4}|(18|19|20)\d{6}[-+]{0,1}\d{4})$/,
+  'uk-UA': /^\d{10}$/,
 };
 // taxIdFormat locale aliases
 taxIdFormat['lb-LU'] = taxIdFormat['fr-LU'];
@@ -1220,6 +1236,7 @@ const taxIdCheck = {
   'sk-SK': skSkCheck,
   'sl-SI': slSiCheck,
   'sv-SE': svSeCheck,
+  'uk-UA': ukUaCheck,
 };
 // taxIdCheck locale aliases
 taxIdCheck['lb-LU'] = taxIdCheck['fr-LU'];
diff --git a/src/lib/isUUID.js b/src/lib/isUUID.js
index c026ca7..512141d 100644
--- a/src/lib/isUUID.js
+++ b/src/lib/isUUID.js
@@ -6,6 +6,7 @@ const uuid = {
   3: /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
   4: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
   5: /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
+  7: /^[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
   all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
 };
 
diff --git a/src/lib/isVAT.js b/src/lib/isVAT.js
index ece7d85..50fcf52 100644
--- a/src/lib/isVAT.js
+++ b/src/lib/isVAT.js
@@ -1,6 +1,22 @@
 import assertString from './util/assertString';
 import * as algorithms from './util/algorithms';
 
+const AU = (str) => {
+  const match = str.match(/^(AU)?(\d{11})$/);
+  if (!match) {
+    return false;
+  }
+  // @see {@link https://abr.business.gov.au/Help/AbnFormat}
+  const weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
+  str = str.replace(/^AU/, '');
+  const ABN = (parseInt(str.slice(0, 1), 10) - 1).toString() + str.slice(1);
+  let total = 0;
+  for (let i = 0; i < 11; i++) {
+    total += weights[i] * ABN.charAt(i);
+  }
+  return (total !== 0 && total % 89 === 0);
+};
+
 const CH = (str) => {
   // @see {@link https://www.ech.ch/de/ech/ech-0097/5.2.0}
   const hasValidCheckNumber = (digits) => {
@@ -68,14 +84,14 @@ export const vatMatchers = {
    */
   AL: str => /^(AL)?\w{9}[A-Z]$/.test(str),
   MK: str => /^(MK)?\d{13}$/.test(str),
-  AU: str => /^(AU)?\d{11}$/.test(str),
+  AU,
   BY: str => /^(УНП )?\d{9}$/.test(str),
   CA: str => /^(CA)?\d{9}$/.test(str),
   IS: str => /^(IS)?\d{5,6}$/.test(str),
   IN: str => /^(IN)?\d{15}$/.test(str),
   ID: str => /^(ID)?(\d{15}|(\d{2}.\d{3}.\d{3}.\d{1}-\d{3}.\d{3}))$/.test(str),
   IL: str => /^(IL)?\d{9}$/.test(str),
-  KZ: str => /^(KZ)?\d{9}$/.test(str),
+  KZ: str => /^(KZ)?\d{12}$/.test(str),
   NZ: str => /^(NZ)?\d{9}$/.test(str),
   NG: str => /^(NG)?(\d{12}|(\d{8}-\d{4}))$/.test(str),
   NO: str => /^(NO)?\d{9}MVA$/.test(str),


Test patch:
diff --git a/test/validators.test.js b/test/validators.test.js
index 6c68cd7..3928a1c 100644
--- a/test/validators.test.js
+++ b/test/validators.test.js
@@ -2048,6 +2048,25 @@ describe('Validators', () => {
     });
   });
 
+  it('should validate Esperanto alpha strings', () => {
+    test({
+      validator: 'isAlpha',
+      args: ['eo'],
+      valid: [
+        'saluton',
+        'eĥoŝanĝoĉiuĵaŭde',
+        'EĤOŜANĜOĈIUĴAŬDE',
+        'Esperanto',
+        'LaŭLudovikoZamenhofBongustasFreŝaĈeĥaManĝaĵoKunSpicoj',
+      ],
+      invalid: [
+        'qwxyz',
+        '1887',
+        'qwxyz 1887',
+      ],
+    });
+  });
+
   it('should error on invalid locale', () => {
     test({
       validator: 'isAlpha',
@@ -2735,6 +2754,24 @@ describe('Validators', () => {
     });
   });
 
+  it('should validate Esperanto alphanumeric strings', () => {
+    test({
+      validator: 'isAlphanumeric',
+      args: ['eo'],
+      valid: [
+        'saluton',
+        'eĥoŝanĝoĉiuĵaŭde0123456789',
+        'EĤOŜANĜOĈIUĴAŬDE0123456789',
+        'Esperanto1887',
+        'LaŭLudovikoZamenhofBongustasFreŝaĈeĥaManĝaĵoKunSpicoj',
+      ],
+      invalid: [
+        'qwxyz',
+        'qwxyz 1887',
+      ],
+    });
+  });
+
   it('should error on invalid locale', () => {
     test({
       validator: 'isAlphanumeric',
@@ -2855,6 +2892,7 @@ describe('Validators', () => {
         '',
         '-1',
         '65536',
+        '0080',
       ],
     });
   });
@@ -2926,11 +2964,11 @@ describe('Validators', () => {
       validator: 'isPassportNumber',
       args: ['AZ'],
       valid: [
-        'AZE16175905',
-        'AA1617595',
+        'A16175905',
+        'A16175958',
       ],
       invalid: [
-        'A12345843',
+        'AZ1234584',
       ],
     });
 
@@ -3648,6 +3686,21 @@ describe('Validators', () => {
         '7903699371',
       ],
     });
+
+    test({
+      validator: 'isPassportNumber',
+      args: ['ZA'],
+      valid: [
+        'T12345678',
+        'A12345678',
+        'M12345678',
+        'D12345678',
+      ],
+      invalid: [
+        '123456789',
+        'Z12345678',
+      ],
+    });
   });
 
   it('should validate decimal numbers', () => {
@@ -5021,6 +5074,7 @@ describe('Validators', () => {
         'A987FBC9-4BED-3078-CF07-9141BA07C9F3',
         'A987FBC9-4BED-4078-8F07-9141BA07C9F3',
         'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
       invalid: [
         '',
@@ -5038,6 +5092,7 @@ describe('Validators', () => {
       valid: [
         'A117FBC9-4BED-3078-CF07-9141BA07C9F3',
         'A117FBC9-4BED-5078-AF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
       invalid: [
         '',
@@ -5051,6 +5106,7 @@ describe('Validators', () => {
       args: [null],
       valid: [
         'A127FBC9-4BED-3078-CF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
       invalid: [
         '',
@@ -5072,6 +5128,7 @@ describe('Validators', () => {
         'AAAAAAAA-1111-2222-AAAG-111111111111',
         'A987FBC9-4BED-4078-8F07-9141BA07C9F3',
         'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
     });
     test({
@@ -5087,6 +5144,7 @@ describe('Validators', () => {
         'AAAAAAAA-1111-1111-AAAG-111111111111',
         'A987FBC9-4BED-4078-8F07-9141BA07C9F3',
         'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
     });
     test({
@@ -5102,6 +5160,7 @@ describe('Validators', () => {
         'AAAAAAAA-1111-1111-AAAG-111111111111',
         'A987FBC9-4BED-4078-8F07-9141BA07C9F3',
         'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
     });
     test({
@@ -5120,6 +5179,7 @@ describe('Validators', () => {
         'AAAAAAAA-1111-1111-AAAG-111111111111',
         'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
         'A987FBC9-4BED-3078-CF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
     });
     test({
@@ -5138,6 +5198,7 @@ describe('Validators', () => {
         'AAAAAAAA-1111-1111-AAAG-111111111111',
         '9c858901-8a57-4791-81fe-4c455b099bc9',
         'A987FBC9-4BED-3078-CF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
       ],
     });
     test({
@@ -5150,6 +5211,26 @@ describe('Validators', () => {
         '987FBC97-4BED-3078-AF07-9141BA07C9F3',
         '987FBC97-4BED-4078-AF07-9141BA07C9F3',
         '987FBC97-4BED-5078-AF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
+      ],
+    });
+    test({
+      validator: 'isUUID',
+      args: [7],
+      valid: [
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
+      ],
+      invalid: [
+        '',
+        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',
+        '934859',
+        'AAAAAAAA-1111-1111-AAAG-111111111111',
+        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
+        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',
+        '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1',
+        '625e63f3-58f5-40b7-83a1-a72ad31acffb',
+        '57b73598-8764-4ad0-a76a-679bb6640eb1',
+        '9c858901-8a57-4791-81fe-4c455b099bc9',
       ],
     });
   });
@@ -5232,6 +5313,26 @@ describe('Validators', () => {
     });
   });
 
+  it('should validate ABA routing number', () => {
+    test({
+      validator: 'isAbaRouting',
+      valid: [
+        '322070381',
+        '011103093',
+        '263170175',
+        '124303065',
+      ],
+      invalid: [
+        '426317017',
+        '789456124',
+        '603558459',
+        'qwerty',
+        '12430306',
+        '382070381',
+      ],
+    });
+  });
+
   it('should validate IBAN', () => {
     test({
       validator: 'isIBAN',
@@ -5259,6 +5360,7 @@ describe('Validators', () => {
         'IR200170000000339545727003',
         'MZ97123412341234123412341',
         'MA64011519000001205000534921',
+        'DZ580002100001113000000570',
       ],
       invalid: [
         'XX22YYY1234567890123',
@@ -6632,20 +6734,39 @@ describe('Validators', () => {
       {
         locale: 'am-AM',
         valid: [
-          '+37410324123',
-          '+37422298765',
-          '+37431276521',
-          '022698763',
-          '37491987654',
-          '+37494567890',
+          '+37433123456',
+          '+37441123456',
+          '+37443123456',
+          '+37444123456',
+          '+37455123456',
+          '+37477123456',
+          '+37488123456',
+          '+37491123456',
+          '+37493123456',
+          '+37494123456',
+          '+37495123456',
+          '+37496123456',
+          '+37498123456',
+          '+37499123456',
+          '055123456',
+          '37455123456',
         ],
         invalid: [
           '12345',
-          '+37411498855',
-          '+37411498123',
+          '+37403498855',
+          '+37416498123',
           '05614988556',
           '',
           '37456789000',
+          '37486789000',
+          '+37431312345',
+          '+37430312345',
+          '+37460123456',
+          '+37410324123',
+          '+37422298765',
+          '+37431276521',
+          '022698763',
+          '+37492123456',
         ],
       },
       {
@@ -11440,6 +11561,7 @@ describe('Validators', () => {
         'MYR',
         'SGD',
         'USD',
+        'SLE',
       ],
       invalid: [
         '',
@@ -11860,6 +11982,13 @@ describe('Validators', () => {
           '3950IO',
           '3997 GH',
         ],
+        invalid: [
+          '1234',
+          '0603 JV',
+          '5194SA',
+          '9164 SD',
+          '1841SS',
+        ],
       },
       {
         locale: 'NP',
@@ -12827,6 +12956,19 @@ describe('Validators', () => {
         '19640823-32333',
         '1964082332333'],
     });
+    test({
+      validator: 'isTaxID',
+      args: ['uk-UA'],
+      valid: [
+        '3006321856',
+        '3003102490',
+        '2164212906'],
+      invalid: [
+        '2565975632',
+        '256597563287',
+        'КС00123456',
+        '2896235845'],
+    });
     test({
       validator: 'isTaxID',
       valid: [
@@ -12892,6 +13034,7 @@ describe('Validators', () => {
         '+&DxJ=X7-4L8jRCD',
         'etV*p%Nr6w&H%FeF',
         '£3.ndSau_7',
+        'VaLIDWith\\Symb0l',
       ],
       invalid: [
         '',
@@ -12957,6 +13100,8 @@ describe('Validators', () => {
         '2019-02-29', // non-leap year
         '2020-04-31', // invalid date
         '2020/03-15', // mixed delimiter
+        '-2020-04-19',
+        '-2023/05/24',
       ],
     });
     test({
@@ -13558,6 +13703,30 @@ describe('Validators', () => {
       ],
       invalid: ['mh04ad0045', 'invalidlicenseplate', '4578', '', 'GJ054GH4785'],
     });
+    test({
+      validator: 'isLicensePlate',
+      args: ['en-PK'],
+      valid: [
+        'P 1789',
+        'RL745',
+        'RIR 5421',
+        'KHI 201',
+        'LB6571',
+        'LHR-786-23',
+        'AJGB 816-10',
+        'LES 7891 06',
+        'IDS 7871',
+        'LEH 4607 15',
+      ],
+      invalid: [
+        'ajgb 816-10',
+        ' 278-37',
+        'ABZ-27',
+        '',
+        'ABC-123-',
+        'D 272',
+      ],
+    });
   });
   it('should validate VAT numbers', () => {
     test({
@@ -13936,10 +14105,24 @@ describe('Validators', () => {
       validator: 'isVAT',
       args: ['AU'],
       valid: [
+        'AU53004085616',
+        '53004085616',
+        'AU65613309809',
+        '65613309809',
+        'AU34118972998',
+        '34118972998',
+      ],
+      invalid: [
+        'AU65613309808',
+        '65613309808',
+        'AU55613309809',
+        '55613309809',
+        'AU65613319809',
+        '65613319809',
+        'AU34117972998',
+        '34117972998',
         'AU12345678901',
         '12345678901',
-      ],
-      invalid: [
         'AU 12345678901',
         '1234567890',
       ],
@@ -14022,11 +14205,11 @@ describe('Validators', () => {
       validator: 'isVAT',
       args: ['KZ'],
       valid: [
-        'KZ123456789',
-        '123456789',
+        'KZ123456789012',
+        '123456789012',
       ],
       invalid: [
-        'KZ 123456789',
+        'KZ 123456789012',
         '12345678',
       ],
     });