UNPKG

@trigo/atrix-swagger

Version:

Swagger API Language intigration

563 lines (493 loc) 17.5 kB
'use strict'; /* eslint-env node, mocha */ /* eslint no-unused-expressions: 0, arrow-body-style: 0 */ const { expect } = require('chai'); const Joi = require('joi'); const uuid = require('uuid'); const { createParameterValidator } = require('./create-validator'); describe('createParameterValidation', () => { function getSchema(def) { const config = {}; config[def.name] = createParameterValidator(def); const schema = Joi.object(config); return { schema, validate: (obj) => schema.validate(obj), ok: obj => { Joi.assert(obj, schema); }, fail: (obj, msg) => { try { expect(() => Joi.assert(obj, schema)).to.throw(Error, msg); } catch (e) { console.error(e); // eslint-disable-line throw e; } }, }; } it('can omit attribute "type" to allow any value', () => { const schema = getSchema({ name: 'test', }); schema.ok({ test: true }); schema.ok({ test: false }); schema.ok({ test: 0 }); schema.ok({ test: 1.2 }); schema.ok({ test: [1, '12'] }); schema.ok({ test: { prop: 1, sub: { p: '12' } } }); }); describe('"boolean" properties', () => { it('creates boolean validator', () => { const schema = getSchema({ name: 'test', type: 'boolean', }); schema.ok({ test: true }); schema.ok({ test: false }); schema.fail({ test: 0 }); schema.fail({ test: 1 }); }); }); describe('attribute "required"', () => { it('make property required', () => { const schema = getSchema({ name: 'test', type: 'string', required: true, }); schema.ok({ test: 'true' }); schema.fail({}); }); }); it('handles attribute "default"', () => { const schema = getSchema({ name: 'test', type: 'string', default: 'uuid', }); const parsedValue = schema.validate({}); // Joi.validate({}, schema.schema); expect(parsedValue.value.test).to.equal('uuid'); }); it('handles attribute "nullable"', () => { const schema1 = getSchema({ name: 'test', type: 'string', nullable: true, required: true, }); const schema2 = getSchema({ name: 'test', type: 'string', nullable: false, }); const schema3 = getSchema({ name: 'test', type: 'string', }); schema1.ok({ test: 'asdf' }); schema1.ok({ test: null }); schema1.fail({ test: undefined }); schema2.fail({ test: null }); schema3.fail({ test: null }); }); describe('handles "enum" attribute', () => { it('string property', () => { const schema = getSchema({ name: 'test', type: 'string', enum: ['v1', 'v2', 'v3'], }); schema.ok({ test: 'v1' }); schema.ok({ test: 'v2' }); schema.ok({ test: 'v3' }); schema.fail({ test: 'adg' }, /must be one of/); }); it('number property', () => { const schema = getSchema({ name: 'test', type: 'number', enum: [42, 21, null], }); schema.ok({ test: 42 }); schema.ok({ test: 21 }); schema.ok({ test: null }); schema.fail({ test: 32 }, /must be one of/); }); }); describe('"number" properties & options', () => { it('creates integer validator', () => { const schema = getSchema({ name: 'test', type: 'integer', }); schema.ok({ test: 100 }); schema.fail({ test: 'asd' }, /must be a number/); schema.fail({ test: 1.2 }, /must be an integer/); }); it('creates number validator', () => { const schema = getSchema({ name: 'test', type: 'number', }); schema.ok({ test: 100 }); schema.ok({ test: -100.3 }); schema.fail({ test: 'asd' }, /must be a number/); schema.fail({ test: false }, /must be a number/); }); it('handles "maximum" attribute', () => { const schema = getSchema({ name: 'test', type: 'number', maximum: 42, }); schema.ok({ test: 12 }); schema.ok({ test: -100 }); schema.ok({ test: 42 }); schema.fail({ test: 43 }, /must be less than or equal to/); schema.fail({ test: 42.00001 }, /must be less than or equal to/); }); it('handles "exclusiveMaximum" attribute', () => { const schema = getSchema({ name: 'test', type: 'number', maximum: 42, exclusiveMaximum: true, }); schema.ok({ test: 12 }); schema.ok({ test: -100 }); schema.fail({ test: 42 }, /must be less than 42/); schema.fail({ test: 42.00001 }, /must be less than 42/); }); it('handles "minimum" attribute', () => { const schema = getSchema({ name: 'test', type: 'number', minimum: 42, }); schema.ok({ test: 1122 }); schema.ok({ test: 1030 }); schema.ok({ test: 42 }); schema.fail({ test: -14 }, /must be greater than or equal/); schema.fail({ test: 41.99999999 }, /must be greater than or equal/); }); it('handles "exclusiveMinimum" attibute', () => { const schema = getSchema({ name: 'test', type: 'number', minimum: 42, exclusiveMinimum: true, }); schema.ok({ test: 1122 }); schema.ok({ test: 1030 }); schema.fail({ test: 42 }, /must be greater than 42/); schema.fail({ test: 41.99999999 }, /must be greater than 42/); }); it('handles "multipleOf" attribute', () => { const schema = getSchema({ name: 'test', type: 'number', multipleOf: 5, }); schema.ok({ test: 0 }); schema.ok({ test: 5 }); schema.ok({ test: 20 }); schema.fail({ test: 21 }, /must be a multiple of 5/); }); it('handles attribute "default"', () => { const schema = getSchema({ name: 'test', type: 'number', default: 5, }); const parsedValue = schema.validate({}); expect(parsedValue.value.test).to.equal(5); }); }); describe('"string" properties & options', () => { it('creates string validator', () => { const schema = getSchema({ name: 'test', type: 'string', }); schema.ok({ test: '100' }); schema.ok({ test: 'asdgasg' }); schema.fail({ test: 12 }, /must be a string/); schema.fail({ test: false }, /must be a string/); }); it('string validator allows empty strings', () => { const schema = getSchema({ name: 'test', type: 'string', }); schema.ok({ test: '' }); }); it('empty string not allowed with "pattern" attribute', () => { const schema = getSchema({ name: 'test', type: 'string', pattern: '^start', }); schema.ok({ test: 'start' }); schema.fail({ test: '' }); }); it('empty string not allowed with minLength attribute', () => { const schema = getSchema({ name: 'test', type: 'string', minLength: 1, }); schema.ok({ test: 's' }); schema.fail({ test: '' }); }); it('handles "pattern" attribute', () => { const schema = getSchema({ name: 'test', type: 'string', pattern: '^start', }); schema.ok({ test: 'start' }); schema.fail({ test: 'notstart' }); }); it('handles "minLength" attribute', () => { const schema = getSchema({ name: 'test', type: 'string', minLength: 4, }); schema.ok({ test: 'start' }); schema.fail({ test: 'i12' }, /length must be at least 4 character/); }); it('handles "maxLength" attribute', () => { const schema = getSchema({ name: 'test', type: 'string', maxLength: 4, }); schema.ok({ test: 'stat' }); schema.fail({ test: 'i12as' }, /length must be less than or equal to 4 characters/); }); it('handles attribute "format=date"', () => { const schema = getSchema({ name: 'test', type: 'string', format: 'date', }); schema.ok({ test: '1980-05-14' }); schema.fail({ test: new Date().toISOString() }); }); it('handles attribute "format=date-time"', () => { const schema = getSchema({ name: 'test', type: 'string', format: 'date-time', }); schema.ok({ test: new Date().toISOString() }); schema.ok({ test: new Date() }); schema.fail({ test: 'ka date' }); }); it('handles attribute "format=uuid"', () => { const schema = getSchema({ name: 'test', type: 'string', format: 'uuid', }); schema.ok({ test: uuid() }); schema.fail({ test: 'ka date' }); }); }); describe('array properties', () => { it('handle "string" array', () => { const schema = getSchema({ name: 'test', type: 'array', items: { type: 'string', }, }); schema.ok({ test: [] }); schema.ok({ test: ['1', '2', '1asf'] }); schema.fail({ test: 'ka date' }, /must be an array/); schema.fail({ test: [1, 2] }); }); it('handle "number" array', () => { const schema = getSchema({ name: 'test', type: 'array', items: { type: 'number', }, }); schema.ok({ test: [] }); schema.ok({ test: [1, 2, 12.2] }); schema.fail({ test: 'ka date' }, /must be an array/); schema.fail({ test: ['1s', 2] }); }); it('handles "minItems" attribute', () => { const schema = getSchema({ name: 'test', type: 'array', items: { type: 'number', }, minItems: 3, }); schema.ok({ test: [1, 213, 412, 12] }); schema.ok({ test: [1, 2, 12.2] }); schema.fail({ test: [2] }, /must contain at least 3 items/); }); it('handles "maxItems" attribute', () => { const schema = getSchema({ name: 'test', type: 'array', items: { type: 'number', }, maxItems: 3, }); schema.ok({ test: [213, 412, 12] }); schema.ok({ test: [1] }); schema.fail({ test: [1, 2, 3, 4, 5] }, /must contain less than or equal to 3 items/); }); it('handles "uniqueItems" attribute', () => { const schema = getSchema({ name: 'test', type: 'array', items: { type: 'number', }, uniqueItems: true, }); schema.ok({ test: [213, 412, 12] }); schema.ok({ test: [1] }); schema.fail({ test: [1, 2, 3, 1, 5] }, /contains a duplicate value/); }); it('handles empty arrays with "required" attribute', () => { const schema = getSchema({ name: 'test', type: 'array', items: { type: 'object', required: ['id', 'name'], properties: { id: { type: 'string', }, name: { type: 'string', }, }, }, }); schema.ok({ test: [{ id: '1', name: 'obj1' }, { id: '2', name: 'obj2' }] }); schema.ok({ test: [] }); schema.fail({ test: [{ id: '1' }] }, /is required/); }); it('handles arrays with "required" object items', () => { const schema = getSchema({ name: 'test', type: 'array', items: { type: 'object', required: true, properties: { id: { type: 'string', }, name: { type: 'string', }, }, }, }); schema.ok({ test: [{ id: '1', name: 'obj1' }, { id: '2', name: 'obj2' }] }); schema.ok({ test: [{ id: '1' }] }); schema.fail({ test: [] }, /does not contain 1 required/); }); it('in query: array can also be a single value', () => { const schema = getSchema({ in: 'query', name: 'test', type: 'array', items: { type: 'string', }, }); schema.ok({ test: 'ka date' }); schema.ok({ test: [] }); schema.ok({ test: ['1', '2', '1asf'] }); schema.fail({ test: [1, 2] }); }); }); describe('"object" properties', () => { it('primitive type property', () => { const schema = getSchema({ name: 'test', type: 'object', description: 'desc', properties: { name: { type: 'string', }, }, }); schema.ok({ test: { name: 'AtrixSwagger' } }); schema.ok({ test: {} }); schema.fail({ test: 0 }); }); it('object type property', () => { const schema = getSchema({ name: 'test', type: 'object', description: 'desc', properties: { name: { type: 'object', description: 'test nested obj', properties: { id: { type: 'number', minimum: 0, }, }, }, }, }); schema.ok({ test: { name: { id: 12 } } }); schema.ok({ test: {} }); schema.fail({ test: { name: { id: -1 } } }, /must be greater than or equal to 0/); }); it('"required" property', () => { const schema = getSchema({ name: 'test', type: 'object', description: 'desc', properties: { name: { type: 'string', }, }, required: ['name'], }); schema.ok({ test: { name: 'AtrixSwagger' } }); schema.fail({ test: {} }, /is required/); schema.fail({ test: 0 }); }); it('"additionalProperties" = true allows undeclared properties', () => { const schema = getSchema({ name: 'test', type: 'object', properties: { name: { type: 'string', }, }, required: ['name'], additionalProperties: true, }); schema.ok({ test: { name: 'AtrixSwagger' } }); schema.ok({ test: { name: 'AtrixSwagger', ndn: 'asdf', asd: { a: [1, 3] } } }); schema.fail({ test: {} }, /is required/); }); }); });