Skip to content

Commit 09f2838

Browse files
committed
test(validator): implements tests for main validator types
1 parent 3f2eea8 commit 09f2838

17 files changed

Lines changed: 1840 additions & 0 deletions
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const { test } = require('node:test');
6+
const { Schema } = require('node:validator');
7+
8+
test('minItems - passes at boundary', () => {
9+
const schema = new Schema({ type: 'array', minItems: 2 });
10+
assert.strictEqual(schema.validate([1, 2]).valid, true);
11+
});
12+
13+
test('minItems - fails below', () => {
14+
const schema = new Schema({ type: 'array', minItems: 2 });
15+
const result = schema.validate([1]);
16+
assert.strictEqual(result.valid, false);
17+
assert.strictEqual(result.errors[0].code, 'ARRAY_TOO_SHORT');
18+
});
19+
20+
test('maxItems - passes at boundary', () => {
21+
const schema = new Schema({ type: 'array', maxItems: 3 });
22+
assert.strictEqual(schema.validate([1, 2, 3]).valid, true);
23+
});
24+
25+
test('maxItems - fails above', () => {
26+
const schema = new Schema({ type: 'array', maxItems: 3 });
27+
const result = schema.validate([1, 2, 3, 4]);
28+
assert.strictEqual(result.valid, false);
29+
assert.strictEqual(result.errors[0].code, 'ARRAY_TOO_LONG');
30+
});
31+
32+
test('items - validates each item', () => {
33+
const schema = new Schema({
34+
type: 'array',
35+
items: { type: 'string' },
36+
});
37+
assert.strictEqual(schema.validate(['a', 'b', 'c']).valid, true);
38+
});
39+
40+
test('items - reports errors with index path', () => {
41+
const schema = new Schema({
42+
type: 'array',
43+
items: { type: 'string' },
44+
});
45+
const result = schema.validate(['a', 42, 'c']);
46+
assert.strictEqual(result.valid, false);
47+
assert.strictEqual(result.errors.length, 1);
48+
assert.strictEqual(result.errors[0].path, '[1]');
49+
assert.strictEqual(result.errors[0].code, 'INVALID_TYPE');
50+
});
51+
52+
test('items - multiple errors', () => {
53+
const schema = new Schema({
54+
type: 'array',
55+
items: { type: 'number', minimum: 0 },
56+
});
57+
const result = schema.validate([1, -1, 'x', 3]);
58+
assert.strictEqual(result.valid, false);
59+
assert.strictEqual(result.errors.length, 2);
60+
});
61+
62+
test('minItems === maxItems pins exact length', () => {
63+
const schema = new Schema({ type: 'array', minItems: 2, maxItems: 2 });
64+
assert.strictEqual(schema.validate([1, 2]).valid, true);
65+
66+
const tooShort = schema.validate([1]);
67+
assert.strictEqual(tooShort.valid, false);
68+
assert.strictEqual(tooShort.errors[0].code, 'ARRAY_TOO_SHORT');
69+
70+
const tooLong = schema.validate([1, 2, 3]);
71+
assert.strictEqual(tooLong.valid, false);
72+
assert.strictEqual(tooLong.errors[0].code, 'ARRAY_TOO_LONG');
73+
});
74+
75+
test('empty array is valid', () => {
76+
const schema = new Schema({ type: 'array', items: { type: 'string' } });
77+
assert.strictEqual(schema.validate([]).valid, true);
78+
});
79+
80+
test('nested array schemas', () => {
81+
const schema = new Schema({
82+
type: 'array',
83+
items: {
84+
type: 'array',
85+
items: { type: 'number' },
86+
},
87+
});
88+
assert.strictEqual(schema.validate([[1, 2], [3, 4]]).valid, true);
89+
const result = schema.validate([[1, 'x']]);
90+
assert.strictEqual(result.valid, false);
91+
assert.strictEqual(result.errors[0].path, '[0][1]');
92+
});
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const { test } = require('node:test');
6+
const { Schema } = require('node:validator');
7+
8+
test('five-level nested object path', () => {
9+
const schema = new Schema({
10+
type: 'object',
11+
properties: {
12+
a: {
13+
type: 'object',
14+
properties: {
15+
b: {
16+
type: 'object',
17+
properties: {
18+
c: {
19+
type: 'object',
20+
properties: {
21+
d: {
22+
type: 'object',
23+
properties: {
24+
e: { type: 'string' },
25+
},
26+
},
27+
},
28+
},
29+
},
30+
},
31+
},
32+
},
33+
},
34+
});
35+
36+
const result = schema.validate({ a: { b: { c: { d: { e: 42 } } } } });
37+
assert.strictEqual(result.valid, false);
38+
assert.strictEqual(result.errors.length, 1);
39+
assert.strictEqual(result.errors[0].path, 'a.b.c.d.e');
40+
assert.strictEqual(result.errors[0].code, 'INVALID_TYPE');
41+
});
42+
43+
test('deeply nested arrays of arrays', () => {
44+
const schema = new Schema({
45+
type: 'array',
46+
items: {
47+
type: 'array',
48+
items: {
49+
type: 'array',
50+
items: { type: 'number' },
51+
},
52+
},
53+
});
54+
55+
const result = schema.validate([[[1, 2], [3, 'bad']]]);
56+
assert.strictEqual(result.valid, false);
57+
assert.strictEqual(result.errors[0].path, '[0][1][1]');
58+
assert.strictEqual(result.errors[0].code, 'INVALID_TYPE');
59+
});
60+
61+
test('mixed arrays and objects deep path', () => {
62+
const schema = new Schema({
63+
type: 'object',
64+
properties: {
65+
teams: {
66+
type: 'array',
67+
items: {
68+
type: 'object',
69+
properties: {
70+
members: {
71+
type: 'array',
72+
items: {
73+
type: 'object',
74+
properties: {
75+
addresses: {
76+
type: 'array',
77+
items: {
78+
type: 'object',
79+
properties: {
80+
zip: { type: 'string', minLength: 5 },
81+
},
82+
},
83+
},
84+
},
85+
},
86+
},
87+
},
88+
},
89+
},
90+
},
91+
});
92+
93+
const result = schema.validate({
94+
teams: [
95+
{
96+
members: [
97+
{ addresses: [{ zip: '12345' }] },
98+
{ addresses: [{ zip: '12345' }, { zip: '1' }] },
99+
],
100+
},
101+
],
102+
});
103+
assert.strictEqual(result.valid, false);
104+
assert.strictEqual(
105+
result.errors[0].path,
106+
'teams[0].members[1].addresses[1].zip',
107+
);
108+
assert.strictEqual(result.errors[0].code, 'STRING_TOO_SHORT');
109+
});
110+
111+
test('multiple errors at different deep paths', () => {
112+
const schema = new Schema({
113+
type: 'object',
114+
properties: {
115+
outer: {
116+
type: 'object',
117+
required: ['x', 'y'],
118+
properties: {
119+
x: {
120+
type: 'object',
121+
properties: {
122+
value: { type: 'number', minimum: 0 },
123+
},
124+
},
125+
y: {
126+
type: 'object',
127+
properties: {
128+
value: { type: 'string', minLength: 3 },
129+
},
130+
},
131+
},
132+
},
133+
},
134+
});
135+
136+
const result = schema.validate({
137+
outer: {
138+
x: { value: -5 },
139+
y: { value: 'a' },
140+
},
141+
});
142+
assert.strictEqual(result.valid, false);
143+
const paths = result.errors.map((e) => e.path);
144+
assert.ok(paths.includes('outer.x.value'));
145+
assert.ok(paths.includes('outer.y.value'));
146+
});
147+
148+
test('deeply nested applyDefaults fills missing leaves', () => {
149+
const schema = new Schema({
150+
type: 'object',
151+
properties: {
152+
a: {
153+
type: 'object',
154+
properties: {
155+
b: {
156+
type: 'object',
157+
properties: {
158+
c: {
159+
type: 'object',
160+
properties: {
161+
d: { type: 'string', default: 'deep' },
162+
},
163+
},
164+
},
165+
},
166+
},
167+
},
168+
},
169+
});
170+
171+
const result = schema.applyDefaults({ a: { b: { c: {} } } });
172+
assert.strictEqual(result.a.b.c.d, 'deep');
173+
});
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const { test } = require('node:test');
6+
const { Schema } = require('node:validator');
7+
8+
test('applyDefaults - applies defaults for missing properties', () => {
9+
const schema = new Schema({
10+
type: 'object',
11+
properties: {
12+
host: { type: 'string', default: 'localhost' },
13+
port: { type: 'integer', default: 3000 },
14+
},
15+
});
16+
const result = schema.applyDefaults({});
17+
assert.strictEqual(result.host, 'localhost');
18+
assert.strictEqual(result.port, 3000);
19+
});
20+
21+
test('applyDefaults - does not overwrite existing values', () => {
22+
const schema = new Schema({
23+
type: 'object',
24+
properties: {
25+
host: { type: 'string', default: 'localhost' },
26+
},
27+
});
28+
const result = schema.applyDefaults({ host: 'example.com' });
29+
assert.strictEqual(result.host, 'example.com');
30+
});
31+
32+
test('applyDefaults - does not mutate input', () => {
33+
const schema = new Schema({
34+
type: 'object',
35+
properties: {
36+
host: { type: 'string', default: 'localhost' },
37+
},
38+
});
39+
const input = {};
40+
schema.applyDefaults(input);
41+
assert.strictEqual(input.host, undefined);
42+
});
43+
44+
test('applyDefaults - applies for undefined values', () => {
45+
const schema = new Schema({
46+
type: 'object',
47+
properties: {
48+
host: { type: 'string', default: 'localhost' },
49+
},
50+
});
51+
const result = schema.applyDefaults({ host: undefined });
52+
assert.strictEqual(result.host, 'localhost');
53+
});
54+
55+
test('applyDefaults - does not apply for null values', () => {
56+
const schema = new Schema({
57+
type: 'object',
58+
properties: {
59+
host: { type: 'string', default: 'localhost' },
60+
},
61+
});
62+
const result = schema.applyDefaults({ host: null });
63+
assert.strictEqual(result.host, null);
64+
});
65+
66+
test('applyDefaults - nested defaults', () => {
67+
const schema = new Schema({
68+
type: 'object',
69+
properties: {
70+
config: {
71+
type: 'object',
72+
properties: {
73+
timeout: { type: 'integer', default: 5000 },
74+
retries: { type: 'integer', default: 3 },
75+
},
76+
},
77+
},
78+
});
79+
const result = schema.applyDefaults({ config: { retries: 1 } });
80+
assert.strictEqual(result.config.timeout, 5000);
81+
assert.strictEqual(result.config.retries, 1);
82+
});
83+
84+
test('applyDefaults - preserves extra properties', () => {
85+
const schema = new Schema({
86+
type: 'object',
87+
properties: {
88+
name: { type: 'string', default: 'unknown' },
89+
},
90+
});
91+
const result = schema.applyDefaults({ extra: 'value' });
92+
assert.strictEqual(result.name, 'unknown');
93+
assert.strictEqual(result.extra, 'value');
94+
});
95+
96+
test('applyDefaults - returns non-object data as-is', () => {
97+
const schema = new Schema({ type: 'string' });
98+
assert.strictEqual(schema.applyDefaults('hello'), 'hello');
99+
});
100+
101+
test('applyDefaults - array items defaults', () => {
102+
const schema = new Schema({
103+
type: 'array',
104+
items: {
105+
type: 'object',
106+
properties: {
107+
enabled: { type: 'boolean', default: true },
108+
},
109+
},
110+
});
111+
const result = schema.applyDefaults([{ enabled: false }, {}]);
112+
assert.strictEqual(result[0].enabled, false);
113+
assert.strictEqual(result[1].enabled, true);
114+
});

0 commit comments

Comments
 (0)