Version 1
[yaffs-website] / node_modules / is-my-json-valid / test / misc.js
1 var tape = require('tape')
2 var cosmic = require('./fixtures/cosmic')
3 var validator = require('../')
4 var validatorRequire = require('../require')
5
6 tape('simple', function(t) {
7   var schema = {
8     required: true,
9     type: 'object',
10     properties: {
11       hello: {type:'string', required:true}
12     }
13   }
14
15   var validate = validator(schema)
16
17   t.ok(validate({hello: 'world'}), 'should be valid')
18   t.notOk(validate(), 'should be invalid')
19   t.notOk(validate({}), 'should be invalid')
20   t.end()
21 })
22
23 tape('data is undefined', function (t) {
24   var validate = validator({type: 'string'})
25
26   t.notOk(validate(null))
27   t.notOk(validate(undefined))
28   t.end()
29 })
30
31 tape('advanced', function(t) {
32   var validate = validator(cosmic.schema)
33
34   t.ok(validate(cosmic.valid), 'should be valid')
35   t.notOk(validate(cosmic.invalid), 'should be invalid')
36   t.end()
37 })
38
39 tape('greedy/false', function(t) {
40   var validate = validator({
41     type: 'object',
42     properties: {
43       x: {
44         type: 'number'
45       }
46     },
47     required: ['x', 'y']
48   });
49   t.notOk(validate({}), 'should be invalid')
50   t.strictEqual(validate.errors.length, 2);
51   t.strictEqual(validate.errors[0].field, 'data.x')
52   t.strictEqual(validate.errors[0].message, 'is required')
53   t.strictEqual(validate.errors[1].field, 'data.y')
54   t.strictEqual(validate.errors[1].message, 'is required')
55   t.notOk(validate({x: 'string'}), 'should be invalid')
56   t.strictEqual(validate.errors.length, 1);
57   t.strictEqual(validate.errors[0].field, 'data.y')
58   t.strictEqual(validate.errors[0].message, 'is required')
59   t.notOk(validate({x: 'string', y: 'value'}), 'should be invalid')
60   t.strictEqual(validate.errors.length, 1);
61   t.strictEqual(validate.errors[0].field, 'data.x')
62   t.strictEqual(validate.errors[0].message, 'is the wrong type')
63   t.end();
64 });
65
66 tape('greedy/true', function(t) {
67   var validate = validator({
68     type: 'object',
69     properties: {
70       x: {
71         type: 'number'
72       }
73     },
74     required: ['x', 'y']
75   }, {
76     greedy: true
77   });
78   t.notOk(validate({}), 'should be invalid')
79   t.strictEqual(validate.errors.length, 2);
80   t.strictEqual(validate.errors[0].field, 'data.x')
81   t.strictEqual(validate.errors[0].message, 'is required')
82   t.strictEqual(validate.errors[1].field, 'data.y')
83   t.strictEqual(validate.errors[1].message, 'is required')
84   t.notOk(validate({x: 'string'}), 'should be invalid')
85   t.strictEqual(validate.errors.length, 2);
86   t.strictEqual(validate.errors[0].field, 'data.y')
87   t.strictEqual(validate.errors[0].message, 'is required')
88   t.strictEqual(validate.errors[1].field, 'data.x')
89   t.strictEqual(validate.errors[1].message, 'is the wrong type')
90   t.notOk(validate({x: 'string', y: 'value'}), 'should be invalid')
91   t.strictEqual(validate.errors.length, 1);
92   t.strictEqual(validate.errors[0].field, 'data.x')
93   t.strictEqual(validate.errors[0].message, 'is the wrong type')
94   t.ok(validate({x: 1, y: 'value'}), 'should be invalid')
95   t.end();
96 });
97
98 tape('additional props', function(t) {
99   var validate = validator({
100     type: 'object',
101     additionalProperties: false
102   }, {
103     verbose: true
104   })
105
106   t.ok(validate({}))
107   t.notOk(validate({foo:'bar'}))
108   t.ok(validate.errors[0].value === 'data.foo', 'should output the property not allowed in verbose mode')
109   t.strictEqual(validate.errors[0].type, 'object', 'error object should contain the type')
110   t.end()
111 })
112
113 tape('array', function(t) {
114   var validate = validator({
115     type: 'array',
116     required: true,
117     items: {
118       type: 'string'
119     }
120   })
121
122   t.notOk(validate({}), 'wrong type')
123   t.notOk(validate(), 'is required')
124   t.ok(validate(['test']))
125   t.end()
126 })
127
128 tape('nested array', function(t) {
129   var validate = validator({
130     type: 'object',
131     properties: {
132       list: {
133         type: 'array',
134         required: true,
135         items: {
136           type: 'string'
137         }
138       }
139     }
140   })
141
142   t.notOk(validate({}), 'is required')
143   t.ok(validate({list:['test']}))
144   t.notOk(validate({list:[1]}))
145   t.end()
146 })
147
148 tape('enum', function(t) {
149   var validate = validator({
150     type: 'object',
151     properties: {
152       foo: {
153         type: 'number',
154         required: true,
155         enum: [42]
156       }
157     }
158   })
159
160   t.notOk(validate({}), 'is required')
161   t.ok(validate({foo:42}))
162   t.notOk(validate({foo:43}))
163   t.end()
164 })
165
166 tape('minimum/maximum', function(t) {
167   var validate = validator({
168     type: 'object',
169     properties: {
170       foo: {
171         type: 'number',
172         minimum: 0,
173         maximum: 0
174       }
175     }
176   })
177
178   t.notOk(validate({foo:-42}))
179   t.ok(validate({foo:0}))
180   t.notOk(validate({foo:42}))
181   t.end()
182 })
183
184 tape('exclusiveMinimum/exclusiveMaximum', function(t) {
185   var validate = validator({
186     type: 'object',
187     properties: {
188       foo: {
189         type: 'number',
190         minimum: 10,
191         maximum: 20,
192         exclusiveMinimum: true,
193         exclusiveMaximum: true
194       }
195     }
196   })
197
198   t.notOk(validate({foo:10}))
199   t.ok(validate({foo:11}))
200   t.notOk(validate({foo:20}))
201   t.ok(validate({foo:19}))
202   t.end()
203 })
204
205 tape('minimum/maximum number type', function(t) {
206   var validate = validator({
207     type: ['integer', 'null'],
208     minimum: 1,
209     maximum: 100
210   })
211
212   t.notOk(validate(-1))
213   t.notOk(validate(0))
214   t.ok(validate(null))
215   t.ok(validate(1))
216   t.ok(validate(100))
217   t.notOk(validate(101))
218   t.end()
219 })
220
221 tape('custom format', function(t) {
222   var validate = validator({
223     type: 'object',
224     properties: {
225       foo: {
226         type: 'string',
227         format: 'as'
228       }
229     }
230   }, {formats: {as:/^a+$/}})
231
232   t.notOk(validate({foo:''}), 'not as')
233   t.notOk(validate({foo:'b'}), 'not as')
234   t.notOk(validate({foo:'aaab'}), 'not as')
235   t.ok(validate({foo:'a'}), 'as')
236   t.ok(validate({foo:'aaaaaa'}), 'as')
237   t.end()
238 })
239
240 tape('custom format function', function(t) {
241   var validate = validator({
242     type: 'object',
243     properties: {
244       foo: {
245         type: 'string',
246         format: 'as'
247       }
248     }
249   }, {formats: {as:function(s) { return /^a+$/.test(s) } }})
250
251   t.notOk(validate({foo:''}), 'not as')
252   t.notOk(validate({foo:'b'}), 'not as')
253   t.notOk(validate({foo:'aaab'}), 'not as')
254   t.ok(validate({foo:'a'}), 'as')
255   t.ok(validate({foo:'aaaaaa'}), 'as')
256   t.end()
257 })
258
259 tape('do not mutate schema', function(t) {
260   var sch = {
261     items: [
262       {}
263     ],
264     additionalItems: {
265       type: 'integer'
266     }
267   }
268
269   var copy = JSON.parse(JSON.stringify(sch))
270
271   validator(sch)
272
273   t.same(sch, copy, 'did not mutate')
274   t.end()
275 })
276
277 tape('#toJSON()', function(t) {
278   var schema = {
279     required: true,
280     type: 'object',
281     properties: {
282       hello: {type:'string', required:true}
283     }
284   }
285
286   var validate = validator(schema)
287
288   t.deepEqual(validate.toJSON(), schema, 'should return original schema')
289   t.end()
290 })
291
292 tape('external schemas', function(t) {
293   var ext = {type: 'string'}
294   var schema = {
295     required: true,
296     $ref: '#ext'
297   }
298
299   var validate = validator(schema, {schemas: {ext:ext}})
300
301   t.ok(validate('hello string'), 'is a string')
302   t.notOk(validate(42), 'not a string')
303   t.end()
304 })
305
306 tape('external schema URIs', function(t) {
307   var ext = {type: 'string'}
308   var schema = {
309     required: true,
310     $ref: 'http://example.com/schemas/schemaURIs'
311   }
312
313   var opts = {schemas:{}};
314   opts.schemas['http://example.com/schemas/schemaURIs'] = ext;
315   var validate = validator(schema, opts)
316
317   t.ok(validate('hello string'), 'is a string')
318   t.notOk(validate(42), 'not a string')
319   t.end()
320 })
321
322 tape('top-level external schema', function(t) {
323   var defs = {
324     "string": {
325       type: "string"
326     },
327     "sex": {
328       type: "string",
329       enum: ["male", "female", "other"]
330     }
331   }
332   var schema = {
333     type: "object",
334     properties: {
335       "name": { $ref: "definitions.json#/string" },
336       "sex": { $ref: "definitions.json#/sex" }
337     },
338     required: ["name", "sex"]
339   }
340
341   var validate = validator(schema, {
342     schemas: {
343       "definitions.json": defs
344     }
345   })
346   t.ok(validate({name:"alice", sex:"female"}), 'is an object')
347   t.notOk(validate({name:"alice", sex: "bob"}), 'recognizes external schema')
348   t.notOk(validate({name:2, sex: "female"}), 'recognizes external schema')
349   t.end()
350 })
351
352 tape('nested required array decl', function(t) {
353   var schema = {
354     properties: {
355       x: {
356         type: 'object',
357         properties: {
358           y: {
359             type: 'object',
360             properties: {
361               z: {
362                 type: 'string'
363               }
364             },
365             required: ['z']
366           }
367         }
368       }
369     },
370     required: ['x']
371   }
372
373   var validate = validator(schema)
374
375   t.ok(validate({x: {}}), 'should be valid')
376   t.notOk(validate({}), 'should not be valid')
377   t.strictEqual(validate.errors[0].field, 'data.x', 'should output the missing field')
378   t.end()
379 })
380
381 tape('verbose mode', function(t) {
382   var schema = {
383     required: true,
384     type: 'object',
385     properties: {
386       hello: {
387         required: true,
388         type: 'string'
389       }
390     }
391   };
392
393   var validate = validator(schema, {verbose: true})
394
395   t.ok(validate({hello: 'string'}), 'should be valid')
396   t.notOk(validate({hello: 100}), 'should not be valid')
397   t.strictEqual(validate.errors[0].value, 100, 'error object should contain the invalid value')
398   t.strictEqual(validate.errors[0].type, 'string', 'error object should contain the type')
399   t.end()
400 })
401
402 tape('additional props in verbose mode', function(t) {
403   var schema = {
404     type: 'object',
405     required: true,
406     additionalProperties: false,
407     properties: {
408       foo: {
409         type: 'string'
410       },
411       'hello world': {
412         type: 'object',
413         required: true,
414         additionalProperties: false,
415         properties: {
416           foo: {
417             type: 'string'
418           }
419         }
420       }
421     }
422   };
423
424   var validate = validator(schema, {verbose: true})
425
426   validate({'hello world': {bar: 'string'}});
427
428   t.strictEqual(validate.errors[0].value, 'data["hello world"].bar', 'should output the path to the additional prop in the error')
429   t.end()
430 })
431
432 tape('Date.now() is an integer', function(t) {
433   var schema = {type: 'integer'}
434   var validate = validator(schema)
435
436   t.ok(validate(Date.now()), 'is integer')
437   t.end()
438 })
439
440 tape('field shows item index in arrays', function(t) {
441   var schema = {
442     type: 'array',
443     items: {
444       type: 'array',
445       items: {
446         properties: {
447           foo: {
448             type: 'string',
449             required: true
450           }
451         }
452       }
453     }
454   }
455
456   var validate = validator(schema)
457
458   validate([
459     [
460       { foo: 'test' },
461       { foo: 'test' }
462     ],
463     [
464       { foo: 'test' },
465       { baz: 'test' }
466     ]
467   ])
468
469   t.strictEqual(validate.errors[0].field, 'data.1.1.foo', 'should output the field with specific index of failing item in the error')
470   t.end()
471 })