123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- var tape = require('tape')
- var cosmic = require('./fixtures/cosmic')
- var validator = require('../')
- var validatorRequire = require('../require')
-
- tape('simple', function(t) {
- var schema = {
- required: true,
- type: 'object',
- properties: {
- hello: {type:'string', required:true}
- }
- }
-
- var validate = validator(schema)
-
- t.ok(validate({hello: 'world'}), 'should be valid')
- t.notOk(validate(), 'should be invalid')
- t.notOk(validate({}), 'should be invalid')
- t.end()
- })
-
- tape('data is undefined', function (t) {
- var validate = validator({type: 'string'})
-
- t.notOk(validate(null))
- t.notOk(validate(undefined))
- t.end()
- })
-
- tape('advanced', function(t) {
- var validate = validator(cosmic.schema)
-
- t.ok(validate(cosmic.valid), 'should be valid')
- t.notOk(validate(cosmic.invalid), 'should be invalid')
- t.end()
- })
-
- tape('greedy/false', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- x: {
- type: 'number'
- }
- },
- required: ['x', 'y']
- });
- t.notOk(validate({}), 'should be invalid')
- t.strictEqual(validate.errors.length, 2);
- t.strictEqual(validate.errors[0].field, 'data.x')
- t.strictEqual(validate.errors[0].message, 'is required')
- t.strictEqual(validate.errors[1].field, 'data.y')
- t.strictEqual(validate.errors[1].message, 'is required')
- t.notOk(validate({x: 'string'}), 'should be invalid')
- t.strictEqual(validate.errors.length, 1);
- t.strictEqual(validate.errors[0].field, 'data.y')
- t.strictEqual(validate.errors[0].message, 'is required')
- t.notOk(validate({x: 'string', y: 'value'}), 'should be invalid')
- t.strictEqual(validate.errors.length, 1);
- t.strictEqual(validate.errors[0].field, 'data.x')
- t.strictEqual(validate.errors[0].message, 'is the wrong type')
- t.end();
- });
-
- tape('greedy/true', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- x: {
- type: 'number'
- }
- },
- required: ['x', 'y']
- }, {
- greedy: true
- });
- t.notOk(validate({}), 'should be invalid')
- t.strictEqual(validate.errors.length, 2);
- t.strictEqual(validate.errors[0].field, 'data.x')
- t.strictEqual(validate.errors[0].message, 'is required')
- t.strictEqual(validate.errors[1].field, 'data.y')
- t.strictEqual(validate.errors[1].message, 'is required')
- t.notOk(validate({x: 'string'}), 'should be invalid')
- t.strictEqual(validate.errors.length, 2);
- t.strictEqual(validate.errors[0].field, 'data.y')
- t.strictEqual(validate.errors[0].message, 'is required')
- t.strictEqual(validate.errors[1].field, 'data.x')
- t.strictEqual(validate.errors[1].message, 'is the wrong type')
- t.notOk(validate({x: 'string', y: 'value'}), 'should be invalid')
- t.strictEqual(validate.errors.length, 1);
- t.strictEqual(validate.errors[0].field, 'data.x')
- t.strictEqual(validate.errors[0].message, 'is the wrong type')
- t.ok(validate({x: 1, y: 'value'}), 'should be invalid')
- t.end();
- });
-
- tape('additional props', function(t) {
- var validate = validator({
- type: 'object',
- additionalProperties: false
- }, {
- verbose: true
- })
-
- t.ok(validate({}))
- t.notOk(validate({foo:'bar'}))
- t.ok(validate.errors[0].value === 'data.foo', 'should output the property not allowed in verbose mode')
- t.strictEqual(validate.errors[0].type, 'object', 'error object should contain the type')
- t.end()
- })
-
- tape('array', function(t) {
- var validate = validator({
- type: 'array',
- required: true,
- items: {
- type: 'string'
- }
- })
-
- t.notOk(validate({}), 'wrong type')
- t.notOk(validate(), 'is required')
- t.ok(validate(['test']))
- t.end()
- })
-
- tape('nested array', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- list: {
- type: 'array',
- required: true,
- items: {
- type: 'string'
- }
- }
- }
- })
-
- t.notOk(validate({}), 'is required')
- t.ok(validate({list:['test']}))
- t.notOk(validate({list:[1]}))
- t.end()
- })
-
- tape('enum', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- foo: {
- type: 'number',
- required: true,
- enum: [42]
- }
- }
- })
-
- t.notOk(validate({}), 'is required')
- t.ok(validate({foo:42}))
- t.notOk(validate({foo:43}))
- t.end()
- })
-
- tape('minimum/maximum', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- foo: {
- type: 'number',
- minimum: 0,
- maximum: 0
- }
- }
- })
-
- t.notOk(validate({foo:-42}))
- t.ok(validate({foo:0}))
- t.notOk(validate({foo:42}))
- t.end()
- })
-
- tape('exclusiveMinimum/exclusiveMaximum', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- foo: {
- type: 'number',
- minimum: 10,
- maximum: 20,
- exclusiveMinimum: true,
- exclusiveMaximum: true
- }
- }
- })
-
- t.notOk(validate({foo:10}))
- t.ok(validate({foo:11}))
- t.notOk(validate({foo:20}))
- t.ok(validate({foo:19}))
- t.end()
- })
-
- tape('minimum/maximum number type', function(t) {
- var validate = validator({
- type: ['integer', 'null'],
- minimum: 1,
- maximum: 100
- })
-
- t.notOk(validate(-1))
- t.notOk(validate(0))
- t.ok(validate(null))
- t.ok(validate(1))
- t.ok(validate(100))
- t.notOk(validate(101))
- t.end()
- })
-
- tape('custom format', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- foo: {
- type: 'string',
- format: 'as'
- }
- }
- }, {formats: {as:/^a+$/}})
-
- t.notOk(validate({foo:''}), 'not as')
- t.notOk(validate({foo:'b'}), 'not as')
- t.notOk(validate({foo:'aaab'}), 'not as')
- t.ok(validate({foo:'a'}), 'as')
- t.ok(validate({foo:'aaaaaa'}), 'as')
- t.end()
- })
-
- tape('custom format function', function(t) {
- var validate = validator({
- type: 'object',
- properties: {
- foo: {
- type: 'string',
- format: 'as'
- }
- }
- }, {formats: {as:function(s) { return /^a+$/.test(s) } }})
-
- t.notOk(validate({foo:''}), 'not as')
- t.notOk(validate({foo:'b'}), 'not as')
- t.notOk(validate({foo:'aaab'}), 'not as')
- t.ok(validate({foo:'a'}), 'as')
- t.ok(validate({foo:'aaaaaa'}), 'as')
- t.end()
- })
-
- tape('do not mutate schema', function(t) {
- var sch = {
- items: [
- {}
- ],
- additionalItems: {
- type: 'integer'
- }
- }
-
- var copy = JSON.parse(JSON.stringify(sch))
-
- validator(sch)
-
- t.same(sch, copy, 'did not mutate')
- t.end()
- })
-
- tape('#toJSON()', function(t) {
- var schema = {
- required: true,
- type: 'object',
- properties: {
- hello: {type:'string', required:true}
- }
- }
-
- var validate = validator(schema)
-
- t.deepEqual(validate.toJSON(), schema, 'should return original schema')
- t.end()
- })
-
- tape('external schemas', function(t) {
- var ext = {type: 'string'}
- var schema = {
- required: true,
- $ref: '#ext'
- }
-
- var validate = validator(schema, {schemas: {ext:ext}})
-
- t.ok(validate('hello string'), 'is a string')
- t.notOk(validate(42), 'not a string')
- t.end()
- })
-
- tape('external schema URIs', function(t) {
- var ext = {type: 'string'}
- var schema = {
- required: true,
- $ref: 'http://example.com/schemas/schemaURIs'
- }
-
- var opts = {schemas:{}};
- opts.schemas['http://example.com/schemas/schemaURIs'] = ext;
- var validate = validator(schema, opts)
-
- t.ok(validate('hello string'), 'is a string')
- t.notOk(validate(42), 'not a string')
- t.end()
- })
-
- tape('top-level external schema', function(t) {
- var defs = {
- "string": {
- type: "string"
- },
- "sex": {
- type: "string",
- enum: ["male", "female", "other"]
- }
- }
- var schema = {
- type: "object",
- properties: {
- "name": { $ref: "definitions.json#/string" },
- "sex": { $ref: "definitions.json#/sex" }
- },
- required: ["name", "sex"]
- }
-
- var validate = validator(schema, {
- schemas: {
- "definitions.json": defs
- }
- })
- t.ok(validate({name:"alice", sex:"female"}), 'is an object')
- t.notOk(validate({name:"alice", sex: "bob"}), 'recognizes external schema')
- t.notOk(validate({name:2, sex: "female"}), 'recognizes external schema')
- t.end()
- })
-
- tape('nested required array decl', function(t) {
- var schema = {
- properties: {
- x: {
- type: 'object',
- properties: {
- y: {
- type: 'object',
- properties: {
- z: {
- type: 'string'
- }
- },
- required: ['z']
- }
- }
- }
- },
- required: ['x']
- }
-
- var validate = validator(schema)
-
- t.ok(validate({x: {}}), 'should be valid')
- t.notOk(validate({}), 'should not be valid')
- t.strictEqual(validate.errors[0].field, 'data.x', 'should output the missing field')
- t.end()
- })
-
- tape('verbose mode', function(t) {
- var schema = {
- required: true,
- type: 'object',
- properties: {
- hello: {
- required: true,
- type: 'string'
- }
- }
- };
-
- var validate = validator(schema, {verbose: true})
-
- t.ok(validate({hello: 'string'}), 'should be valid')
- t.notOk(validate({hello: 100}), 'should not be valid')
- t.strictEqual(validate.errors[0].value, 100, 'error object should contain the invalid value')
- t.strictEqual(validate.errors[0].type, 'string', 'error object should contain the type')
- t.end()
- })
-
- tape('additional props in verbose mode', function(t) {
- var schema = {
- type: 'object',
- required: true,
- additionalProperties: false,
- properties: {
- foo: {
- type: 'string'
- },
- 'hello world': {
- type: 'object',
- required: true,
- additionalProperties: false,
- properties: {
- foo: {
- type: 'string'
- }
- }
- }
- }
- };
-
- var validate = validator(schema, {verbose: true})
-
- validate({'hello world': {bar: 'string'}});
-
- t.strictEqual(validate.errors[0].value, 'data["hello world"].bar', 'should output the path to the additional prop in the error')
- t.end()
- })
-
- tape('Date.now() is an integer', function(t) {
- var schema = {type: 'integer'}
- var validate = validator(schema)
-
- t.ok(validate(Date.now()), 'is integer')
- t.end()
- })
-
- tape('field shows item index in arrays', function(t) {
- var schema = {
- type: 'array',
- items: {
- type: 'array',
- items: {
- properties: {
- foo: {
- type: 'string',
- required: true
- }
- }
- }
- }
- }
-
- var validate = validator(schema)
-
- validate([
- [
- { foo: 'test' },
- { foo: 'test' }
- ],
- [
- { foo: 'test' },
- { baz: 'test' }
- ]
- ])
-
- t.strictEqual(validate.errors[0].field, 'data.1.1.foo', 'should output the field with specific index of failing item in the error')
- t.end()
- })
|