Skip to content

Commit c736b90

Browse files
Ricardo Lopesfranciscocardoso
authored andcommitted
Add NullOrAssert to allow any assert to be nullable
1 parent d916e15 commit c736b90

File tree

5 files changed

+156
-1
lines changed

5 files changed

+156
-1
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ The following set of extra asserts are provided by this package:
4646
- [Iso3166Country](#iso3166country) (requires `isoc`)
4747
- [Json](#json)
4848
- [NotEmpty](#notempty)
49+
- [NullOr](#nullor)
4950
- [NullOrDate](#nullordate)
5051
- [NullOrBoolean](#nullorboolean)
5152
- [NullOrString](#nullorstring)
@@ -196,6 +197,9 @@ Tests if the value is valid json.
196197
### NotEmpty
197198
Tests if the value is not an empty (empty object, empty array, empty string, etc).
198199

200+
### NullOr
201+
Tests if the value is a `null` or validates agains the assert received as an argument.
202+
199203
### NullOrBoolean
200204
Tests if the value is a `null` or `boolean`.
201205

@@ -264,6 +268,13 @@ if (true !== violation) {
264268
console.log('"foo" is not a valid IP. Violation:', violation[0].show());
265269
// => "foo" is not a valid IP. Violation: { assert: 'Ip', value: 'foo' }
266270
}
271+
272+
// Make the validation nullable.
273+
violation = validator.validate(null, is.nullOr(is.ip()));
274+
275+
if (true === violation) {
276+
console.log('null is null or a valid IP'); // => null is null or a valid IP
277+
}
267278
```
268279

269280
## Tests

src/asserts/null-or-assert.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
3+
/**
4+
* Export `NullOrAssert`.
5+
*/
6+
7+
module.exports = function nullOrAssert(assert) {
8+
/**
9+
* Class name.
10+
*/
11+
12+
this.__class__ = 'NullOr';
13+
14+
if (typeof assert !== 'object') {
15+
throw new Error('Assert must be an object.');
16+
}
17+
18+
if (typeof assert.validate !== 'function') {
19+
throw new Error('Assert must have a validate function.');
20+
}
21+
22+
/**
23+
* Nullable assert.
24+
*/
25+
26+
this.assert = assert;
27+
28+
/**
29+
* Validation algorithm.
30+
*/
31+
32+
this.validate = value => {
33+
if (value === null) {
34+
return true;
35+
}
36+
37+
return this.assert.validate(value);
38+
};
39+
40+
return this;
41+
};

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const Ip = require('./asserts/ip-assert.js');
3030
const Iso3166Country = require('./asserts/iso-3166-country-assert.js');
3131
const Json = require('./asserts/json-assert.js');
3232
const NotEmpty = require('./asserts/not-empty-assert.js');
33+
const NullOr = require('./asserts/null-or-assert.js');
3334
const NullOrBoolean = require('./asserts/null-or-boolean-assert.js');
3435
const NullOrDate = require('./asserts/null-or-date-assert.js');
3536
const NullOrString = require('./asserts/null-or-string-assert.js');
@@ -73,6 +74,7 @@ module.exports = {
7374
Iso3166Country,
7475
Json,
7576
NotEmpty,
77+
NullOr,
7678
NullOrBoolean,
7779
NullOrDate,
7880
NullOrString,
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
'use strict';
2+
3+
/**
4+
* Module dependencies.
5+
*/
6+
7+
const { Assert: BaseAssert, Violation } = require('validator.js');
8+
const NullOrAssert = require('../../src/asserts/null-or-assert');
9+
const UuidAssert = require('../../src/asserts/uuid-assert');
10+
11+
/**
12+
* Extend `Assert` with `NullOrAssert`.
13+
*/
14+
15+
const Assert = BaseAssert.extend({
16+
NullOr: NullOrAssert,
17+
Uuid: UuidAssert
18+
});
19+
20+
/**
21+
* Test `NullOrAssert`.
22+
*/
23+
24+
describe('NullOrAssert', () => {
25+
it('should throw an error if the specified assert is missing', () => {
26+
try {
27+
Assert.nullOr('foo').validate();
28+
29+
fail();
30+
} catch (e) {
31+
expect(e).toBeInstanceOf(Error);
32+
expect(e.message).toBe('Assert must be an object.');
33+
}
34+
});
35+
36+
it('should throw an error if the specified assert is not valid', () => {
37+
try {
38+
Assert.nullOr('foo').validate('bar');
39+
40+
fail();
41+
} catch (e) {
42+
expect(e).toBeInstanceOf(Error);
43+
expect(e.message).toBe('Assert must be an object.');
44+
}
45+
});
46+
47+
it('should throw an error if the specified assert has no `validate` function', () => {
48+
try {
49+
Assert.nullOr({}).validate(123);
50+
51+
fail();
52+
} catch (e) {
53+
expect(e).toBeInstanceOf(Error);
54+
expect(e.message).toBe('Assert must have a validate function.');
55+
}
56+
});
57+
58+
it('should throw an error if the specified assert has a `validate` property that is not a function', () => {
59+
try {
60+
Assert.nullOr({ validate: true }).validate(123);
61+
62+
fail();
63+
} catch (e) {
64+
expect(e).toBeInstanceOf(Error);
65+
expect(e.message).toBe('Assert must have a validate function.');
66+
}
67+
});
68+
69+
it('should throw an error if the value is not null and is not valid for the specified assert', () => {
70+
try {
71+
Assert.nullOr(Assert.string()).validate(123);
72+
73+
fail();
74+
} catch (e) {
75+
expect(e).toBeInstanceOf(Violation);
76+
expect(e.show().assert).toBe('IsString');
77+
expect(e.violation.value).toBe('must_be_a_string');
78+
}
79+
});
80+
81+
it('should include the arguments of the specified assert', () => {
82+
try {
83+
Assert.nullOr(Assert.uuid(4)).validate('foobar');
84+
85+
fail();
86+
} catch (e) {
87+
expect(e).toBeInstanceOf(Object);
88+
expect(e.show().assert).toBe('Uuid');
89+
expect(e.violation.version).toBe(4);
90+
}
91+
});
92+
93+
it('should accept a null value', () => {
94+
Assert.nullOr(Assert.string()).validate(null);
95+
});
96+
97+
it('should accept a value that is valid for the specified assert', () => {
98+
Assert.nullOr(Assert.string()).validate('foobar');
99+
});
100+
});

test/index.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('validator.js-asserts', () => {
1414
it('should export all asserts', () => {
1515
const assertNames = Object.keys(asserts);
1616

17-
expect(assertNames).toHaveLength(37);
17+
expect(assertNames).toHaveLength(38);
1818
expect(assertNames).toEqual(
1919
expect.arrayContaining([
2020
'AbaRoutingNumber',
@@ -43,6 +43,7 @@ describe('validator.js-asserts', () => {
4343
'Iso3166Country',
4444
'Json',
4545
'NotEmpty',
46+
'NullOr',
4647
'NullOrBoolean',
4748
'NullOrDate',
4849
'NullOrString',

0 commit comments

Comments
 (0)