feat(blocksTools): mockBlockProps to provide schema errors

This commit is contained in:
Gervwyk 2020-10-28 15:23:39 +02:00
parent c5bd4ebc9a
commit 6c192d42b0
8 changed files with 177 additions and 49 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@lowdefy/block-tools",
"version": "1.0.1-alpha.4",
"version": "1.0.1-alpha.5",
"licence": "Apache-2.0",
"description": "Lowdefy Block Tools",
"homepage": "https://lowdefy.com",

View File

@ -0,0 +1,53 @@
{
"type": "object",
"additionalProperties": false,
"required": [
"id",
"type"
],
"properties": {
"id": {
"type": "string"
},
"required": {
"type": [
"boolean",
"object"
]
},
"type": {
"type": "string"
},
"properties": {
"type": "object"
},
"layout": {
"type": "object"
},
"blocks": {
"type": "array",
"items": {
"type": "object"
}
},
"actions": {
"type": "object"
},
"areas": {
"type": "object",
"patternProperties": {
"^.*$": {
"type": "object",
"properties": {
"blocks": {
"type": "array",
"items": {
"type": "object"
}
}
}
}
}
}
}
}

View File

@ -15,7 +15,17 @@
*/
import React, { useState } from 'react';
import Ajv from 'ajv';
import AjvErrors from 'ajv-errors';
import { type } from '@lowdefy/helpers';
import blockSchema from './blockSchema.json';
const initAjv = (options) => {
const ajv = new Ajv({ allErrors: true, jsonPointers: true, ...options });
AjvErrors(ajv, options);
return ajv;
};
const ajvInstance = initAjv();
const mockBlockProps = ({ block, meta, logger }) => {
const [value, setState] = useState(type.enforceType(meta.valueType, null));
@ -25,6 +35,12 @@ const mockBlockProps = ({ block, meta, logger }) => {
let log = alert;
if (logger) log = logger;
// evaluate block schema
blockSchema.properties = { ...blockSchema.properties, ...meta.schema };
const validate = ajvInstance.compile(blockSchema);
block.schemaErrors = !validate(block);
if (block.schemaErrors) block.schemaErrors = validate.errors;
// block defaults
block.blockId = block.id;
if (meta.category === 'list' || meta.category === 'container' || meta.category === 'context') {

View File

@ -51,6 +51,7 @@ test('basic display', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Display",
}
`);
@ -78,6 +79,17 @@ test('basic display with methods', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": Array [
Object {
"dataPath": "",
"keyword": "additionalProperties",
"message": "should NOT have additional properties",
"params": Object {
"additionalProperty": "methods",
},
"schemaPath": "#/additionalProperties",
},
],
"type": "Display",
}
`);
@ -106,6 +118,7 @@ test('basic input', () => {
"registerMethod": [Function],
"setValue": [Function],
},
"schemaErrors": false,
"type": "Input",
"value": null,
}
@ -132,6 +145,7 @@ test('input setState', () => {
"registerMethod": [Function],
"setValue": [Function],
},
"schemaErrors": false,
"type": "Input",
"value": null,
}
@ -163,6 +177,7 @@ test('basic container', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Container",
}
`);
@ -191,6 +206,7 @@ test('basic context', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Context",
}
`);
@ -222,6 +238,7 @@ test('basic list', () => {
"removeItem": [Function],
"unshiftItem": [Function],
},
"schemaErrors": false,
"type": "List",
}
`);
@ -254,6 +271,7 @@ test('list methods', () => {
"removeItem": [Function],
"unshiftItem": [Function],
},
"schemaErrors": false,
"type": "List",
}
`);
@ -308,6 +326,7 @@ test('blocks container', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Container",
}
`);
@ -368,6 +387,7 @@ test('blocks areas container', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Container",
}
`);
@ -415,6 +435,7 @@ test('areas container', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Container",
}
`);
@ -462,6 +483,7 @@ test('areas context', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Context",
}
`);
@ -516,6 +538,7 @@ test('areas list', () => {
"removeItem": [Function],
"unshiftItem": [Function],
},
"schemaErrors": false,
"type": "List",
}
`);
@ -556,6 +579,7 @@ test('actions display', () => {
"registerAction": [Function],
"registerMethod": [Function],
},
"schemaErrors": false,
"type": "Display",
}
`);
@ -564,3 +588,76 @@ test('actions display', () => {
res.methods.registerMethod({ action: 'open' });
expect(logger).toBeCalledTimes(3);
});
test('provide schema errors', () => {
let block = {
id: 'a',
type: 'Display',
properties: {
mistake: true,
},
};
const meta = {
category: 'display',
schema: {
properties: {
type: 'object',
additionalProperties: false,
properties: {
mistake: {
type: 'boolean',
},
},
},
},
};
expect(mockBlockProps({ block, meta })).toMatchInlineSnapshot(`
Object {
"blockId": "a",
"id": "a",
"methods": Object {
"callAction": [Function],
"registerAction": [Function],
"registerMethod": [Function],
},
"properties": Object {
"mistake": true,
},
"schemaErrors": false,
"type": "Display",
}
`);
block = {
id: 'a',
type: 'Display',
properties: {
mistake: 1,
},
};
expect(mockBlockProps({ block, meta })).toMatchInlineSnapshot(`
Object {
"blockId": "a",
"id": "a",
"methods": Object {
"callAction": [Function],
"registerAction": [Function],
"registerMethod": [Function],
},
"properties": Object {
"mistake": 1,
},
"schemaErrors": Array [
Object {
"dataPath": "/properties/mistake",
"keyword": "type",
"message": "should be boolean",
"params": Object {
"type": "boolean",
},
"schemaPath": "#/properties/properties/properties/mistake/type",
},
],
"type": "Display",
}
`);
});

