@e22m4u/js-repository
Version:
Реализация репозитория для работы с базами данных в Node.js
2,831 lines • 91.6 kB
JavaScript
import {expect} from 'chai';
import {format} from '@e22m4u/js-format';
import {DataType} from './properties/index.js';
import {DatabaseSchema} from '../../database-schema.js';
import {EmptyValuesService} from '@e22m4u/js-empty-values';
import {ModelDataValidator} from './model-data-validator.js';
import {DefinitionRegistry} from '../definition-registry.js';
import {PropertyValidatorRegistry} from './properties/index.js';
describe('ModelDataValidator', function () {
describe('validate', function () {
it('does not throw an error if a model does not have a property of a given data', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({name: 'model'});
dbs.getService(ModelDataValidator).validate('model', {foo: 'bar'});
});
it('throws an error if a given data is not a pure object', function () {
const throwable = modelData => () => {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
});
dbs.getService(ModelDataValidator).validate('model', modelData);
};
const error = v =>
format(
'The data of the model "model" should be an Object, but %s given.',
v,
);
expect(throwable('str')).to.throw(error('"str"'));
expect(throwable(10)).to.throw(error('10'));
expect(throwable(true)).to.throw(error('true'));
expect(throwable(false)).to.throw(error('false'));
expect(throwable([])).to.throw(error('Array'));
expect(throwable(null)).to.throw(error('null'));
expect(throwable(undefined)).to.throw(error('undefined'));
});
it('uses a base model hierarchy to validate a given data', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'modelA',
properties: {
foo: DataType.STRING,
},
});
dbs.defineModel({
name: 'modelB',
base: 'modelA',
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('modelB', {foo: 10});
expect(throwable).to.throw(
'The property "foo" of the model "modelB" must ' +
'have a String, but Number given.',
);
});
it('throws an error if a given data does not have a required property', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {});
expect(throwable).to.throw(
'The property "foo" of the model "model" ' +
'is required, but undefined given.',
);
});
it('throws an error if a required property is undefined', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {foo: undefined});
expect(throwable).to.throw(
'The property "foo" of the model "model" is required, but undefined given.',
);
});
it('throws an error if a required property is null', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {foo: null});
expect(throwable).to.throw(
'The property "foo" of the model "model" is required, but null given.',
);
});
it('throws an error if a required property has an empty value', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
dbs
.getService(EmptyValuesService)
.setEmptyValuesOf(DataType.STRING, ['empty']);
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {foo: 'empty'});
expect(throwable).to.throw(
'The property "foo" of the model "model" ' +
'is required, but "empty" given.',
);
});
describe('an option "isPartial" is true', function () {
it('does not throw an error if a given data does not have a required property', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {}, true);
});
it('throws an error if a required property is undefined', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
const throwable = () =>
dbs
.getService(ModelDataValidator)
.validate('model', {foo: undefined}, true);
expect(throwable).to.throw(
'The property "foo" of the model "model" ' +
'is required, but undefined given.',
);
});
it('throws an error if a required property is null', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
const throwable = () =>
dbs
.getService(ModelDataValidator)
.validate('model', {foo: null}, true);
expect(throwable).to.throw(
'The property "foo" of the model "model" is required, but null given.',
);
});
it('throws an error if a required property has an empty value', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
required: true,
},
},
});
dbs
.getService(EmptyValuesService)
.setEmptyValuesOf(DataType.STRING, [5]);
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {foo: 5}, true);
expect(throwable).to.throw(
'The property "foo" of the model "model" is required, but 5 given.',
);
});
});
describe('validate by property type', function () {
it('skips validation for an empty value', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
dbs
.getService(EmptyValuesService)
.setEmptyValuesOf(DataType.STRING, [5]);
dbs.getService(ModelDataValidator).validate('model', {foo: 5});
});
describe('DataType.ANY', function () {
describe('ShortPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('does not throw an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
});
it('does not throw an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
});
it('does not throw an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
});
it('does not throw an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
});
it('does not throw an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
});
it('does not throw an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ANY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
});
});
describe('FullPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('does not throw an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
});
it('does not throw an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
});
it('does not throw an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
});
it('does not throw an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
});
it('does not throw an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
});
it('does not throw an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ANY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
});
});
});
describe('DataType.STRING', function () {
describe('ShortPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('does not throw an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Number given.',
);
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Boolean given.',
);
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Array given.',
);
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.STRING,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Object given.',
);
});
});
describe('FullPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('does not throw an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Number given.',
);
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Boolean given.',
);
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Array given.',
);
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.STRING,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a String, but Object given.',
);
});
});
});
describe('DataType.NUMBER', function () {
describe('ShortPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but String given.',
);
});
it('does not throw an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Boolean given.',
);
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Array given.',
);
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.NUMBER,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Object given.',
);
});
});
describe('FullPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but String given.',
);
});
it('does not throw an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Boolean given.',
);
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Array given.',
);
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.NUMBER,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Number, but Object given.',
);
});
});
});
describe('DataType.BOOLEAN', function () {
describe('ShortPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but String given.',
);
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but Number given.',
);
});
it('does not throw an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
});
it('does not throw an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but Array given.',
);
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.BOOLEAN,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but Object given.',
);
});
});
describe('FullPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but String given.',
);
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but Number given.',
);
});
it('does not throw an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
});
it('does not throw an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but Array given.',
);
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.BOOLEAN,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'a Boolean, but Object given.',
);
});
});
});
describe('DataType.ARRAY', function () {
describe('ShortPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but String given.',
);
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Number given.',
);
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Boolean given.',
);
});
it('does not throw an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.ARRAY,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Object given.',
);
});
});
describe('FullPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but String given.',
);
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Number given.',
);
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Boolean given.',
);
});
it('does not throw an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
});
it('throws an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.ARRAY,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Array, but Object given.',
);
});
describe('the "itemModel" option', function () {
it('does not throw an error if the option "itemModel" is not specified in case of Object item type', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ARRAY,
itemType: DataType.OBJECT,
},
},
});
const value = {foo: [{a: 1}, {b: 2}]};
dbs.getService(ModelDataValidator).validate('model', value);
});
it('throws an error when the given object element has an invalid model', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'modelA',
properties: {
foo: DataType.STRING,
},
});
dbs.defineModel({
name: 'modelB',
datasource: 'datasource',
properties: {
bar: {
type: DataType.ARRAY,
itemType: DataType.OBJECT,
itemModel: 'modelA',
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('modelB', {
bar: [{foo: 10}],
});
expect(throwable).to.throw(
'The property "foo" of the model "modelA" must have ' +
'a String, but Number given.',
);
});
it('does not throw an error when the given object element has a valid model', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'modelA',
properties: {
foo: DataType.STRING,
},
});
dbs.defineModel({
name: 'modelB',
datasource: 'datasource',
properties: {
bar: {
type: DataType.ARRAY,
itemType: DataType.OBJECT,
itemModel: 'modelA',
},
},
});
dbs.getService(ModelDataValidator).validate('modelB', {
bar: [{foo: '10'}],
});
});
});
});
});
describe('DataType.OBJECT', function () {
describe('ShortPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but String given.',
);
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Number given.',
);
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Boolean given.',
);
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Array given.',
);
});
it('does not throw an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: DataType.OBJECT,
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
});
});
describe('FullPropertyDefinition', function () {
it('does not throw an error if an undefined given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: undefined,
});
});
it('does not throw an error if a null given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: null,
});
});
it('throws an error if a string given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'bar',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but String given.',
);
});
it('throws an error if a number given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 10,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Number given.',
);
});
it('throws an error if true given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: true,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Boolean given.',
);
});
it('throws an error if false given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: false,
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Boolean given.',
);
});
it('throws an error if an array given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: [],
});
expect(throwable).to.throw(
'The property "foo" of the model "model" must have ' +
'an Object, but Array given.',
);
});
it('does not throw an error if an object given', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
datasource: 'datasource',
properties: {
foo: {
type: DataType.OBJECT,
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: {},
});
});
describe('the "model" option', function () {
it('throws an error when the given object has an invalid model', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'modelA',
properties: {
foo: DataType.STRING,
},
});
dbs.defineModel({
name: 'modelB',
datasource: 'datasource',
properties: {
bar: {
type: DataType.OBJECT,
model: 'modelA',
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('modelB', {
bar: {foo: 10},
});
expect(throwable).to.throw(
'The property "foo" of the model "modelA" must have ' +
'a String, but Number given.',
);
});
it('does not throw an error when the given object has a valid model', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'modelA',
properties: {
foo: DataType.STRING,
},
});
dbs.defineModel({
name: 'modelB',
datasource: 'datasource',
properties: {
bar: {
type: DataType.OBJECT,
model: 'modelA',
},
},
});
dbs.getService(ModelDataValidator).validate('modelB', {
bar: {foo: '10'},
});
});
});
});
});
});
describe('validate by property validators', function () {
it('skips validation for an empty value', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => false);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.STRING,
validate: 'myValidator',
},
},
});
dbs
.getService(EmptyValuesService)
.setEmptyValuesOf(DataType.STRING, [5]);
dbs.getService(ModelDataValidator).validate('model', {foo: 5});
});
describe('the option "validate" with the string value', function () {
it('does not validate a property value if it is not provided', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => false);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
const validator = dbs.getService(ModelDataValidator);
validator.validate('model', {});
});
it('does not validate undefined and null values', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => false);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
const validator = dbs.getService(ModelDataValidator);
validator.validate('model', {foo: undefined});
validator.validate('model', {foo: null});
});
it('throws an error from the validator', function () {
const myValidator = function () {
throw Error('My error');
};
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw('My error');
});
it('allows the given value if the validator returns true', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => true);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
});
it('throws an error if the validator returns a promise', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => Promise.resolve(true));
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw(
'Asynchronous property validators are not supported, ' +
'but the property validator "myValidator" returns a Promise.',
);
});
it('throws an error for non-true result from the validator', function () {
const testFn = v => {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => v);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" has an invalid value "test" ' +
'that caught by the validator "myValidator".',
);
};
testFn('str');
testFn('');
testFn(10);
testFn(0);
testFn(false);
testFn(undefined);
testFn(null);
testFn({});
testFn([]);
testFn(() => undefined);
});
it('passes arguments to the validator', function () {
let validated = false;
const dbs = new DatabaseSchema();
const myValidator = function (value, options, context) {
expect(value).to.be.eq('test');
expect(options).to.be.undefined;
expect(context).to.be.eql({
validatorName: 'myValidator',
modelName: 'model',
propName: 'foo',
});
validated = true;
return true;
};
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(validated).to.be.true;
});
it('invokes the validator only once per value', function () {
let invoked = 0;
const myValidator = function () {
invoked++;
return true;
};
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: 'myValidator',
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(invoked).to.be.eq(1);
});
});
describe('the option "validate" with an array value', function () {
it('does nothing for an empty array validators', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: [],
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
});
it('does not validate a property value if it is not provided', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => false);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator'],
},
},
});
const validator = dbs.getService(ModelDataValidator);
validator.validate('model', {});
});
it('does not validate undefined and null values', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => false);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator'],
},
},
});
const validator = dbs.getService(ModelDataValidator);
validator.validate('model', {foo: undefined});
validator.validate('model', {foo: null});
});
it('throws an error from the validator', function () {
const myValidator = function () {
throw Error('My error');
};
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator'],
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw('My error');
});
it('allows the given value if validators returns true', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator1', () => true)
.addValidator('myValidator2', () => true);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator1', 'myValidator2'],
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
});
it('throws an error if the validator returns a promise', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => Promise.resolve(true));
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator'],
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw(
'Asynchronous property validators are not supported, ' +
'but the property validator "myValidator" returns a Promise.',
);
});
it('throws an error by non-true result from one of validators', function () {
const testFn = v => {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator1', () => true)
.addValidator('myValidator2', () => v);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator1', 'myValidator2'],
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" has an invalid value "test" ' +
'that caught by the validator "myValidator2".',
);
};
testFn('str');
testFn('');
testFn(10);
testFn(0);
testFn(false);
testFn(undefined);
testFn(null);
testFn({});
testFn([]);
testFn(() => undefined);
});
it('passes arguments to the validator', function () {
let validated = false;
const dbs = new DatabaseSchema();
const myValidator = function (value, options, context) {
expect(value).to.be.eq('test');
expect(options).to.be.undefined;
expect(context).to.be.eql({
validatorName: 'myValidator',
modelName: 'model',
propName: 'foo',
});
validated = true;
return true;
};
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator'],
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(validated).to.be.true;
});
it('invokes validators by the given order', function () {
const invocation = [];
const validator1 = function () {
invocation.push('myValidator1');
return true;
};
const validator2 = function () {
invocation.push('myValidator2');
return true;
};
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator1', validator1)
.addValidator('myValidator2', validator2);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: ['myValidator1', 'myValidator2'],
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(invocation).to.be.eql(['myValidator1', 'myValidator2']);
});
});
describe('the option "validate" with an object value', function () {
it('does nothing for an empty validators object', function () {
const dbs = new DatabaseSchema();
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {},
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
});
it('does not validate a property value if it is not provided', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => false);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator: true,
},
},
},
});
const validator = dbs.getService(ModelDataValidator);
validator.validate('model', {});
});
it('does not validate undefined and null values', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => false);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator: true,
},
},
},
});
const validator = dbs.getService(ModelDataValidator);
validator.validate('model', {foo: undefined});
validator.validate('model', {foo: null});
});
it('throws an error from the validator', function () {
const myValidator = function () {
throw Error('My error');
};
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator: true,
},
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw('My error');
});
it('allows the given value if validators returns true', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator1', () => true)
.addValidator('myValidator2', () => true);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator1: true,
myValidator2: true,
},
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
});
it('throws an error if the validator returns a promise', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => Promise.resolve(true));
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator: true,
},
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw(
'Asynchronous property validators are not supported, ' +
'but the property validator "myValidator" returns a Promise.',
);
});
it('throws an error by non-true result from one of validators', function () {
const testFn = v => {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator1', () => true)
.addValidator('myValidator2', () => v);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator1: true,
myValidator2: true,
},
},
},
});
const throwable = () =>
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(throwable).to.throw(
'The property "foo" of the model "model" has an invalid value "test" ' +
'that caught by the validator "myValidator2".',
);
};
testFn('str');
testFn('');
testFn(10);
testFn(0);
testFn(false);
testFn(undefined);
testFn(null);
testFn({});
testFn([]);
testFn(() => undefined);
});
it('passes arguments to the validator', function () {
let validated = false;
const dbs = new DatabaseSchema();
const myValidator = function (value, options, context) {
expect(value).to.be.eq('test');
expect(options).to.be.eql({
option1: 'value1',
option2: 'value2',
});
expect(context).to.be.eql({
validatorName: 'myValidator',
modelName: 'model',
propName: 'foo',
});
validated = true;
return true;
};
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator: {
option1: 'value1',
option2: 'value2',
},
},
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(validated).to.be.true;
});
it('invokes validators by the given order', function () {
const invocation = [];
const validator1 = function () {
invocation.push('myValidator1');
return true;
};
const validator2 = function () {
invocation.push('myValidator2');
return true;
};
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator1', validator1)
.addValidator('myValidator2', validator2);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator1: true,
myValidator2: true,
},
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(invocation).to.be.eql(['myValidator1', 'myValidator2']);
});
it('validates even the validator options is false', function () {
let validated = false;
const myValidator = function () {
validated = true;
return true;
};
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', myValidator);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: {
myValidator: false,
},
},
},
});
dbs.getService(ModelDataValidator).validate('model', {
foo: 'test',
});
expect(validated).to.be.true;
});
});
it('the option "validate" requires a non-empty String, an Array or an Object', function () {
const dbs = new DatabaseSchema();
dbs
.getService(PropertyValidatorRegistry)
.addValidator('myValidator', () => true);
dbs.defineModel({
name: 'model',
properties: {
foo: {
type: DataType.ANY,
validate: undefined,
},
},
});
const V = dbs.getService(ModelDataValidator);
const throwable = v => () => {
const models = dbs.getService(DefinitionRegistry)['_models'];
models.model.properties.foo.validate = v;
V.validate('model', {foo: 'bar'});
};
const error = v =>
format(
'The provided option "validate" of the property "foo" in the model "model" ' +
'should be a non-empty String, an Array of String or an Object, ' +
'but %s given.',
v,
);
expect(throwable('')).to.throw(error('""'));
expect(throwable(10)).to.throw(error('10'));
expect(throwable(0)).to.throw(error('0'));
expect(throwable(true)).to.throw(error('true'));
expect(throwable(false)).to.throw(error('false'));
throwable('myValidator')();
throwable(['myValidator'])();
throwable([])();
throwable({myValidator: true})();
throwable({})();
});
});
});
});