UNPKG

gotta-validate

Version:

A POJO object validator for node, built with resources, promises, and testing in mind.

657 lines (563 loc) 14.7 kB
'use strict'; var q = require('q'); var GottaValidate; // TODO: Clear cache before each test it seems a lot of reuse of rules/resources is happening. BAD! describe('gotta validate', function () { beforeEach(function () { require.cache = undefined; GottaValidate = require('./index'); }); describe('instantiation', function () { it('should throw error if resource is not defined', function () { expect(function () { GottaValidate({ resource: 'not-defined', mode: 'not-defined' }); }).toThrow(Error('Resource is not defined, add one via. GottaValidate.addResource({}) before trying to instantiate!')); }); it('should throw error if mode is not defined', function () { expect(function () { GottaValidate.addRule({ name: 'defined', func: function () {} }); GottaValidate.addResource({ name: 'name', mode: 'create', rules: { propertyName: 'defined', anotherProperty: ['defined'] } }); GottaValidate({ resource: 'name', mode: 'not-defined' }); }).toThrow(Error('Resource mode is not defined, add one via. GottaValidate.addResource({}) before trying to instantiate!')); }); }); describe('adding rule', function () { it('should throw error if no object is passed in', function () { expect(function () { GottaValidate.addRule(); }).toThrow(Error('Pass a rule object in!')); }); it('should throw error if name isnt defined', function () { expect(function () { GottaValidate.addRule({}); }).toThrow(Error('Name must be a string!')); }); it('should throw error if rule isnt a function', function () { expect(function () { GottaValidate.addRule({ name: 'ayylmao' }); }).toThrow(Error('Rule must be a function!')); }); it('should throw error when inheriting with string if rule not found', function () { expect(function () { GottaValidate.addRule({ name: 'cool-rule', func: function () {}, inherits: 'ayyy' }); }).toThrow(Error('Rule [ayyy] not found, add it before trying to inherit')); }); it('should throw error when inheriting with array if rule not found', function () { expect(function () { GottaValidate.addRule({ name: 'cool-rule', func: function () {}, inherits: ['ayyy'] }); }).toThrow(Error(['Rule [ayyy] not found, add it before trying to inherit'])); }); }); describe('adding resource', function () { it('should throw three errors on empty object', function () { expect(function () { GottaValidate.addResource({}); }).toThrow(Error( [ 'Name not defined', 'Mode not defined', 'Rules not defined' ])); }); it('should throw error if rules isnt an object', function () { expect(function () { GottaValidate.addResource({ name: 'name', mode: 'create', rules: 'not an object' }); }).toThrow(Error('Rules has to be an object!')); }); it('should throw error if rule doesnt exist for complex object', function () { expect(function () { GottaValidate.addResource({ name: 'name', mode: 'create', rules: { tokens: { token: 'ahh' } } }); }).toThrow(Error('Rule "ahh" for property [token] is not defined. Add it before adding a resource!')); }); it('should allow complex objects to be validated', function () { GottaValidate.addDefaultRules(); expect(function () { GottaValidate.addResource({ name: 'name', mode: 'create', rules: { tokens: { token: 'required' } } }); }).not.toThrow(); }); it('should throw error if any of the rules are arent defined', function () { expect(function () { GottaValidate.addResource({ name: 'name', mode: 'create', rules: { propertyName: 'not defined', anotherProperty: ['not-defined'] } }); }) .toThrow(Error([ 'Rule "not defined" for property [propertyName] is not defined. Add it before adding a resource!', 'Rule "not-defined" for property [anotherProperty] is not defined. Add it before adding a resource!', ])); }); it('should add successfully', function () { expect(function () { GottaValidate.addRule({ name: 'defined', func: function () {} }) .addRule({ name: 'swag', func: function () {} }); GottaValidate.addResource({ name: 'name', mode: 'create', rules: { propertyName: 'defined', anotherProperty: ['swag'] } }) .addResource({ name: 'another-resource', mode: 'update', rules: { propertyName: 'swag', anotherProperty: ['defined'] } }); }).not.toThrow(); }); }); describe('runner', function () { var systemUnderTest; var promiseRuleDefer; GottaValidate = require('./index'); beforeEach(function () { GottaValidate.addRule({ name: 'required-synchronous', func: function (name, val) { if(!val) { return 'is required'; } } }); GottaValidate.addRule({ name: 'promise-with-dependency', func: function (name, val, dependencies) { expect(dependencies.a).toBeDefined(); expect(dependencies.a.hey).toBe('im defined'); promiseRuleDefer = q.defer(); return promiseRuleDefer.promise; }, dependencies: { a: { hey: 'im defined' } } }); GottaValidate.addResource({ name: 'user', mode: 'create', rules: { email: 'required-synchronous', uniqueEmail: 'promise-with-dependency' } }); GottaValidate.addResource({ name: 'user', mode: 'update', rules: { email: ['required-synchronous', 'promise-with-dependency'] } }); }); it ('should throw error if object isnt passed in', function () { systemUnderTest = GottaValidate({ resource: 'user', mode: 'create' }); expect(function () { systemUnderTest.validate(); }).toThrow(Error('Only objects can be validated.')); }); describe('with single rule', function () { it ('should resolve promise with error email is required', function (done) { systemUnderTest = GottaValidate({ resource: 'user', mode: 'create' }); systemUnderTest.validate({}) .then(null, function (e) { expect(e).toEqual([ '[email] is required' ]); done(); }); promiseRuleDefer.resolve(); }); it ('should resolve promise', function (done) { systemUnderTest = GottaValidate({ resource: 'user', mode: 'create' }); systemUnderTest.validate({ email: 'email@email.com' }) .then(function (e) { done(); }); promiseRuleDefer.resolve(); }); it ('should reject promise with unique email is required error', function (done) { systemUnderTest = GottaValidate({ resource: 'user', mode: 'create' }); systemUnderTest.validate({ email: 'im here', uniqueEmail: 'cool@email.com' }) .then(null, function (e) { expect(e).toEqual([ '[uniqueEmail] is taken' ]); done(); }); promiseRuleDefer.resolve({ message: 'is taken', property: 'uniqueEmail' }); }); it ('should reject promise with required and unique error', function (done) { systemUnderTest = GottaValidate({ resource: 'user', mode: 'create' }); systemUnderTest.validate({ uniqueEmail: 'cool@email.com' }) .then(null, function (e) { expect(e).toEqual([ '[email] is required', '[uniqueEmail] is taken' ]); done(); }); promiseRuleDefer.resolve({ message: 'is taken', property: 'uniqueEmail' }); }); it ('should call inherited rules', function (done) { var inheritPromiseRuleDefer; GottaValidate.addRule({ name: 'sync-rule', func: function () { return 'ayy sync'; } }); GottaValidate.addRule({ name: 'promise-rule-with-inheritance', func: function (name, object) { inheritPromiseRuleDefer = q.defer(); return inheritPromiseRuleDefer.promise; }, inherits: 'sync-rule' }); GottaValidate.addResource({ name: 'cool', mode: 'cooler', rules: { prop1: 'promise-rule-with-inheritance' } }); systemUnderTest = GottaValidate({ resource: 'cool', mode: 'cooler' }); systemUnderTest.validate({ prop1: 'lol' }) .then(null, function (e) { expect(e).toEqual([ '[prop1] ayy sync', '[prop1] is cool' ]); done(); }); inheritPromiseRuleDefer.resolve({ message: 'is cool', property: 'prop1' }); }); it ('should throw if inherited rule doesnt exist', function () { expect(function () { GottaValidate.addRule({ name: 'promise-rule-with-inheritance', func: function (name, val) { inheritPromiseRuleDefer = q.defer(); return inheritPromiseRuleDefer.promise; }, inherits: 'no-exist' }); }).toThrow(Error('Rule [no-exist] not found, add it before trying to inherit')); }); }); describe('with array of rules', function () { it ('should reject promise with unique error', function (done) { systemUnderTest = GottaValidate({ resource: 'user', mode: 'update' }); systemUnderTest.validate({ email: 'cool@email.com' }) .then(null, function (e) { expect(e).toEqual([ '[email] is taken' ]); done(); }); promiseRuleDefer.resolve({ message: 'is taken', property: 'email' }); }); it ('should reject promise with required error', function (done) { systemUnderTest = GottaValidate({ resource: 'user', mode: 'update' }); systemUnderTest.validate({}) .then(null, function (e) { expect(e).toEqual([ '[email] is required' ]); done(); }); promiseRuleDefer.resolve(); }); it ('should call inherited rules', function (done) { var inheritPromiseRuleDefer; GottaValidate.addRule({ name: 'sync-rule', func: function () { return 'ayy sync'; } }); GottaValidate.addRule({ name: 'promise-rule-with-inheritance', func: function (name, val) { inheritPromiseRuleDefer = q.defer(); return inheritPromiseRuleDefer.promise; }, inherits: ['sync-rule'] }); GottaValidate.addResource({ name: 'cool', mode: 'cooler', rules: { prop1: 'promise-rule-with-inheritance' } }); systemUnderTest = GottaValidate({ resource: 'cool', mode: 'cooler' }); systemUnderTest.validate({ prop1: 'lol' }) .then(null, function (e) { expect(e).toEqual([ '[prop1] ayy sync', '[prop1] is cool' ]); done(); }); inheritPromiseRuleDefer.resolve({ message: 'is cool', property: 'prop1' }); }); it ('should throw if inherited rule doesnt exist', function () { expect(function () { GottaValidate.addRule({ name: 'promise-rule-with-inheritance', func: function (name, object) { inheritPromiseRuleDefer = q.defer(); return inheritPromiseRuleDefer.promise; }, inherits: ['no-exist'] }); }).toThrow(Error(['Rule [no-exist] not found, add it before trying to inherit'])); }); }); describe('with complex objects', function () { GottaValidate.addRule({ name: 'lmao', func: function () { return 'ur bad bro'; } }); GottaValidate.addRule({ name: 'heheaa', func: function () { return 'haha wtf'; } }); GottaValidate.addResource({ name: 'lol', mode: 'cats', rules: { tokens: { token: ['lmao', 'heheaa'] } } }); GottaValidate.addRule({ name: 't1', func: function (name, val) { if (val === 'token_one') { return 't1 found!'; } } }); GottaValidate.addRule({ name: 't2', func: function (name, val) { if (val === 'token_two') { return 't2 found!'; } } }); GottaValidate.addResource({ name: 'lol', mode: 'arraysdoe', rules: { ayyy: { ok: ['t1', 't2'] } } }); describe('that have array inputs', function () { it('should reject with errors', function (done) { var sut = GottaValidate({ resource: 'lol', mode: 'arraysdoe' }); sut.validate({ ayyy: { ok: [ 'token_one', 'token_two' ] } }) .then(null, function (e) { expect(e).toEqual([ '[ok] t1 found!', '[ok] t2 found!' ]); done(); }); }); }); describe('objects', function () { it('should reject wither errors', function (done) { var sut = GottaValidate({ resource: 'lol', mode: 'cats' }); sut.validate({}) .then(null, function (e) { expect(e).toEqual([ '[token] ur bad bro', '[token] haha wtf' ]); done(); }); }); }); }); }); describe('pre defined rules', function () { it('should have required', function () { GottaValidate.addDefaultRules(); GottaValidate.addResource({ name: 'resource', mode: 'mode', rules: { property: 'required' } }); }); it('should have noWhiteSpace', function () { GottaValidate.addDefaultRules(); GottaValidate.addResource({ name: 'resource', mode: 'mode', rules: { property: 'no-white-space' } }); }); it('should have password', function () { GottaValidate.addDefaultRules(); GottaValidate.addResource({ name: 'resource', mode: 'mode', rules: { property: 'password' } }); }); it('should have email', function () { GottaValidate.addDefaultRules(); GottaValidate.addResource({ name: 'resource', mode: 'mode', rules: { property: 'email' } }); }); }); });