View File

@ -16,6 +16,7 @@
import Ajv from 'ajv';
import AjvErrors from 'ajv-errors';
import blockSchema from './blockSchema.json';
const initAjv = (options) => {
const ajv = new Ajv({ allErrors: true, jsonPointers: true, ...options });
@ -23,51 +24,6 @@ const initAjv = (options) => {
return ajv;
};
const blockSchema = {
type: 'object',
additionalProperties: false,
required: ['id', 'type'],
properties: {
id: {
type: 'string',
},
type: {
type: 'string',
},
properties: {
type: 'object',
},
layout: {
type: 'object',
},
blocks: {
type: 'array',
items: {
type: 'object',
},
},
actions: {
type: 'object',
},
areas: {
type: 'object',
patternProperties: {
'^.*$': {
type: 'object',
properties: {
blocks: {
type: 'array',
items: {
type: 'object',
},
},
},
},
},
},
},
};
const ajvInstance = initAjv();
const runBlockSchemaTests = ({ examples, meta }) => {
blockSchema.properties = { ...blockSchema.properties, ...meta.schema };

View File

@ -55,6 +55,12 @@
"$ref": "#/definitions/request"
}
},
"required": {
"type": [
"boolean",
"object"
]
},
"mutations": {
"type": "array",
"items": {

View File

@ -33,7 +33,7 @@
"version:major": "yarn version major -d"
},
"dependencies": {
"@lowdefy/block-tools": "1.0.1-alpha.4",
"@lowdefy/block-tools": "1.0.1-alpha.5",
"@lowdefy/graphql": "0.0.0-experimental.0",
"apollo-server-express": "2.18.2",
"express": "4.17.1",

View File

@ -2794,7 +2794,7 @@ __metadata:
languageName: node
linkType: hard
"@lowdefy/block-tools@1.0.1-alpha.4, @lowdefy/block-tools@workspace:packages/blockTools":
"@lowdefy/block-tools@1.0.1-alpha.5, @lowdefy/block-tools@workspace:packages/blockTools":
version: 0.0.0-use.local
resolution: "@lowdefy/block-tools@workspace:packages/blockTools"
dependencies:
@ -2943,7 +2943,7 @@ __metadata:
dependencies:
"@babel/core": 7.12.3
"@babel/preset-react": 7.12.1
"@lowdefy/block-tools": 1.0.1-alpha.4
"@lowdefy/block-tools": 1.0.1-alpha.5
"@lowdefy/graphql": 0.0.0-experimental.0
apollo-server-express: 2.18.2
babel-loader: 8.1.0