Skip to content
This repository was archived by the owner on Nov 27, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"json-refs": "^3.0.4",
"material-ui-pickers": "1.0.0-rc.9",
"react": "16.3.2",
"ajv-errors": "^1.0.0",
"react-dom": "^16.3.1",
"react-redux": "^5.0.7",
"recompose": "^0.27.1",
Expand Down
111 changes: 92 additions & 19 deletions src/models/ui-metaschema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { JsonSchema7 } from '@jsonforms/core';

export const uiMetaSchema: JsonSchema7 = {
'$schema': 'http://json-schema.org/draft-07/schema',
'type': 'object',
'$id': '#root',
'properties': {
Expand Down Expand Up @@ -71,10 +73,23 @@ export const uiMetaSchema: JsonSchema7 = {
'$ref': '#/definitions/rule'
}
},
'required': [
'type',
'scope'
]
'required': ['type', 'scope'],
'additionalProperties': false,
'errorMessage': {
'properties': {
'type': 'type should be equal to one of the allowed values',
'scope': 'Control scope should match pattern "^#\\/properties\\/{1}"',
'suggestion': 'Control suggestion should be array',
'options': 'Control options should be object',
'label': 'Control label should be string, boolean or label object'
},
'required': {
'scope': 'Control should have an object property "scope"',
'type': 'Control should have a string property "type"'
},
'additionalProperties': 'Control should not have properties ' +
'other than type, label, scope, options, suggestion and rule'
}
},
'horizontallayout': {
'type': 'object',
Expand All @@ -92,10 +107,18 @@ export const uiMetaSchema: JsonSchema7 = {
'$ref': '#/definitions/rule'
}
},
'required': [
'type',
'elements'
]
'required': ['type', 'elements'],
'additionalProperties': false,
'errorMessage': {
'properties': {
'type': 'type should be equal to one of the allowed values'
},
'required': {
'elements': 'Layout should have an array property "elements"',
'type': 'Layout should have a string property "type"'
},
'additionalProperties': 'Layout should not have properties other than type and elements'
}
},
'verticallayout': {
'type': 'object',
Expand Down Expand Up @@ -137,7 +160,19 @@ export const uiMetaSchema: JsonSchema7 = {
'required': [
'type',
'elements'
]
],
'additionalProperties': false,
'errorMessage': {
'properties': {
'type': 'type should be equal to one of the allowed values'
},
'required': {
'elements': 'Categorization should have an array property "elements"',
'type': 'Categorization should have a string property "type"'
},
'additionalProperties': 'Categorization should not have properties ' +
'other than type and elements'
}
},
'category': {
'type': 'object',
Expand All @@ -158,10 +193,19 @@ export const uiMetaSchema: JsonSchema7 = {
'$ref': '#/definitions/rule'
}
},
'required': [
'type',
'elements'
]
'additionalProperties': false,
'errorMessage': {
'properties': {
'type': 'type should be equal to one of the allowed values',
'label': 'Category label should be string'
},
'required': {
'type': 'Category layout should have a string property "type"',
'elements': 'Category layout should have an array property "elements"'
},
'additionalProperties': 'Category layout should not have properties ' +
'other than type,elements and label'
}
},
'group': {
'type': 'object',
Expand All @@ -179,11 +223,21 @@ export const uiMetaSchema: JsonSchema7 = {
'type': 'string'
}
},
'required': [
'type',
'elements',
'label'
]
'required': ['type', 'elements', 'label'],
'additionalProperties': false,
'errorMessage': {
'properties': {
'type': 'type should be equal to one of the allowed values',
'label': 'Group label should be string'
},
'required': {
'type': 'Group layout should have a string property "type"',
'elements': 'Group layout should have an array property "elements"',
'label': 'Group layout should have a string property "label"'
},
'additionalProperties': 'Group layout should not have properties ' +
'other than type,elements and label'
}
},
'rule': {
'type': 'object',
Expand Down Expand Up @@ -228,6 +282,12 @@ export const uiMetaSchema: JsonSchema7 = {
'dependencies': {
'effect': ['condition'],
'condition': ['effect']
},
'errorMessage': {
'dependencies': {
'effect': 'Effect has to de defined',
'condition': 'Condition has to be defined',
}
}
},
'scope': {
Expand All @@ -244,5 +304,18 @@ export const uiMetaSchema: JsonSchema7 = {
'required': [
'elements',
'type'
]
],
'additionalProperties': false,
'errorMessage': {
'properties': {
'type': 'Root type should be equal to one of the allowed values',
'label': 'Root label should be string'
},
'required': {
'elements': 'Root should have an array property "elements"',
'type': 'Root should have a string property "type"'
},
'additionalProperties': 'Root should not have properties ' +
'other than type, elements, label and rule'
}
};
7 changes: 4 additions & 3 deletions src/validation.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import * as AJV from 'ajv';
import { ErrorObject } from 'ajv';
import { JsonSchema7 } from '@jsonforms/core';
import * as AjvErrors from 'ajv-errors'; // tslint:disable-line

const ajv = new AJV({allErrors: true, verbose: true});
const ajv = new AJV({allErrors: true, verbose: true, jsonPointers: true});
AjvErrors(ajv);

interface ValidationErrors {
message: string;
schemaPath?: string;
}

const extractErrors = (errors: ErrorObject[]): ValidationErrors[] =>
const extractErrors = (errors: ErrorObject[]): ValidationErrors[] =>
errors.map((error: ErrorObject) => {
return {
message: error.message,
schemaPath: error.schemaPath
};
});

Expand Down
69 changes: 60 additions & 9 deletions test/uischemaValidation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,7 @@ test('invalid control element, layout label must be string', () => {
elements: [
{
type: 'Control',
label: {
label: 'Occupation'
},
label: ['Occupation'],
scope: '#/properties/occupation'
}
]
Expand Down Expand Up @@ -226,12 +224,6 @@ test('invalid vertical layout, missing layout elements', () => {
expect(errors).not.toEqual([]);
});

test('invalid layout, empty uischema', () => {
const uischema = {};
const errors = validator(uischema);
expect(errors).not.toEqual([]);
});

test('invalid layout type', () => {
const uischema = {
type: 'TestLayout',
Expand Down Expand Up @@ -318,6 +310,27 @@ test('invalid control element, options of Control must be type of object', () =>
expect(errors).not.toEqual([]);
});

test('invalid control element, invalid suggestion type', () => {
const uischema = {
type: 'HorizontalLayout',
elements: [
{
type: 'Control',
label: 'Occupation',
scope: '#/properties/occupation',
suggestion: {
Accountant: 'Accountant',
Engineer: 'Engineer',
Freelancer: 'Freelancer',
Journalism: 'Journalism'
}
}
]
};
const errors = validator(uischema);
expect(errors).not.toEqual([]);
});

test('invalid rule, missing rule effect', () => {
const uischema = {
type: 'HorizontalLayout',
Expand Down Expand Up @@ -470,6 +483,29 @@ test('invalid rule, condition type must be LEAF', () => {
expect(errors).not.toEqual([]);
});

test('invalid rule, invalid effect value', () => {
const uischema = {
type: 'HorizontalLayout',
elements: [
{
type: 'Control',
label: 'Occupation',
scope: '#/properties/occupation',
rule: {
effect: 'Test',
condition: {
type: 'LEAF',
scope: '#/properties/alive',
expectedValue: true
}
}
}
]
};
const errors = validator(uischema);
expect(errors).not.toEqual([]);
});

test('invalid rule, expected value of condition must be string,integer,number or boolean', () => {
const uischema = {
type: 'HorizontalLayout',
Expand Down Expand Up @@ -559,3 +595,18 @@ test('invalid group layout, Group layout must have label', () => {
const errors = validator(uischema);
expect(errors).not.toEqual([]);
});

test('invalid control element, custom error message for missing scope', () => {
const uischema = {
type: 'HorizontalLayout',
elements: [
{
type: 'Control',
label: 'Occupation',
}
]
};
const errors = validator(uischema);
expect(errors).not.toEqual([]);
expect(errors[0].message).toEqual(`Control should have an object property "scope"`);
});