Repository: validatorjs/validator.js
Pull request #1865 (2021-11-10 13:54:04)

feat(isMACAddress): add EUI-64 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 --->
This PR adds support for validating against EUI-64 as well as the previous EUI-48. This corresponds with the [macaddr8 type](https://www.postgresql.org/docs/current/datatype-net-types.html#DATATYPE-MACADDR8) in postgres.

## Checklist

- [X] PR contains only changes related; no stray files, etc.
- [X] README updated (where applicable)
- [X] Tests written (where applicable)


codecov[bot]: # [Codecov](https://codecov.io/gh/validatorjs/validator.js/pull/1865?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs) Report
> Merging [#1865](https://codecov.io/gh/validatorjs/validator.js/pull/1865?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs) (6b987b4) into [master](https://codecov.io/gh/validatorjs/validator.js/commit/47ee5ad64cf5c684c841b59110af4e221b74945c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs) (47ee5ad) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/validatorjs/validator.js/pull/1865/graphs/tree.svg?width=650&height=150&src=pr&token=YzR3kbN1m2&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs)](https://codecov.io/gh/validatorjs/validator.js/pull/1865?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs)

```diff
@@            Coverage Diff            @@
##            master     #1865   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          102       102           
  Lines         2059      2072   +13     
  Branches       464       472    +8     
=========================================
+ Hits          2059      2072   +13     
```


| [Impacted Files](https://codecov.io/gh/validatorjs/validator.js/pull/1865?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs) | Coverage Δ | |
|---|---|---|
| [src/lib/isMACAddress.js](https://codecov.io/gh/validatorjs/validator.js/pull/1865/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs#diff-c3JjL2xpYi9pc01BQ0FkZHJlc3MuanM=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/validatorjs/validator.js/pull/1865?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/validatorjs/validator.js/pull/1865?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs). Last update [47ee5ad...6b987b4](https://codecov.io/gh/validatorjs/validator.js/pull/1865?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=validatorjs).

WikiRik: To be honest, I do not really know. I would be happy to refer to it as MacAddr6 and 8. Do you think I should refactor it to numberOfBits? Or some other suggestion?
tux-tn: @WikiRik Looks like IEEE and IETF are using `EUI-48` and `EUI-64` terminology ([RFC7043](https://datatracker.ietf.org/doc/html/rfc7043) as an example). I suggest we stick to that, we can add aliases later if community is complaining or suggesting another name. 

Patch:
diff --git a/README.md b/README.md
index 2cf6505..0d2ed2b 100644
--- a/README.md
+++ b/README.md
@@ -129,7 +129,7 @@ Validator                               | Description
 **isIPRange(str [, version])**          | check if the string is an IP Range (version 4 or 6).
 **isISBN(str [, version])**             | check if the string is an ISBN (version 10 or 13).
 **isISIN(str)**                         | check if the string is an [ISIN][ISIN] (stock/security identifier).
-**isISO8601(str)**                      | check if the string is a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date. <br/>`options` is an object which defaults to `{ strict: false, strictSeparator: false }`. If `strict` is true, date strings with invalid dates like `2009-02-29` will be invalid. If `strictSeparator` is true, date strings with date and time separated by anything other than a T will be invalid.
+**isISO8601(str [, options])**          | check if the string is a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date. <br/>`options` is an object which defaults to `{ strict: false, strictSeparator: false }`. If `strict` is true, date strings with invalid dates like `2009-02-29` will be invalid. If `strictSeparator` is true, date strings with date and time separated by anything other than a T will be invalid.
 **isISO31661Alpha2(str)**               | check 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(str)**               | check 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.
 **isISO4217(str)**                      | check if the string is a valid [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) officially assigned currency code.
@@ -142,11 +142,11 @@ Validator                               | Description
 **isLicensePlate(str [, locale])**     | check if string matches the format of a country's license plate.<br/><br/>(locale is one of `['cs-CZ', 'de-DE', 'de-LI', 'fi-FI', pt-PT', 'sq-AL', 'pt-BR']` or `any`)
 **isLocale(str)**                       | check if the string is a locale
 **isLowercase(str)**                    | check if the string is lowercase.
-**isMACAddress(str)**                   | 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'.
+**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](https://en.wikipedia.org/wiki/Magnet_URI_scheme).
 **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](https://en.wikipedia.org/wiki/Media_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-IQ', ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SY', 'ar-TN', 'az-AZ', 'az-LY', 'az-LB', 'bs-BA', 'be-BY', 'bg-BG', 'bn-BD', 'ca-AD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'de-CH', 'de-LU', 'dv-MV', 'el-GR', 'en-AU', 'en-BM', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-MO', 'en-IE', 'en-IN', 'en-KE', 'en-KI', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-PH', 'en-RW', 'en-SG', 'en-SL', 'en-UG', 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-HN', 'es-PE', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', ''mz-MZ', nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'pt-AO', 'ro-RO', 'ru-RU', 'si-LK' 'sl-SI', 'sk-SK', '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', 'dz-BT']` 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`.
+**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-IQ', ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SY', 'ar-TN', 'az-AZ', 'az-LY', 'az-LB', 'bs-BA', 'be-BY', 'bg-BG', 'bn-BD', 'ca-AD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'de-CH', 'de-LU', 'dv-MV', 'el-GR', 'en-AU', 'en-BM', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-MO', 'en-IE', 'en-IN', 'en-KE', 'en-KI', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-PH', 'en-RW', 'en-SG', 'en-SL', 'en-UG', 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-HN', 'es-PE', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', 'my-MM', 'mz-MZ', nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'pt-AO', 'ro-RO', 'ru-RU', 'si-LK' 'sl-SI', 'sk-SK', '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', 'dz-BT']` 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`.
 **isMongoId(str)**                      | check if the string is a valid hex-encoded representation of a [MongoDB ObjectId][mongoid].
 **isMultibyte(str)**                    | check if the string contains one or more multibyte chars.
 **isNumeric(str [, options])**                      | check if the string contains only numbers.<br/><br/>`options` is an object which defaults to `{no_symbols: false}` it also has locale as an option. If `no_symbols` is true, the validator will reject numeric strings that feature a symbol (e.g. `+`, `-`, or `.`).<br/><br/>`locale` determine the decimal separator and 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', 'cs-CZ', 'da-DK', 'de-DE', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fr-FR', 'fr-CA', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`.
diff --git a/src/lib/isMACAddress.js b/src/lib/isMACAddress.js
index 8ffc8c2..d87cd4a 100644
--- a/src/lib/isMACAddress.js
+++ b/src/lib/isMACAddress.js
@@ -1,18 +1,34 @@
 import assertString from './util/assertString';
 
-const macAddress = /^(?:[0-9a-fA-F]{2}([-:\s]))([0-9a-fA-F]{2}\1){4}([0-9a-fA-F]{2})$/;
-const macAddressNoSeparators = /^([0-9a-fA-F]){12}$/;
-const macAddressWithDots = /^([0-9a-fA-F]{4}\.){2}([0-9a-fA-F]{4})$/;
+const macAddress48 = /^(?:[0-9a-fA-F]{2}([-:\s]))([0-9a-fA-F]{2}\1){4}([0-9a-fA-F]{2})$/;
+const macAddress48NoSeparators = /^([0-9a-fA-F]){12}$/;
+const macAddress48WithDots = /^([0-9a-fA-F]{4}\.){2}([0-9a-fA-F]{4})$/;
+const macAddress64 = /^(?:[0-9a-fA-F]{2}([-:\s]))([0-9a-fA-F]{2}\1){6}([0-9a-fA-F]{2})$/;
+const macAddress64NoSeparators = /^([0-9a-fA-F]){16}$/;
+const macAddress64WithDots = /^([0-9a-fA-F]{4}\.){3}([0-9a-fA-F]{4})$/;
 
 export default function isMACAddress(str, options) {
   assertString(str);
+  if (options?.eui) {
+    options.eui = String(options.eui);
+  }
   /**
    * @deprecated `no_colons` TODO: remove it in the next major
   */
-  if (options && (options.no_colons || options.no_separators)) {
-    return macAddressNoSeparators.test(str);
+  if (options?.no_colons || options?.no_separators) {
+    if (options.eui === '48') {
+      return macAddress48NoSeparators.test(str);
+    }
+    if (options.eui === '64') {
+      return macAddress64NoSeparators.test(str);
+    }
+    return macAddress48NoSeparators.test(str) || macAddress64NoSeparators.test(str);
   }
-
-  return macAddress.test(str)
-    || macAddressWithDots.test(str);
+  if (options?.eui === '48') {
+    return macAddress48.test(str) || macAddress48WithDots.test(str);
+  }
+  if (options?.eui === '64') {
+    return macAddress64.test(str) || macAddress64WithDots.test(str);
+  }
+  return isMACAddress(str, { eui: '48' }) || isMACAddress(str, { eui: '64' });
 }
diff --git a/src/lib/isMobilePhone.js b/src/lib/isMobilePhone.js
index c70310e..575415e 100644
--- a/src/lib/isMobilePhone.js
+++ b/src/lib/isMobilePhone.js
@@ -26,7 +26,7 @@ const phones = {
   'ca-AD': /^(\+376)?[346]\d{5}$/,
   'cs-CZ': /^(\+?420)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/,
   'da-DK': /^(\+?45)?\s?\d{2}\s?\d{2}\s?\d{2}\s?\d{2}$/,
-  'de-DE': /^((\+49|0)[1|3])([0|5][0-45-9]\d|6([23]|0\d?)|7([0-57-9]|6\d))\d{7,9}$/,
+  'de-DE': /^((\+49|0)1)(5[0-25-9]\d|6([23]|0\d?)|7([0-57-9]|6\d))\d{7,9}$/,
   'de-AT': /^(\+43|0)\d{1,4}\d{3,12}$/,
   'de-CH': /^(\+41|0)([1-9])\d{1,9}$/,
   'de-LU': /^(\+352)?((6\d1)\d{6})$/,
@@ -103,6 +103,7 @@ const phones = {
   'ko-KR': /^((\+?82)[ \-]?)?0?1([0|1|6|7|8|9]{1})[ \-]?\d{3,4}[ \-]?\d{4}$/,
   'lt-LT': /^(\+370|8)\d{8}$/,
   'lv-LV': /^(\+?371)2\d{7}$/,
+  'my-MM': /^(\+?959|09|9)(2[5-7]|3[1-2]|4[0-5]|6[6-9]|7[5-9]|9[6-9])[0-9]{7}$/,
   'ms-MY': /^(\+?6?01){1}(([0145]{1}(\-|\s)?\d{7,8})|([236789]{1}(\s|\-)?\d{7}))$/,
   'mz-MZ': /^(\+?258)?8[234567]\d{7}$/,
   'nb-NO': /^(\+?47)?[49]\d{7}$/,


Test patch:
diff --git a/test/validators.js b/test/validators.js
index a4e0029..76ec3d9 100644
--- a/test/validators.js
+++ b/test/validators.js
@@ -810,6 +810,14 @@ describe('Validators', () => {
         '01 02 03 04 05 ab',
         '01-02-03-04-05-ab',
         '0102.0304.05ab',
+        'ab:ab:ab:ab:ab:ab:ab:ab',
+        'FF:FF:FF:FF:FF:FF:FF:FF',
+        '01:02:03:04:05:06:07:ab',
+        '01:AB:03:04:05:06:07:08',
+        'A9 C5 D4 9F EB D3 B6 65',
+        '01 02 03 04 05 06 07 ab',
+        '01-02-03-04-05-06-07-ab',
+        '0102.0304.0506.07ab',
       ],
       invalid: [
         'abc',
@@ -822,6 +830,67 @@ describe('Validators', () => {
         '01-02 03:04 05 ab',
         '0102.03:04.05ab',
         '900f/dffs/sdea',
+        '01:02:03:04:05:06:07',
+        '01:02:03:04:05:06:07:z0',
+        '01:02:03:04:05:06::ab',
+        '1:2:3:4:5:6:7:8',
+        'AB:CD:EF:GH:01:02:03:04',
+        'A9C5 D4 9F EB D3 B6 65',
+        '01-02 03:04 05 06 07 ab',
+        '0102.03:04.0506.07ab',
+        '900f/dffs/sdea/54gh',
+      ],
+    });
+    test({
+      validator: 'isMACAddress',
+      args: [{
+        eui: '48',
+      }],
+      valid: [
+        'ab:ab:ab:ab:ab:ab',
+        'FF:FF:FF:FF:FF:FF',
+        '01:02:03:04:05:ab',
+        '01:AB:03:04:05:06',
+        'A9 C5 D4 9F EB D3',
+        '01 02 03 04 05 ab',
+        '01-02-03-04-05-ab',
+        '0102.0304.05ab',
+      ],
+      invalid: [
+        'ab:ab:ab:ab:ab:ab:ab:ab',
+        'FF:FF:FF:FF:FF:FF:FF:FF',
+        '01:02:03:04:05:06:07:ab',
+        '01:AB:03:04:05:06:07:08',
+        'A9 C5 D4 9F EB D3 B6 65',
+        '01 02 03 04 05 06 07 ab',
+        '01-02-03-04-05-06-07-ab',
+        '0102.0304.0506.07ab',
+      ],
+    });
+    test({
+      validator: 'isMACAddress',
+      args: [{
+        eui: '64',
+      }],
+      valid: [
+        'ab:ab:ab:ab:ab:ab:ab:ab',
+        'FF:FF:FF:FF:FF:FF:FF:FF',
+        '01:02:03:04:05:06:07:ab',
+        '01:AB:03:04:05:06:07:08',
+        'A9 C5 D4 9F EB D3 B6 65',
+        '01 02 03 04 05 06 07 ab',
+        '01-02-03-04-05-06-07-ab',
+        '0102.0304.0506.07ab',
+      ],
+      invalid: [
+        'ab:ab:ab:ab:ab:ab',
+        'FF:FF:FF:FF:FF:FF',
+        '01:02:03:04:05:ab',
+        '01:AB:03:04:05:06',
+        'A9 C5 D4 9F EB D3',
+        '01 02 03 04 05 ab',
+        '01-02-03-04-05-ab',
+        '0102.0304.05ab',
       ],
     });
   });
@@ -837,6 +906,10 @@ describe('Validators', () => {
         'FFFFFFFFFFFF',
         '0102030405ab',
         '01AB03040506',
+        'abababababababab',
+        'FFFFFFFFFFFFFFFF',
+        '01020304050607ab',
+        '01AB030405060708',
       ],
       invalid: [
         'abc',
@@ -852,6 +925,56 @@ describe('Validators', () => {
         '01020304ab',
         '123456',
         'ABCDEFGH0102',
+        '01:02:03:04:05:06:07',
+        '01:02:03:04:05:06::ab',
+        '1:2:3:4:5:6:7:8',
+        'AB:CD:EF:GH:01:02:03:04',
+        'ab:ab:ab:ab:ab:ab:ab:ab',
+        'FF:FF:FF:FF:FF:FF:FF:FF',
+        '01:02:03:04:05:06:07:ab',
+        '01:AB:03:04:05:06:07:08',
+        '01020304050607',
+        '010203040506ab',
+        '12345678',
+        'ABCDEFGH01020304',
+      ],
+    });
+    test({
+      validator: 'isMACAddress',
+      args: [{
+        no_separators: true,
+        eui: '48',
+      }],
+      valid: [
+        'abababababab',
+        'FFFFFFFFFFFF',
+        '0102030405ab',
+        '01AB03040506',
+      ],
+      invalid: [
+        'abababababababab',
+        'FFFFFFFFFFFFFFFF',
+        '01020304050607ab',
+        '01AB030405060708',
+      ],
+    });
+    test({
+      validator: 'isMACAddress',
+      args: [{
+        no_separators: true,
+        eui: '64',
+      }],
+      valid: [
+        'abababababababab',
+        'FFFFFFFFFFFFFFFF',
+        '01020304050607ab',
+        '01AB030405060708',
+      ],
+      invalid: [
+        'abababababab',
+        'FFFFFFFFFFFF',
+        '0102030405ab',
+        '01AB03040506',
       ],
     });
   });
@@ -6207,7 +6330,6 @@ describe('Validators', () => {
         locale: 'de-DE',
         valid: [
           '+4915123456789',
-          '+4930405044550',
           '015123456789',
           '015123456789',
           '015623456789',
@@ -6218,10 +6340,9 @@ describe('Validators', () => {
           '01631234567',
           '01701234567',
           '017612345678',
-          '015345678910',
-          '015412345678',
         ],
         invalid: [
+          '+4930405044550',
           '34412345678',
           '14412345678',
           '16212345678',
@@ -6230,6 +6351,8 @@ describe('Validators', () => {
           '17012345678',
           '+4912345678910',
           '+49015123456789',
+          '015345678910',
+          '015412345678',
         ],
       },
       {
@@ -8441,6 +8564,36 @@ describe('Validators', () => {
           'NotANumber',
         ],
       },
+      {
+        locale: 'my-MM',
+        valid: [
+          '+959750202595',
+          '09750202595',
+          '9750202595',
+          '+959260000966',
+          '09256000323',
+          '09276000323',
+          '09426000323',
+          '09456000323',
+          '09761234567',
+          '09791234567',
+          '09961234567',
+          '09771234567',
+          '09660000234',
+        ],
+        invalid: [
+          '59750202595',
+          '+9597502025',
+          '08943234524',
+          '09950000966',
+          '959240000966',
+          '09246000323',
+          '09466000323',
+          '09951234567',
+          '09801234567',
+          '09650000234',
+        ],
+      },
       {
         locale: 'en-PK',
         valid: [