UNPKG

octonom

Version:

Object Document Mapper for any database

145 lines (128 loc) 5.77 kB
import { ArrayCollection } from '../array-collection'; import { SanitizationError, ValidationError } from '../errors'; import { Model } from '../model'; import { ModelSchema } from './model'; import { ReferenceSchema } from './reference'; import { StringSchema } from './string'; describe('ModelSchema', () => { class ReferencedModel extends Model { public id: string; } ReferencedModel.setSchema('id', new StringSchema()); class TestModel extends Model { public foo: string; public reference: string | ReferencedModel; } TestModel.setSchema('foo', new StringSchema()); TestModel.setSchema('reference', new ReferenceSchema({collection: () => collection})); const collection = new ArrayCollection<ReferencedModel>(ReferencedModel, {modelIdField: 'id'}); const referencedInstance = new ReferencedModel({id: '0xACAB'}); collection.insert(referencedInstance); describe('constructor()', () => { it('should be instantiatable with options', () => { const schema = new ModelSchema({model: TestModel}); expect(schema).to.have.property('options').that.eql({model: TestModel}); }); }); describe('sanitize()', () => { it('should throw a SanitizationError if value is not an object and not a model instance', () => { const schema = new ModelSchema({model: TestModel}); expect(() => schema.create('foo')) .to.throw(SanitizationError, 'Value is not an object.'); }); it('should throw a SanitizationError if model sanitization fails', () => { const schema = new ModelSchema({model: TestModel}); expect(() => schema.create({foo: 42})) .to.throw(SanitizationError, 'Value is not a string.'); }); it('should return undefined', () => { const schema = new ModelSchema({model: TestModel}); expect(schema.create(undefined)).to.eql(undefined); }); it('should return an empty model instance if undefined and required and defaults are enabled', () => { const schema = new ModelSchema({required: true, model: TestModel}); expect(schema.create(undefined, {defaults: true})) .to.have.property('value').that.is.an.instanceOf(TestModel).and.to.eql({}); }); it('should return a model instance', () => { const schema = new ModelSchema({model: TestModel}); const instance = new TestModel(); expect(schema.create(instance)) .to.have.property('value').that.eql(instance).and.not.equals(instance); }); it('should return a model instance when an object was provided', () => { const schema = new ModelSchema({model: TestModel}); expect(schema.create({foo: 'bar'})) .to.have.property('value').that.is.instanceOf(TestModel).and.to.eql({foo: 'bar'}); }); }); describe('populate()', () => { it('should throw if populateReference is not an object', async () => { const schema = new ModelSchema({model: TestModel}); await expect(schema.populate(schema.create(new TestModel()), true)) .to.be.rejectedWith(Error, 'populateReference must be an object.'); }); it('should populate a reference', async () => { const schema = new ModelSchema<TestModel>({model: TestModel}); const instance = schema.create({reference: '0xACAB'}); const result = await schema.populate(instance, {reference: true}); expect(result).to.equal(instance.value); expect(result).to.eql({reference: {id: '0xACAB'}}); expect(result.reference).to.be.an.instanceOf(ReferencedModel); }); }); describe('toObject()', () => { it('should return an object', () => { const schema = new ModelSchema({model: TestModel}); const instance = schema.create(new TestModel({foo: 'bar'})); const obj = schema.toObject(instance); expect(obj).to.not.equal(instance); expect(obj).to.eql({foo: 'bar'}); }); }); describe('validate()', () => { it('should throw if nested validator fails', async () => { class FailModel extends Model { public foo: string; } FailModel.setSchema('foo', new StringSchema({ validate: async instance => { if (instance.value === 'baz') { throw new ValidationError('baz is not allowed.'); } if (instance.value === 'err') { throw new Error('Critical error.'); } }, })); const schema = new ModelSchema({model: FailModel}); await schema.validate(schema.create(new FailModel({foo: 'bar'}))); await expect(schema.validate(schema.create(new FailModel({foo: 'baz'})))) .to.be.rejectedWith(ValidationError, 'baz is not allowed.'); await expect(schema.validate(schema.create(new FailModel({foo: 'err'})))) .to.be.rejectedWith(Error, 'Critical error.'); }); it('should run custom validator', async () => { const schema = new ModelSchema<TestModel>({ model: TestModel, validate: async instance => { if (instance.value.foo === 'baz') { throw new ValidationError('baz is not allowed.'); } if (instance.value.foo === 'err') { throw new Error('Critical error.'); } }, }); await schema.validate(schema.create(new TestModel({foo: 'bar'}))); await expect(schema.validate(schema.create(new TestModel({foo: 'baz'})))) .to.be.rejectedWith(ValidationError, 'baz is not allowed.'); await expect(schema.validate(schema.create(new TestModel({foo: 'err'})))) .to.be.rejectedWith(Error, 'Critical error.'); }); it('should validate a model instance', async () => { const schema = new ModelSchema({model: TestModel}); await schema.validate(schema.create(new TestModel({foo: 'bar'}))); }); }); });