@rawmodel/schema
Version:
JSON Schema utils for RawModel.
211 lines (198 loc) • 4.35 kB
text/typescript
import { Model } from '@rawmodel/core';
import { Spec } from '@hayspec/spec';
import { stringParser } from '@rawmodel/parsers';
import { stringLengthValidator } from '@rawmodel/validators';
import { createModelClass } from '../../..';
const spec = new Spec();
spec.test('generates empty model class', (ctx) => {
const Klass = createModelClass({});
ctx.true(new Klass() instanceof Model);
});
spec.test('generates model with properties', (ctx) => {
const Klass = createModelClass({
props: [
{ name: 'firstName' },
{ name: 'lastName' },
],
});
const data = {
firstName: 'John',
lastName: 'Smith',
};
const model = new Klass(data);
ctx.deepEqual(model.serialize(), data);
});
spec.test('supports property custom getter', (ctx) => {
const Klass = createModelClass({
getters: {
foo () { return () => 'foo'; },
},
props: [
{
name: 'firstName',
getter: 'foo',
},
],
});
const model = new Klass();
ctx.deepEqual(model.serialize(), {
firstName: 'foo',
});
});
spec.test('supports property custom setter', (ctx) => {
const Klass = createModelClass({
setters: {
foo () { return () => 'foo'; },
},
props: [
{
name: 'firstName',
setter: 'foo',
},
],
});
const model = new Klass({
firstName: 'bar',
});
ctx.deepEqual(model.serialize(), {
firstName: 'foo',
});
});
spec.test('supports property default value', (ctx) => {
const Klass = createModelClass({
defaultValues: {
smithName() { return 'Smith'; },
},
props: [
{
name: 'firstName',
defaultValue: 'John',
},
{
name: 'lastName',
defaultValue: 'smithName',
},
],
});
const model = new Klass();
ctx.deepEqual(model.serialize(), {
firstName: 'John',
lastName: 'Smith',
});
});
spec.test('supports property fake value', (ctx) => {
const Klass = createModelClass({
fakeValues: {
smithName() { return 'Smith'; },
},
props: [
{
name: 'firstName',
fakeValue: 'John',
},
{
name: 'lastName',
fakeValue: 'smithName',
},
],
});
const model = new Klass().fake();
ctx.deepEqual(model.serialize(), {
firstName: 'John',
lastName: 'Smith',
});
});
spec.test('supports property empty value', (ctx) => {
const Klass = createModelClass({
emptyValues: {
emptyString() { return ''; },
},
props: [
{
name: 'firstName',
emptyValue: 'none',
},
{
name: 'lastName',
emptyValue: 'emptyString',
},
],
});
const model = new Klass();
ctx.deepEqual(model.serialize(), {
firstName: 'none',
lastName: '',
});
});
spec.test('supports property parsers', (ctx) => {
const Klass = createModelClass({
parsers: {
string: stringParser,
},
props: [
{
name: 'firstName',
parser: {
array: true,
resolver: 'string',
},
},
],
});
const model = new Klass({
firstName: 100,
});
ctx.deepEqual(model.serialize(), {
firstName: ['100'],
});
});
spec.test('supports property validators', async (ctx) => {
const Klass = createModelClass({
validators: {
stringLength: stringLengthValidator,
},
props: [
{
name: 'firstName',
validators: [
{
resolver: 'stringLength',
code: 400,
options: { min: 5 },
},
],
},
],
});
const model = new Klass({
firstName: '123',
});
await ctx.throws(() => model.validate());
ctx.deepEqual(model.collectErrors(), [
{ path: ['firstName'], code: 400 },
]);
});
spec.test('supports property handlers', async (ctx) => {
const Klass = createModelClass({
handlers: {
generalError() { return (e: any) => true; },
},
props: [
{
name: 'firstName',
handlers: [
{
resolver: 'generalError',
code: 400,
},
],
},
],
});
const model = new Klass();
await ctx.throws(() => model.handle(new Error(), { quiet: false }));
ctx.deepEqual(model.collectErrors(), [
{ path: ['firstName'], code: 400 },
]);
});
export default spec;