UNPKG

rest-api-starter

Version:
562 lines (542 loc) 20.7 kB
/** * Created by svinci on 1/13/17. */ 'use strict'; const mocha = require('mocha'); const chai = require('chai'); const describe = mocha.describe; const it = mocha.it; const expect = chai.expect; const validator = require('../app/validator'); const ComboSchema = { 'type': 'object', 'description': 'combo', 'additionalProperties': false, 'properties': { 'pizzaFlavorIds': { 'type': 'array', 'required': false }, 'description': { 'type': 'string', 'required': false }, 'name': { 'type': 'string', 'required': true }, 'feeds': { 'type': 'number', 'required': true }, 'price': { 'type': 'number', 'required': true } } }; const OrderSchema = { 'type': 'object', 'description': 'pizza.delivery.order', 'properties': { 'order': { 'type': 'object', 'properties': { 'combos': { 'type': 'array', 'required': true, 'minItems': 0, 'items': { 'type': 'object', 'properties': { 'quantity': { 'type': 'number', 'required': true }, 'comboId': { 'type': 'string', 'required': true } } } }, 'pizzas': { 'type': 'array', 'required': true, 'minItems': 0, 'items': { 'type': 'object', 'properties': { 'size': { 'enum': ['giant', 'classic', 'small'], 'required': true }, 'flavors': { 'type': 'array', 'minItems': 1, 'maxItems': 4, 'items': { 'type': 'object', 'properties': { 'portion': { 'enum': ['FULL', 'HALF', 'QUARTER'], 'required': true }, 'flavorId': { 'type': 'string', 'required': true } } }, 'required': true } } } }, 'patties': { 'type': 'array', 'required': true, 'minItems': 0, 'items': { 'type': 'object', 'properties': { 'flavorId': { 'type': 'string', 'required': true }, 'quantity': { 'type': 'number', 'required': true } } } }, 'fainaQuantity': { 'type': 'number', 'required': true } }, 'required': true }, 'delivery': { 'type': 'object', 'properties': { 'pickUp': { 'type': 'boolean', 'required': true }, 'phone': { 'type': 'string', 'required': true }, 'name': { 'type': 'string', 'required': true }, 'address': { 'type': 'string', 'required': false } }, 'required': true } } }; describe('Validator', () => { const comboValidator = validator(ComboSchema); const orderValidator = validator(OrderSchema, (schema, object, id, errors, endValidation) => { if (object.order.pizzas && object.order.pizzas.length > 0) { object.order.pizzas.forEach((pizza) => { if (pizza.flavors && pizza.flavors.length > 0) { let portions = 0; pizza.flavors.forEach((flavor) => { switch (flavor.portion) { case 'FULL': portions += 4; break; case 'HALF': portions += 2; break; case 'QUARTER': portions += 1; break; } }); if (portions !== 4) { errors.push(`validation.error.${schema.description}.flavor.qty`); } } }); } if (object.delivery && !object.delivery.pickUp && !object.delivery.address) { errors.push(`validation.error.${schema.description}.delivery.address`); } endValidation(); }); it('no errors should be raised if object is valid', (done) => { const caseObject = { 'order': { 'combos': [ {'quantity': 1, 'comboId': '5828d73f59250039ffeeec6a'}, {'quantity': 2, 'comboId': '5828d76959250039ffeeec71'} ], 'pizzas': [ { 'size': 'giant', 'flavors': [ { 'portion': 'FULL', 'flavorId': '5828cb9059250039ffeeebf5' } ] }, { 'size': 'classic', 'flavors': [ { 'portion': 'HALF', 'flavorId': '5828cb9059250039ffeeebf5' }, { 'portion': 'QUARTER', 'flavorId': '5828cff459250039ffeeec19' }, { 'portion': 'QUARTER', 'flavorId': '5828cb7959250039ffeeebf2' } ] } ], 'patties': [ {'flavorId': '5828ddb059250039ffeeecd3', 'quantity': 6}, {'flavorId': '5828dcbe59250039ffeeeca6', 'quantity': 4}, {'flavorId': '5828dd4e59250039ffeeecc1', 'quantity': 2}, {'flavorId': '5828dd9959250039ffeeeccd', 'quantity': 12} ], 'fainaQuantity': 5 }, 'delivery': { 'pickUp': true, 'phone': '1132287295', 'name': 'Seba' } }; orderValidator.validate(caseObject) .then(() => done()) .catch((err) => done(err)); }); it('custom errors should be raised if object does not complies with custom validation', (done) => { const caseObject = { 'order': { 'combos': [ {'quantity': 1, 'comboId': '5828d73f59250039ffeeec6a'}, {'quantity': 2, 'comboId': '5828d76959250039ffeeec71'} ], 'pizzas': [ { 'size': 'giant', 'flavors': [ { 'portion': 'FULL', 'flavorId': '5828cb9059250039ffeeebf5' } ] }, { 'size': 'classic', 'flavors': [ { 'portion': 'HALF', 'flavorId': '5828cb9059250039ffeeebf5' }, { 'portion': 'HALF', 'flavorId': '5828cff459250039ffeeec19' }, { 'portion': 'QUARTER', 'flavorId': '5828cb7959250039ffeeebf2' } ] } ], 'patties': [ {'flavorId': '5828ddb059250039ffeeecd3', 'quantity': 6}, {'flavorId': '5828dcbe59250039ffeeeca6', 'quantity': 4}, {'flavorId': '5828dd4e59250039ffeeecc1', 'quantity': 2}, {'flavorId': '5828dd9959250039ffeeeccd', 'quantity': 12} ], 'fainaQuantity': 5 }, 'delivery': { 'pickUp': true, 'phone': '1132287295', 'name': 'Seba' } }; orderValidator.validate(caseObject) .then(() => done('expected validation errors')) .catch((err) => { expect(err.errors).to.contain(`validation.error.${OrderSchema.description}.flavor.qty`); }) .then(() => done()) .catch((err) => done(err)); }); it('id errors should be raised if object\'s id doesn\'t match provided id', (done) => { const caseObject = { 'id': '123', 'order': { 'combos': [ {'quantity': 1, 'comboId': '5828d73f59250039ffeeec6a'}, {'quantity': 2, 'comboId': '5828d76959250039ffeeec71'} ], 'pizzas': [ { 'size': 'giant', 'flavors': [ { 'portion': 'FULL', 'flavorId': '5828cb9059250039ffeeebf5' } ] }, { 'size': 'classic', 'flavors': [ { 'portion': 'HALF', 'flavorId': '5828cb9059250039ffeeebf5' }, { 'portion': 'QUARTER', 'flavorId': '5828cff459250039ffeeec19' }, { 'portion': 'QUARTER', 'flavorId': '5828cb7959250039ffeeebf2' } ] } ], 'patties': [ {'flavorId': '5828ddb059250039ffeeecd3', 'quantity': 6}, {'flavorId': '5828dcbe59250039ffeeeca6', 'quantity': 4}, {'flavorId': '5828dd4e59250039ffeeecc1', 'quantity': 2}, {'flavorId': '5828dd9959250039ffeeeccd', 'quantity': 12} ], 'fainaQuantity': 5 }, 'delivery': { 'pickUp': true, 'phone': '1132287295', 'name': 'Seba' } }; orderValidator.validate(caseObject, '234') .then(() => done('expected validation errors')) .catch((err) => { expect(err.errors).to.contain(`validation.error.${OrderSchema.description}.id.match`); }) .then(() => done()) .catch((err) => done(err)); }); it('id errors should be raised if an id is provided but object has none', (done) => { const caseObject = { 'order': { 'combos': [ {'quantity': 1, 'comboId': '5828d73f59250039ffeeec6a'}, {'quantity': 2, 'comboId': '5828d76959250039ffeeec71'} ], 'pizzas': [ { 'size': 'giant', 'flavors': [ { 'portion': 'FULL', 'flavorId': '5828cb9059250039ffeeebf5' } ] }, { 'size': 'classic', 'flavors': [ { 'portion': 'HALF', 'flavorId': '5828cb9059250039ffeeebf5' }, { 'portion': 'QUARTER', 'flavorId': '5828cff459250039ffeeec19' }, { 'portion': 'QUARTER', 'flavorId': '5828cb7959250039ffeeebf2' } ] } ], 'patties': [ {'flavorId': '5828ddb059250039ffeeecd3', 'quantity': 6}, {'flavorId': '5828dcbe59250039ffeeeca6', 'quantity': 4}, {'flavorId': '5828dd4e59250039ffeeecc1', 'quantity': 2}, {'flavorId': '5828dd9959250039ffeeeccd', 'quantity': 12} ], 'fainaQuantity': 5 }, 'delivery': { 'pickUp': true, 'phone': '1132287295', 'name': 'Seba' } }; orderValidator.validate(caseObject, '234') .then(() => done('expected validation errors')) .catch((err) => { expect(err.errors).to.contain(`validation.error.${OrderSchema.description}.schema.instance.id`); }) .then(() => done()) .catch((err) => done(err)); }); it('schema errors should be raised if object doesn\'t comply with provided schema.', (done) => { const caseObject = { 'order': { 'combos': [ {'quantity': 1, 'comboId': '5828d73f59250039ffeeec6a'}, {'quantity': 2} ], 'pizzas': [ { 'size': 'giant', 'flavors': [ { 'portion': 'FULL', 'flavorId': '5828cb9059250039ffeeebf5' } ] }, { 'size': 'classic', 'flavors': [ { 'portion': 'HALF', 'flavorId': '5828cb9059250039ffeeebf5' }, { 'portion': 'QUARTER', 'flavorId': '5828cff459250039ffeeec19' }, { 'portion': 'QUARTER', 'flavorId': '5828cb7959250039ffeeebf2' } ] } ], 'patties': [ {'flavorId': '5828ddb059250039ffeeecd3', 'quantity': 6}, {'flavorId': '5828dcbe59250039ffeeeca6', 'quantity': 4}, {'flavorId': '5828dd4e59250039ffeeecc1', 'quantity': 2}, {'flavorId': '5828dd9959250039ffeeeccd', 'quantity': 12} ], 'fainaQuantity': 5 }, 'delivery': { 'pickUp': true, 'phone': '1132287295', 'name': 'Seba' } }; orderValidator.validate(caseObject) .then(() => done('expected validation errors')) .catch((err) => { expect(err.errors).to.contain(`validation.error.${OrderSchema.description}.schema.instance.order.combos[1].comboId`); }) .then(() => done()) .catch((err) => done(err)); }); it('validator should be capable of validating even when no custom validations are provided', (done) => { const caseObject = { 'pizzaFlavorIds': [1, 2, 3], 'name': 'COMBO 1', 'feeds': 4, 'price': 125.30 }; comboValidator.validate(caseObject) .then(() => done()) .catch((err) => done(err)); }); it('validator should fail on unknown properties (only one) when configured to do so', (done) => { const caseObject = { 'pizzaFlavorIds': [1, 2, 3], 'name': 'COMBO 1', 'feeds': 4, 'price': 125.30, 'someUnknownProp': 1, 'anotherUnknownProp': 2 }; comboValidator.validate(caseObject) .then(() => done('expected validation error')) .catch((err) => { expect(err.name).to.equal('validation.error'); expect(err.errors.length).to.equal(1); expect(err.errors).to.contain('validation.error.combo.schema.unknown.property'); done(); }) .catch((err) => done(err)); }); it('validator should not fail on unknown properties when not configured to do so', (done) => { const caseObject = { 'someUnknownProperty': 1, 'order': { 'combos': [ {'quantity': 1, 'comboId': '5828d73f59250039ffeeec6a'}, {'quantity': 2, 'comboId': '5828d76959250039ffeeec71'} ], 'pizzas': [ { 'size': 'giant', 'flavors': [ { 'portion': 'FULL', 'flavorId': '5828cb9059250039ffeeebf5' } ] }, { 'size': 'classic', 'flavors': [ { 'portion': 'HALF', 'flavorId': '5828cb9059250039ffeeebf5' }, { 'portion': 'QUARTER', 'flavorId': '5828cff459250039ffeeec19' }, { 'portion': 'QUARTER', 'flavorId': '5828cb7959250039ffeeebf2' } ] } ], 'patties': [ {'flavorId': '5828ddb059250039ffeeecd3', 'quantity': 6}, {'flavorId': '5828dcbe59250039ffeeeca6', 'quantity': 4}, {'flavorId': '5828dd4e59250039ffeeecc1', 'quantity': 2}, {'flavorId': '5828dd9959250039ffeeeccd', 'quantity': 12} ], 'fainaQuantity': 5 }, 'delivery': { 'pickUp': true, 'phone': '1132287295', 'name': 'Seba' } }; orderValidator.validate(caseObject) .then(() => done()) .catch((err) => done(err)); }); });