UNPKG

alamid-schema

Version:

Extendable mongoose-like schemas for node.js and the browser

320 lines (258 loc) 12.1 kB
"use strict"; var chai = require("chai"), expect = chai.expect, spies = require('chai-spies'); var Schema = require("../lib/Schema.js"), validators = require("../plugins/validation/validators.js"), validationPlugin = require("../plugins/validation/index.js"); chai.use(spies); chai.Assertion.includeStack = true; function oldEnough(age) { return age > 18 || "too-young"; } function notTooOld(age) { return age < 99 || "too-old"; } Schema.use(validationPlugin); describe("plugins/validation", function () { describe(".prototype", function () { describe(".constructor()", function () { describe("default validators", function () { it("should add a required validator", function () { var schema = new Schema({ name: { type: String, required: true } }); expect(schema.validators.name).to.be.an("array"); expect(schema.validators.name).to.have.length(1); expect(schema.validators.name[0].name).to.eql(validators.required().name); }); it("should add a enum validator", function () { var schema = new Schema({ tags: { type: String, "enum": ["a", "b"] } }); expect(schema.validators.tags).to.be.an("array"); expect(schema.validators.tags).to.have.length(1); expect(schema.validators.tags[0].name).to.eql(validators.enum().name); }); it("should add a min validator", function () { var schema = new Schema({ age: { type: Number, min: 0 } }); expect(schema.validators.age).to.be.an("array"); expect(schema.validators.age).to.have.length(1); expect(schema.validators.age[0].name).to.eql(validators.min().name); }); it("should add a max validator", function () { var schema = new Schema({ age: { type: Number, max: 200 } }); expect(schema.validators.age).to.be.an("array"); expect(schema.validators.age).to.have.length(1); expect(schema.validators.age[0].name).to.eql(validators.max().name); }); }); describe("custom validators", function () { it("should accept a single validation function", function () { var schema = new Schema({ age: { type: Number, validate: oldEnough } }); expect(schema.validators.age).to.be.an("array"); expect(schema.validators.age).to.have.length(1); expect(schema.validators.age[0]).to.eql(oldEnough); }); it("should accept an array of validation functions", function () { var schema = new Schema({ age: { type: Number, validate: [oldEnough, notTooOld] } }); expect(schema.validators.age).to.be.an("array"); expect(schema.validators.age).to.have.length(2); expect(schema.validators.age[0]).to.eql(oldEnough); expect(schema.validators.age[1]).to.eql(notTooOld); }); }); describe("mixed validators", function () { it("should register default validators always before custom validators", function () { var schema = new Schema({ age: { type: Number, min: 1, validate: [oldEnough, notTooOld] } }); expect(schema.validators.age).to.be.an("array"); expect(schema.validators.age).to.have.length(3); expect(schema.validators.age[0].name).to.eql("validateMin"); expect(schema.validators.age[1]).to.eql(oldEnough); expect(schema.validators.age[2]).to.eql(notTooOld); }); }); describe("extended schemas", function () { it("should merge all specified validators", function () { var schema = new Schema({ age: { required: true, max: 99, validate: oldEnough } }), extended = schema.extend({ age: { required: false, validate: notTooOld } }), ageValidators = extended.validators.age.toString(); expect(ageValidators).to.contain(validators.max(), oldEnough, notTooOld); expect(ageValidators).to.not.contain(validators.required()); }); }); }); describe(".validate(model, callback)", function () { var schema; it("should reference the given model to the validation result", function (done) { var model = {}; schema = new Schema({}); schema.validate(model, function (validation) { expect(validation.model).to.equal(model); done(); }); }); it("should work with sync validators", function (done) { schema = new Schema({ age: { type: Number, validate: function (age) { return age > 8; } } }); schema.validate({ age: 18 }, function (validation) { expect(validation.result).to.eql(true); expect(validation.failedFields).to.eql({}); done(); }); }); it("should work with async validators", function (done) { schema = new Schema({ age: { type: Number, validate: function (age, callback) { setTimeout(function () { callback(age > 8); }, 0); } } }); schema.validate({ age: 18 }, function (validation) { expect(validation.result).to.eql(true); expect(validation.failedFields).to.eql({}); done(); }); }); describe("mixed validators", function () { function validateAgeAsync(age, callback) { setTimeout(function () { callback(age > 8 || "fail-async"); }, 0); } function validateAgeSync(age) { return age > 8 || "fail-sync"; } it("should pass if async & sync validators pass", function (done) { var asyncSpy = chai.spy(validateAgeAsync), syncSpy = chai.spy(validateAgeSync); schema = new Schema({ age: { type: Number, validate: [asyncSpy, syncSpy] } }); schema.validate({ age: 18 }, function (validation) { expect(asyncSpy).to.have.been.called.once(); expect(syncSpy).to.have.been.called.once(); expect(validation.result).to.eql(true); expect(validation.failedFields).to.eql({}); done(); }); }); it("should fail if a async and sync validator fail", function (done) { var asyncSpy = chai.spy(validateAgeAsync), syncSpy = chai.spy(validateAgeSync); schema = new Schema({ age: { type: Number, validate: [asyncSpy, syncSpy] } }); schema.validate({ age: 6 }, function (validation) { expect(asyncSpy).to.have.been.called.once(); expect(syncSpy).to.have.been.called.once(); expect(validation.result).to.eql(false); expect(validation.failedFields.age).to.contain("fail-async", "fail-sync"); done(); }); }); it("should fail if the async validator fails & sync passes", function (done) { var asyncSpy = chai.spy(function (age, callback) { setTimeout(function () { callback("fail-async"); }, 0); }), syncSpy = chai.spy(validateAgeSync); schema = new Schema({ age: { type: Number, validate: [asyncSpy, syncSpy] } }); schema.validate({ age: 6 }, function (validation) { expect(asyncSpy).to.have.been.called.once(); expect(syncSpy).to.have.been.called.once(); expect(validation.result).to.eql(false); expect(validation.failedFields.age).to.contain("fail-async"); done(); }); }); it("should fail if the sync validator fails & async passes", function (done) { var asyncSpy = chai.spy(function(age, callback) { callback(true); }), syncSpy = chai.spy(function(age) { return "fail-sync"; }); schema = new Schema({ age: { type: Number, validate: [asyncSpy, syncSpy] } }); schema.validate({ age: 8 }, function (validation) { expect(asyncSpy).to.have.been.called.once(); expect(syncSpy).to.have.been.called.once(); expect(validation.result).to.eql(false); expect(validation.failedFields.age).to.contain("fail-sync"); done(); }); }); }); }); }); });