@thirstie/thirstievalidators 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +24 -0
- package/dist/bundle.cjs +66 -0
- package/dist/bundle.iife.js +1 -0
- package/dist/bundle.mjs +64 -0
- package/package.json +34 -0
- package/rollup.config.mjs +23 -0
- package/src/index.js +35 -0
- package/src/passwordcheck.js +32 -0
- package/tests/func/validators.func.test.js +3 -0
- package/tests/int/validators.int.test.js +3 -0
- package/tests/unit/passwordcheck.unit.test.js +23 -0
- package/tests/unit/validators.email.unit.test.js +31 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [0.0.6](https://github.com/ThirstieAdmin/thirstiejs-monorepo/compare/@thirstie/thirstievalidators@0.0.4...@thirstie/thirstievalidators@0.0.6) (2024-06-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @thirstie/thirstievalidators
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [0.0.5](https://github.com/ThirstieAdmin/thirstiejs-monorepo/compare/@thirstie/thirstievalidators@0.0.4...@thirstie/thirstievalidators@0.0.5) (2024-06-24)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @thirstie/thirstievalidators
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Changelog
|
|
23
|
+
|
|
24
|
+
All notable changes to this project will be documented in this file.
|
|
25
|
+
|
|
26
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
27
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
28
|
+
|
|
29
|
+
## Unreleased
|
|
30
|
+
|
|
31
|
+
- n/a
|
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# validators
|
|
2
|
+
|
|
3
|
+
TODO:
|
|
4
|
+
- review https://github.com/validatorjs/validator.js
|
|
5
|
+
- see https://github.com/jameslk/awesome-falsehoods on why it's better to use a standard library
|
|
6
|
+
- probably will use our own email validator
|
|
7
|
+
- others are probably okay?
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# `passwordcheck`
|
|
11
|
+
|
|
12
|
+
> TODO: description
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
const passwordcheck = require('passwordcheck');
|
|
18
|
+
|
|
19
|
+
const pwStrength = passwordcheck('password');
|
|
20
|
+
console.log(pwStrength);
|
|
21
|
+
> 0 # Too Weak
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
|
package/dist/bundle.cjs
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const BREAKPOINTS = [ 78.0, 52, 0 ];
|
|
4
|
+
const PWSTRENGTH_LABELS = [ 'weak', 'acceptable', 'strong' ];
|
|
5
|
+
|
|
6
|
+
function passwordcheck (pw) {
|
|
7
|
+
const pwEntropy = blindEntropy(pw);
|
|
8
|
+
const strength = entropyMeter(pwEntropy);
|
|
9
|
+
return {
|
|
10
|
+
strength,
|
|
11
|
+
label: PWSTRENGTH_LABELS[strength]
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const blindEntropy = (pw) => {
|
|
16
|
+
const numberPermutations = /.*[0-9].*/.test(pw) ? 10 : 0;
|
|
17
|
+
const lowercasePermutations = /.*[a-z].*/.test(pw) ? 26 : 0;
|
|
18
|
+
const uppercasePermutations = /.*[A-Z].*/.test(pw) ? 26 : 0;
|
|
19
|
+
const punctuationPermutations = /.*[^a-zA-Z0-9].*/.test(pw) ? 33 : 0;
|
|
20
|
+
|
|
21
|
+
const permutations = numberPermutations + lowercasePermutations + uppercasePermutations + punctuationPermutations;
|
|
22
|
+
const pwLength = pw.length;
|
|
23
|
+
|
|
24
|
+
return Math.log2(permutations ** pwLength);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const entropyMeter = (pwEntropy) => {
|
|
28
|
+
const ndx = BREAKPOINTS.findIndex(e => pwEntropy >= e);
|
|
29
|
+
// 0 = Too Weak; 1 == Acceptable; 2 = Strong
|
|
30
|
+
const strength = BREAKPOINTS.length - 1 - ndx;
|
|
31
|
+
return strength;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// see: https://github.com/ThirstieAdmin/archived-repos/tree/master/thirstie-templates/react-cookbook/src/utils
|
|
35
|
+
// TODO: research using https://www.npmjs.com/package/validator
|
|
36
|
+
const thirstieValidators = {
|
|
37
|
+
email: (value, options = null) => {
|
|
38
|
+
const emailRegex = /^(?![.!#$%&'*+/=?^_`{|}~-])(?!.*\.{2})[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]{1,64}@[a-zA-Z0-9]{1,255}\.[a-zA-Z]{2,}$/;
|
|
39
|
+
// TODO: add domain checks
|
|
40
|
+
return emailRegex.test(value);
|
|
41
|
+
},
|
|
42
|
+
phoneNumber: (value, options = null) => {
|
|
43
|
+
const phoneRegex = /^((\+1|1)?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/;
|
|
44
|
+
if (value) {
|
|
45
|
+
const testValue = String(value).replace(/[^0-9]/g, '');
|
|
46
|
+
return phoneRegex.test(testValue);
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
},
|
|
50
|
+
postalCode: (value, options = null) => {
|
|
51
|
+
const country = options.countryCode ? options.countryCode.toLowerCase() : 'en-us';
|
|
52
|
+
const regex = {
|
|
53
|
+
'en-us': /^\d{5}$/,
|
|
54
|
+
'en-ca': /^[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d$/
|
|
55
|
+
}[country];
|
|
56
|
+
if (regex) {
|
|
57
|
+
return regex.test(value);
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
},
|
|
61
|
+
stateProvinceCode: (value, options = null) => { throw new Error('Not implemented'); },
|
|
62
|
+
currencyValue: (value, options = null) => { throw new Error('Not implemented'); },
|
|
63
|
+
passwordStrength: (value, options = null) => { return passwordcheck(value); }
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
module.exports = thirstieValidators;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var thirstievalidators=function(){"use strict";const t=[78,52,0],e=["weak","acceptable","strong"];const n=t=>{const e=(/.*[0-9].*/.test(t)?10:0)+(/.*[a-z].*/.test(t)?26:0)+(/.*[A-Z].*/.test(t)?26:0)+(/.*[^a-zA-Z0-9].*/.test(t)?33:0),n=t.length;return Math.log2(e**n)},r=e=>{const n=t.findIndex((t=>e>=t));return t.length-1-n};return{email:(t,e=null)=>/^(?![.!#$%&'*+/=?^_`{|}~-])(?!.*\.{2})[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]{1,64}@[a-zA-Z0-9]{1,255}\.[a-zA-Z]{2,}$/.test(t),phoneNumber:(t,e=null)=>{const n=/^((\+1|1)?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/;if(t){const e=String(t).replace(/[^0-9]/g,"");return n.test(e)}return!1},postalCode:(t,e=null)=>{const n={"en-us":/^\d{5}$/,"en-ca":/^[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d$/}[e.countryCode?e.countryCode.toLowerCase():"en-us"];return!!n&&n.test(t)},stateProvinceCode:(t,e=null)=>{throw new Error("Not implemented")},currencyValue:(t,e=null)=>{throw new Error("Not implemented")},passwordStrength:(t,o=null)=>function(t){const o=n(t),s=r(o);return{strength:s,label:e[s]}}(t)}}();
|
package/dist/bundle.mjs
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const BREAKPOINTS = [ 78.0, 52, 0 ];
|
|
2
|
+
const PWSTRENGTH_LABELS = [ 'weak', 'acceptable', 'strong' ];
|
|
3
|
+
|
|
4
|
+
function passwordcheck (pw) {
|
|
5
|
+
const pwEntropy = blindEntropy(pw);
|
|
6
|
+
const strength = entropyMeter(pwEntropy);
|
|
7
|
+
return {
|
|
8
|
+
strength,
|
|
9
|
+
label: PWSTRENGTH_LABELS[strength]
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const blindEntropy = (pw) => {
|
|
14
|
+
const numberPermutations = /.*[0-9].*/.test(pw) ? 10 : 0;
|
|
15
|
+
const lowercasePermutations = /.*[a-z].*/.test(pw) ? 26 : 0;
|
|
16
|
+
const uppercasePermutations = /.*[A-Z].*/.test(pw) ? 26 : 0;
|
|
17
|
+
const punctuationPermutations = /.*[^a-zA-Z0-9].*/.test(pw) ? 33 : 0;
|
|
18
|
+
|
|
19
|
+
const permutations = numberPermutations + lowercasePermutations + uppercasePermutations + punctuationPermutations;
|
|
20
|
+
const pwLength = pw.length;
|
|
21
|
+
|
|
22
|
+
return Math.log2(permutations ** pwLength);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const entropyMeter = (pwEntropy) => {
|
|
26
|
+
const ndx = BREAKPOINTS.findIndex(e => pwEntropy >= e);
|
|
27
|
+
// 0 = Too Weak; 1 == Acceptable; 2 = Strong
|
|
28
|
+
const strength = BREAKPOINTS.length - 1 - ndx;
|
|
29
|
+
return strength;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// see: https://github.com/ThirstieAdmin/archived-repos/tree/master/thirstie-templates/react-cookbook/src/utils
|
|
33
|
+
// TODO: research using https://www.npmjs.com/package/validator
|
|
34
|
+
const thirstieValidators = {
|
|
35
|
+
email: (value, options = null) => {
|
|
36
|
+
const emailRegex = /^(?![.!#$%&'*+/=?^_`{|}~-])(?!.*\.{2})[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]{1,64}@[a-zA-Z0-9]{1,255}\.[a-zA-Z]{2,}$/;
|
|
37
|
+
// TODO: add domain checks
|
|
38
|
+
return emailRegex.test(value);
|
|
39
|
+
},
|
|
40
|
+
phoneNumber: (value, options = null) => {
|
|
41
|
+
const phoneRegex = /^((\+1|1)?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/;
|
|
42
|
+
if (value) {
|
|
43
|
+
const testValue = String(value).replace(/[^0-9]/g, '');
|
|
44
|
+
return phoneRegex.test(testValue);
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
},
|
|
48
|
+
postalCode: (value, options = null) => {
|
|
49
|
+
const country = options.countryCode ? options.countryCode.toLowerCase() : 'en-us';
|
|
50
|
+
const regex = {
|
|
51
|
+
'en-us': /^\d{5}$/,
|
|
52
|
+
'en-ca': /^[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d$/
|
|
53
|
+
}[country];
|
|
54
|
+
if (regex) {
|
|
55
|
+
return regex.test(value);
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
},
|
|
59
|
+
stateProvinceCode: (value, options = null) => { throw new Error('Not implemented'); },
|
|
60
|
+
currencyValue: (value, options = null) => { throw new Error('Not implemented'); },
|
|
61
|
+
passwordStrength: (value, options = null) => { return passwordcheck(value); }
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { thirstieValidators as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thirstie/thirstievalidators",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "A collection of data validators used by Thirstiejs modules",
|
|
5
|
+
"author": "Thirstie, Inc. <technology@thirstie.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"source": "src/index.js",
|
|
9
|
+
"main": "dist/bundle.cjs",
|
|
10
|
+
"module": "dist/bundle.mjs",
|
|
11
|
+
"exports": {
|
|
12
|
+
"require": "./dist/bundle.cjs",
|
|
13
|
+
"import": "./dist/bundle.mjs"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "rollup -c -w",
|
|
17
|
+
"build": "rollup -c",
|
|
18
|
+
"lint": "eslint src/",
|
|
19
|
+
"test:int": "node --experimental-vm-modules ../../node_modules/.bin/jest int --no-cache",
|
|
20
|
+
"test:func": "node --experimental-vm-modules ../../node_modules/.bin/jest func --no-cache",
|
|
21
|
+
"test:coverage": "node --experimental-vm-modules ../../node_modules/.bin/jest unit --coverage",
|
|
22
|
+
"test": "concurrently \"npm run lint\" \"npm run test:coverage\"",
|
|
23
|
+
"test:watch": "node --experimental-vm-modules ../../node_modules/.bin/jest unit --watch"
|
|
24
|
+
},
|
|
25
|
+
"jest": {
|
|
26
|
+
"moduleFileExtensions": [
|
|
27
|
+
"js",
|
|
28
|
+
"json"
|
|
29
|
+
],
|
|
30
|
+
"testEnvironment": "jsdom",
|
|
31
|
+
"transform": {}
|
|
32
|
+
},
|
|
33
|
+
"gitHead": "b7400621954f917a80a9a530ea89cc2d41aa6373"
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
2
|
+
import terser from '@rollup/plugin-terser';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
input: 'src/index.js',
|
|
6
|
+
output: [
|
|
7
|
+
{
|
|
8
|
+
file: 'dist/bundle.mjs',
|
|
9
|
+
format: 'esm'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
file: 'dist/bundle.cjs',
|
|
13
|
+
format: 'cjs'
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
file: 'dist/bundle.iife.js',
|
|
17
|
+
format: 'iife',
|
|
18
|
+
name: 'thirstievalidators',
|
|
19
|
+
plugins: [ terser() ]
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
plugins: [ resolve() ]
|
|
23
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import passwordcheck from './passwordcheck';
|
|
2
|
+
|
|
3
|
+
// see: https://github.com/ThirstieAdmin/archived-repos/tree/master/thirstie-templates/react-cookbook/src/utils
|
|
4
|
+
// TODO: research using https://www.npmjs.com/package/validator
|
|
5
|
+
const thirstieValidators = {
|
|
6
|
+
email: (value, options = null) => {
|
|
7
|
+
const emailRegex = /^(?![.!#$%&'*+/=?^_`{|}~-])(?!.*\.{2})[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]{1,64}@[a-zA-Z0-9]{1,255}\.[a-zA-Z]{2,}$/;
|
|
8
|
+
// TODO: add domain checks
|
|
9
|
+
return emailRegex.test(value);
|
|
10
|
+
},
|
|
11
|
+
phoneNumber: (value, options = null) => {
|
|
12
|
+
const phoneRegex = /^((\+1|1)?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/;
|
|
13
|
+
if (value) {
|
|
14
|
+
const testValue = String(value).replace(/[^0-9]/g, '');
|
|
15
|
+
return phoneRegex.test(testValue);
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
},
|
|
19
|
+
postalCode: (value, options = null) => {
|
|
20
|
+
const country = options.countryCode ? options.countryCode.toLowerCase() : 'en-us';
|
|
21
|
+
const regex = {
|
|
22
|
+
'en-us': /^\d{5}$/,
|
|
23
|
+
'en-ca': /^[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d$/
|
|
24
|
+
}[country];
|
|
25
|
+
if (regex) {
|
|
26
|
+
return regex.test(value);
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
},
|
|
30
|
+
stateProvinceCode: (value, options = null) => { throw new Error('Not implemented'); },
|
|
31
|
+
currencyValue: (value, options = null) => { throw new Error('Not implemented'); },
|
|
32
|
+
passwordStrength: (value, options = null) => { return passwordcheck(value); }
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default thirstieValidators;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const BREAKPOINTS = [ 78.0, 52, 0 ];
|
|
2
|
+
const PWSTRENGTH_LABELS = [ 'weak', 'acceptable', 'strong' ];
|
|
3
|
+
|
|
4
|
+
function passwordcheck (pw) {
|
|
5
|
+
const pwEntropy = blindEntropy(pw);
|
|
6
|
+
const strength = entropyMeter(pwEntropy);
|
|
7
|
+
return {
|
|
8
|
+
strength,
|
|
9
|
+
label: PWSTRENGTH_LABELS[strength]
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const blindEntropy = (pw) => {
|
|
14
|
+
const numberPermutations = /.*[0-9].*/.test(pw) ? 10 : 0;
|
|
15
|
+
const lowercasePermutations = /.*[a-z].*/.test(pw) ? 26 : 0;
|
|
16
|
+
const uppercasePermutations = /.*[A-Z].*/.test(pw) ? 26 : 0;
|
|
17
|
+
const punctuationPermutations = /.*[^a-zA-Z0-9].*/.test(pw) ? 33 : 0;
|
|
18
|
+
|
|
19
|
+
const permutations = numberPermutations + lowercasePermutations + uppercasePermutations + punctuationPermutations;
|
|
20
|
+
const pwLength = pw.length;
|
|
21
|
+
|
|
22
|
+
return Math.log2(permutations ** pwLength);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const entropyMeter = (pwEntropy) => {
|
|
26
|
+
const ndx = BREAKPOINTS.findIndex(e => pwEntropy >= e);
|
|
27
|
+
// 0 = Too Weak; 1 == Acceptable; 2 = Strong
|
|
28
|
+
const strength = BREAKPOINTS.length - 1 - ndx;
|
|
29
|
+
return strength;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default passwordcheck;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import thirstieValidators from '../../src/index.js';
|
|
2
|
+
|
|
3
|
+
describe('passwordcheck', () => {
|
|
4
|
+
it('should return password strength', () => {
|
|
5
|
+
const fixtures = [
|
|
6
|
+
{
|
|
7
|
+
testValue: '1235',
|
|
8
|
+
strength: 0,
|
|
9
|
+
label: 'weak'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
testValue: 'Super-Str0ng-Long-Secret',
|
|
13
|
+
strength: 2,
|
|
14
|
+
label: 'strong'
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
fixtures.forEach((fixture) => {
|
|
18
|
+
const pwStrength = thirstieValidators.passwordStrength(fixture.testValue);
|
|
19
|
+
expect(pwStrength.strength).toBe(fixture.strength);
|
|
20
|
+
expect(pwStrength.label).toBe(fixture.label);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import thirstieValidators from '../../src/index.js';
|
|
2
|
+
|
|
3
|
+
describe('email validation', () => {
|
|
4
|
+
/* see:
|
|
5
|
+
* https://github.com/jameslk/awesome-falsehoods
|
|
6
|
+
* https://stackoverflow.com/questions/3844431/are-email-addresses-allowed-to-contain-non-alphanumeric-characters
|
|
7
|
+
* https://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx/
|
|
8
|
+
*/
|
|
9
|
+
it('should return true for valid emails', () => {
|
|
10
|
+
const fixtures = [
|
|
11
|
+
'localpart@domainname.tld',
|
|
12
|
+
'localpart+other@domainname.faketld',
|
|
13
|
+
'first.last@example.com'
|
|
14
|
+
];
|
|
15
|
+
fixtures.forEach((fixture) => {
|
|
16
|
+
const validationCheck = thirstieValidators.email(fixture);
|
|
17
|
+
expect(validationCheck).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
it('should return false for invalid emails', () => {
|
|
21
|
+
const fixtures = [
|
|
22
|
+
'localpart@domainname',
|
|
23
|
+
'first.läst.unicode@domainname.faketld',
|
|
24
|
+
'first.last@example.c'
|
|
25
|
+
];
|
|
26
|
+
fixtures.forEach((fixture) => {
|
|
27
|
+
const validationCheck = thirstieValidators.email(fixture);
|
|
28
|
+
expect(validationCheck).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|