@squiz/dx-json-schema-lib 1.12.0-alpha.8 → 1.12.1-alpha.0
Sign up to get free protection for your applications and to get access to all the features.
- package/.npm/_logs/2023-02-27T04_50_27_819Z-debug-0.log +39 -0
- package/jest.config.ts +0 -6
- package/lib/JsonValidationService.d.ts +35 -0
- package/lib/JsonValidationService.js +127 -1
- package/lib/JsonValidationService.js.map +1 -1
- package/lib/JsonValidationService.spec.js +288 -0
- package/lib/JsonValidationService.spec.js.map +1 -1
- package/lib/errors/JsonResolutionError.d.ts +5 -0
- package/lib/errors/JsonResolutionError.js +12 -0
- package/lib/errors/JsonResolutionError.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/jsonTypeResolution/arbitraryTypeResolution.d.ts +61 -0
- package/lib/jsonTypeResolution/arbitraryTypeResolution.js +61 -0
- package/lib/jsonTypeResolution/arbitraryTypeResolution.js.map +1 -0
- package/lib/jsonTypeResolution/arbitraryTypeResolution.spec.d.ts +1 -0
- package/lib/jsonTypeResolution/arbitraryTypeResolution.spec.js +100 -0
- package/lib/jsonTypeResolution/arbitraryTypeResolution.spec.js.map +1 -0
- package/lib/jsonTypeResolution/index.d.ts +76 -0
- package/lib/jsonTypeResolution/index.js +35 -0
- package/lib/jsonTypeResolution/index.js.map +1 -0
- package/lib/jsonTypeResolution/primitiveTypes.d.ts +10 -0
- package/lib/jsonTypeResolution/primitiveTypes.js +27 -0
- package/lib/jsonTypeResolution/primitiveTypes.js.map +1 -0
- package/lib/jsonTypeResolution/resolvableTypes.d.ts +12 -0
- package/lib/jsonTypeResolution/resolvableTypes.js +30 -0
- package/lib/jsonTypeResolution/resolvableTypes.js.map +1 -0
- package/lib/manifest/v1/v1.json +4 -3
- package/lib/manifest/v1/v1.spec.js +58 -0
- package/lib/manifest/v1/v1.spec.js.map +1 -1
- package/package.json +5 -4
- package/src/JsonValidationService.spec.ts +417 -1
- package/src/JsonValidationService.ts +154 -1
- package/src/errors/JsonResolutionError.ts +5 -0
- package/src/index.ts +3 -0
- package/src/jsonTypeResolution/arbitraryTypeResolution.spec.ts +134 -0
- package/src/jsonTypeResolution/arbitraryTypeResolution.ts +100 -0
- package/src/jsonTypeResolution/index.ts +16 -0
- package/src/jsonTypeResolution/primitiveTypes.ts +32 -0
- package/src/jsonTypeResolution/resolvableTypes.ts +37 -0
- package/src/manifest/v1/v1.json +4 -3
- package/src/manifest/v1/v1.spec.ts +96 -0
- package/tsconfig.tsbuildinfo +1 -1
@@ -4,6 +4,7 @@ const promises_1 = require("fs/promises");
|
|
4
4
|
const path_1 = require("path");
|
5
5
|
const SchemaValidationError_1 = require("../../errors/SchemaValidationError");
|
6
6
|
const JsonValidationService_1 = require("../../JsonValidationService");
|
7
|
+
const NAME_PATTERN = '^[a-z][a-z0-9_\\-]+$';
|
7
8
|
async function fetchTestManifest(filename) {
|
8
9
|
const contents = await (0, promises_1.readFile)((0, path_1.resolve)(__dirname, '__test__', 'schemas', filename), {
|
9
10
|
encoding: 'utf-8',
|
@@ -50,5 +51,62 @@ describe('manifest/v1', () => {
|
|
50
51
|
validationService.validateManifest(manifest, 'v1');
|
51
52
|
}, SchemaValidationError_1.SchemaValidationError, 'failed validation: Expected value at `#/functions/0/input/type` to be `object`, but value given is `string`');
|
52
53
|
});
|
54
|
+
describe.each(['_my-name', '-my-name', 'MyName', 'myName', '0my-name'])('fails name-pattern validation for %s', (propertyValue) => {
|
55
|
+
it.each(['namespace', 'name'])(`fails validation for manifests with %s of %s`, async (propertyName) => {
|
56
|
+
const manifest = await fetchTestManifest('validComponent.json');
|
57
|
+
expectToThrowErrorMatchingTypeAndMessage(() => {
|
58
|
+
validationService.validateManifest({
|
59
|
+
...manifest,
|
60
|
+
[propertyName]: propertyValue,
|
61
|
+
}, 'v1');
|
62
|
+
}, SchemaValidationError_1.SchemaValidationError, `failed validation: Value in \`#/${propertyName}\` should match \`${NAME_PATTERN}\`, but received \`${propertyValue}\``);
|
63
|
+
});
|
64
|
+
it('fails validation for manifests with function names of %s', async () => {
|
65
|
+
const manifest = await fetchTestManifest('validComponent.json');
|
66
|
+
expectToThrowErrorMatchingTypeAndMessage(() => {
|
67
|
+
validationService.validateManifest({
|
68
|
+
...manifest,
|
69
|
+
functions: [
|
70
|
+
{
|
71
|
+
name: propertyValue,
|
72
|
+
entry: 'main.js',
|
73
|
+
input: {},
|
74
|
+
output: {
|
75
|
+
responseType: 'html',
|
76
|
+
},
|
77
|
+
},
|
78
|
+
],
|
79
|
+
}, 'v1');
|
80
|
+
}, SchemaValidationError_1.SchemaValidationError, `failed validation: Value in \`#/functions/0/name\` should match \`${NAME_PATTERN}\`, but received \`${propertyValue}\``);
|
81
|
+
});
|
82
|
+
});
|
83
|
+
it('should allow uppercase letters in property names withe previews', async () => {
|
84
|
+
const manifest = await fetchTestManifest('validComponent.json');
|
85
|
+
expect(validationService.validateManifest({
|
86
|
+
...manifest,
|
87
|
+
previews: {
|
88
|
+
ValidPreview: {
|
89
|
+
functionData: {
|
90
|
+
main: {},
|
91
|
+
},
|
92
|
+
},
|
93
|
+
},
|
94
|
+
}, 'v1')).toEqual(true);
|
95
|
+
});
|
96
|
+
it('errors for non-alphanumeric characters in preview keys', async () => {
|
97
|
+
const manifest = await fetchTestManifest('validComponent.json');
|
98
|
+
expectToThrowErrorMatchingTypeAndMessage(() => {
|
99
|
+
validationService.validateManifest({
|
100
|
+
...manifest,
|
101
|
+
previews: {
|
102
|
+
'Bad-@@@Preview': {
|
103
|
+
functionData: {
|
104
|
+
main: {},
|
105
|
+
},
|
106
|
+
},
|
107
|
+
},
|
108
|
+
}, 'v1');
|
109
|
+
}, SchemaValidationError_1.SchemaValidationError, 'failed validation: Invalid property name `Bad-@@@Preview` at `#/previews`');
|
110
|
+
});
|
53
111
|
});
|
54
112
|
//# sourceMappingURL=v1.spec.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"v1.spec.js","sourceRoot":"","sources":["../../../src/manifest/v1/v1.spec.ts"],"names":[],"mappings":";;AAAA,0CAAuC;AACvC,+BAA+B;AAC/B,8EAA2E;AAC3E,uEAAoE;AAEpE,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,cAAO,EAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE;QACnF,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AACD,wDAAwD;AACxD,SAAS,wCAAwC,CAAC,QAAkB,EAAE,SAAmB,EAAE,OAAe;IACxG,IAAI,KAAK,GAAiB,IAAI,CAAC;IAE/B,IAAI;QACF,QAAQ,EAAE,CAAC;KACZ;IAAC,OAAO,CAAM,EAAE;QACf,KAAK,GAAG,CAAC,CAAC;KACX;IAED,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5B,MAAM,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAI,iBAAwC,CAAC;IAE7C,SAAS,CAAC,GAAG,EAAE;QACb,iBAAiB,GAAG,IAAI,6CAAqB,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QAChE,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,gCAAgC,CAAC,CAAC;QAE3E,wCAAwC,CACtC,GAAG,EAAE;YACH,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC,EACD,6CAAqB,EACrB,sHAAsH,CACvH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,6BAA6B,CAAC,CAAC;QAExE,wCAAwC,CACtC,GAAG,EAAE;YACH,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC,EACD,6CAAqB,EACrB,+HAA+H,CAChI,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,sCAAsC,CAAC,CAAC;QACjF,wCAAwC,CACtC,GAAG,EAAE;YACH,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC,EACD,6CAAqB,EACrB,6GAA6G,CAC9G,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
1
|
+
{"version":3,"file":"v1.spec.js","sourceRoot":"","sources":["../../../src/manifest/v1/v1.spec.ts"],"names":[],"mappings":";;AAAA,0CAAuC;AACvC,+BAA+B;AAC/B,8EAA2E;AAC3E,uEAAoE;AAEpE,MAAM,YAAY,GAAG,sBAAsB,CAAC;AAE5C,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,cAAO,EAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE;QACnF,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AACD,wDAAwD;AACxD,SAAS,wCAAwC,CAAC,QAAkB,EAAE,SAAmB,EAAE,OAAe;IACxG,IAAI,KAAK,GAAiB,IAAI,CAAC;IAE/B,IAAI;QACF,QAAQ,EAAE,CAAC;KACZ;IAAC,OAAO,CAAM,EAAE;QACf,KAAK,GAAG,CAAC,CAAC;KACX;IAED,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5B,MAAM,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAI,iBAAwC,CAAC;IAE7C,SAAS,CAAC,GAAG,EAAE;QACb,iBAAiB,GAAG,IAAI,6CAAqB,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QAChE,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,gCAAgC,CAAC,CAAC;QAE3E,wCAAwC,CACtC,GAAG,EAAE;YACH,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC,EACD,6CAAqB,EACrB,sHAAsH,CACvH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,6BAA6B,CAAC,CAAC;QAExE,wCAAwC,CACtC,GAAG,EAAE;YACH,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC,EACD,6CAAqB,EACrB,+HAA+H,CAChI,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,sCAAsC,CAAC,CAAC;QACjF,wCAAwC,CACtC,GAAG,EAAE;YACH,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC,EACD,6CAAqB,EACrB,6GAA6G,CAC9G,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CACrE,sCAAsC,EACtC,CAAC,aAAa,EAAE,EAAE;QAChB,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,8CAA8C,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE;YACpG,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;YAEhE,wCAAwC,CACtC,GAAG,EAAE;gBACH,iBAAiB,CAAC,gBAAgB,CAChC;oBACE,GAAG,QAAQ;oBACX,CAAC,YAAY,CAAC,EAAE,aAAa;iBAC9B,EACD,IAAI,CACL,CAAC;YACJ,CAAC,EACD,6CAAqB,EACrB,mCAAmC,YAAY,qBAAqB,YAAY,sBAAsB,aAAa,IAAI,CACxH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;YACxE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;YAEhE,wCAAwC,CACtC,GAAG,EAAE;gBACH,iBAAiB,CAAC,gBAAgB,CAChC;oBACE,GAAG,QAAQ;oBACX,SAAS,EAAE;wBACT;4BACE,IAAI,EAAE,aAAa;4BACnB,KAAK,EAAE,SAAS;4BAChB,KAAK,EAAE,EAAE;4BACT,MAAM,EAAE;gCACN,YAAY,EAAE,MAAM;6BACrB;yBACF;qBACF;iBACF,EACD,IAAI,CACL,CAAC;YACJ,CAAC,EACD,6CAAqB,EACrB,qEAAqE,YAAY,sBAAsB,aAAa,IAAI,CACzH,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QAEhE,MAAM,CACJ,iBAAiB,CAAC,gBAAgB,CAChC;YACE,GAAG,QAAQ;YACX,QAAQ,EAAE;gBACR,YAAY,EAAE;oBACZ,YAAY,EAAE;wBACZ,IAAI,EAAE,EAAE;qBACT;iBACF;aACF;SACF,EACD,IAAI,CACL,CACF,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QAEhE,wCAAwC,CACtC,GAAG,EAAE;YACH,iBAAiB,CAAC,gBAAgB,CAChC;gBACE,GAAG,QAAQ;gBACX,QAAQ,EAAE;oBACR,gBAAgB,EAAE;wBAChB,YAAY,EAAE;4BACZ,IAAI,EAAE,EAAE;yBACT;qBACF;iBACF;aACF,EACD,IAAI,CACL,CAAC;QACJ,CAAC,EACD,6CAAqB,EACrB,2EAA2E,CAC5E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/dx-json-schema-lib",
|
3
|
-
"version": "1.12.
|
3
|
+
"version": "1.12.1-alpha.0",
|
4
4
|
"description": "",
|
5
5
|
"main": "lib/index.js",
|
6
6
|
"scripts": {
|
@@ -20,14 +20,15 @@
|
|
20
20
|
"jest": "29.4.1",
|
21
21
|
"json-schema-to-typescript": "11.0.3",
|
22
22
|
"rimraf": "4.1.2",
|
23
|
-
"ts-jest": "
|
23
|
+
"ts-jest": "29.0.5",
|
24
24
|
"ts-loader": "9.3.1",
|
25
25
|
"ts-node": "10.9.1",
|
26
26
|
"typescript": "4.9.4"
|
27
27
|
},
|
28
28
|
"dependencies": {
|
29
29
|
"@sagold/json-query": "6.0.0",
|
30
|
-
"json-schema-library": "7.4.5"
|
30
|
+
"json-schema-library": "7.4.5",
|
31
|
+
"ts-brand": "0.0.2"
|
31
32
|
},
|
32
|
-
"gitHead": "
|
33
|
+
"gitHead": "4a0c81e76ca50706d137dee82869e3ea7844376e"
|
33
34
|
}
|
@@ -1,9 +1,11 @@
|
|
1
|
-
import { JsonValidationService } from './JsonValidationService';
|
1
|
+
import { ComponentInputMetaSchema, JSONSchemaService, JsonValidationService } from './JsonValidationService';
|
2
2
|
import { SchemaValidationError } from './errors/SchemaValidationError';
|
3
3
|
|
4
4
|
import validManifest from './manifest/v1/__test__/schemas/validComponent.json';
|
5
5
|
import validManifestJson from './manifest/v1/__test__/schemas/validComponentJson.json';
|
6
6
|
import { FormattedText } from './formatted-text/v1/formattedText';
|
7
|
+
import { JSONSchema } from 'json-schema-library';
|
8
|
+
import { PrimitiveType, ResolvableType, TypeResolver } from './jsonTypeResolution/arbitraryTypeResolution';
|
7
9
|
|
8
10
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
9
11
|
function expectToThrowErrorMatchingTypeAndMessage(received: Function, errorType: Function, message: string) {
|
@@ -448,6 +450,60 @@ describe('JsonValidationService', () => {
|
|
448
450
|
'failed validation: Expected `[object Object]` (object) in `#/my-input` to be of type `array`',
|
449
451
|
);
|
450
452
|
});
|
453
|
+
|
454
|
+
it('should validate a FormattedText value when the schema is a $ref to a $ref', async () => {
|
455
|
+
const formattedText: FormattedText = [
|
456
|
+
{
|
457
|
+
tag: 'p',
|
458
|
+
type: 'tag',
|
459
|
+
children: [{ type: 'text', value: 'hello' }],
|
460
|
+
},
|
461
|
+
];
|
462
|
+
|
463
|
+
const schema = {
|
464
|
+
type: 'object',
|
465
|
+
properties: {
|
466
|
+
'my-input': { $ref: '#/definitions/FormattedText' },
|
467
|
+
},
|
468
|
+
definitions: {
|
469
|
+
FormattedText: { $ref: '#/definitions/FormattedText2' },
|
470
|
+
FormattedText2: { type: 'FormattedText' },
|
471
|
+
},
|
472
|
+
required: ['my-input'],
|
473
|
+
};
|
474
|
+
const value = {
|
475
|
+
'my-input': formattedText,
|
476
|
+
};
|
477
|
+
|
478
|
+
expect(jsonValidationService.validateComponentInput(schema, value)).toEqual(true);
|
479
|
+
});
|
480
|
+
|
481
|
+
it('should validate a FormattedText value when the schema is in an if/then/else', async () => {
|
482
|
+
const formattedText: FormattedText = [
|
483
|
+
{
|
484
|
+
tag: 'p',
|
485
|
+
type: 'tag',
|
486
|
+
children: [{ type: 'text', value: 'hello' }],
|
487
|
+
},
|
488
|
+
];
|
489
|
+
|
490
|
+
const schema = {
|
491
|
+
type: 'object',
|
492
|
+
properties: {
|
493
|
+
'my-input': {
|
494
|
+
if: { type: 'string' },
|
495
|
+
then: { type: 'string' },
|
496
|
+
else: { type: 'FormattedText' },
|
497
|
+
},
|
498
|
+
},
|
499
|
+
required: ['my-input'],
|
500
|
+
};
|
501
|
+
const value = {
|
502
|
+
'my-input': formattedText,
|
503
|
+
};
|
504
|
+
|
505
|
+
expect(jsonValidationService.validateComponentInput(schema, value)).toEqual(true);
|
506
|
+
});
|
451
507
|
});
|
452
508
|
|
453
509
|
describe('standard inputs', () => {
|
@@ -518,4 +574,364 @@ describe('JsonValidationService', () => {
|
|
518
574
|
});
|
519
575
|
});
|
520
576
|
});
|
577
|
+
|
578
|
+
describe('validateRenderInput', () => {
|
579
|
+
it('should validate a property with type FormattedText as string', () => {
|
580
|
+
const schema = {
|
581
|
+
type: 'object',
|
582
|
+
properties: {
|
583
|
+
'my-input': { type: 'FormattedText' },
|
584
|
+
},
|
585
|
+
required: ['my-input'],
|
586
|
+
};
|
587
|
+
const value = {
|
588
|
+
'my-input': 'hello',
|
589
|
+
};
|
590
|
+
|
591
|
+
expect(jsonValidationService.validateRenderInput(schema, value)).toEqual(true);
|
592
|
+
});
|
593
|
+
|
594
|
+
it('should error when a property with type FormattedText is provided a valid FormattedText value', () => {
|
595
|
+
const schema = {
|
596
|
+
type: 'object',
|
597
|
+
properties: {
|
598
|
+
'my-input': { type: 'FormattedText' },
|
599
|
+
},
|
600
|
+
required: ['my-input'],
|
601
|
+
};
|
602
|
+
const value = {
|
603
|
+
'my-input': [{ type: 'text', value: 'hello' }],
|
604
|
+
};
|
605
|
+
|
606
|
+
expectToThrowErrorMatchingTypeAndMessage(
|
607
|
+
() => {
|
608
|
+
jsonValidationService.validateRenderInput(schema, value);
|
609
|
+
},
|
610
|
+
SchemaValidationError,
|
611
|
+
'failed validation: Expected `[object Object]` (array) in `#/my-input` to be of type `string`',
|
612
|
+
);
|
613
|
+
});
|
614
|
+
|
615
|
+
it('should validate a property with type FormattedText within an if/then/else as string', () => {
|
616
|
+
const schema = {
|
617
|
+
type: 'object',
|
618
|
+
properties: {
|
619
|
+
'my-input': {
|
620
|
+
type: 'object',
|
621
|
+
properties: {
|
622
|
+
prop: { type: 'string' },
|
623
|
+
},
|
624
|
+
required: ['prop'],
|
625
|
+
if: { properties: { prop: { const: 'a' } } },
|
626
|
+
then: {
|
627
|
+
properties: {
|
628
|
+
text: { type: 'FormattedText' },
|
629
|
+
},
|
630
|
+
required: ['text'],
|
631
|
+
},
|
632
|
+
else: {
|
633
|
+
properties: {
|
634
|
+
text: { type: 'array', items: { type: 'FormattedText' } },
|
635
|
+
},
|
636
|
+
required: ['text'],
|
637
|
+
},
|
638
|
+
},
|
639
|
+
},
|
640
|
+
required: ['my-input'],
|
641
|
+
};
|
642
|
+
const value = {
|
643
|
+
'my-input': {
|
644
|
+
prop: 'a',
|
645
|
+
text: 'hello',
|
646
|
+
},
|
647
|
+
};
|
648
|
+
|
649
|
+
expect(jsonValidationService.validateRenderInput(schema, value)).toEqual(true);
|
650
|
+
|
651
|
+
const otherValue = {
|
652
|
+
'my-input': {
|
653
|
+
prop: 'b',
|
654
|
+
text: ['my', 'formatted', 'text'],
|
655
|
+
},
|
656
|
+
};
|
657
|
+
expect(jsonValidationService.validateRenderInput(schema, otherValue)).toEqual(true);
|
658
|
+
});
|
659
|
+
});
|
660
|
+
});
|
661
|
+
|
662
|
+
const defaultSchema: JSONSchema = {
|
663
|
+
type: 'object',
|
664
|
+
properties: {
|
665
|
+
myProperty: {
|
666
|
+
type: 'string',
|
667
|
+
},
|
668
|
+
},
|
669
|
+
required: ['myProperty'],
|
670
|
+
};
|
671
|
+
function primitiveTypeFixture<T extends string>(title: T, schema: JSONSchema = defaultSchema) {
|
672
|
+
return PrimitiveType({
|
673
|
+
...schema,
|
674
|
+
title,
|
675
|
+
});
|
676
|
+
}
|
677
|
+
|
678
|
+
function resolvableTypeFixture<T extends string>(title: T, schema: JSONSchema = defaultSchema) {
|
679
|
+
return ResolvableType({
|
680
|
+
...schema,
|
681
|
+
title,
|
682
|
+
});
|
683
|
+
}
|
684
|
+
|
685
|
+
describe('JsonSchemaService', () => {
|
686
|
+
describe('validateInput', () => {
|
687
|
+
it.each([String('123'), Number(123), [123]])(
|
688
|
+
'should validate any primitive type with its resolvable type %s',
|
689
|
+
(propertyValue) => {
|
690
|
+
const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
|
691
|
+
const jsonSchemaService = new JSONSchemaService(
|
692
|
+
new TypeResolver(
|
693
|
+
{
|
694
|
+
MyPrimitive: primitiveSchema,
|
695
|
+
},
|
696
|
+
{
|
697
|
+
MyResolvableNumber: resolvableTypeFixture('MyResolvableNumber', { type: 'number' }),
|
698
|
+
MyResolvableArray: resolvableTypeFixture('MyResolvableArray', { type: 'array' }),
|
699
|
+
},
|
700
|
+
{
|
701
|
+
MyPrimitive: {
|
702
|
+
MyResolvableNumber: (value: number) => value.toString(),
|
703
|
+
MyResolvableArray: (value: any[]) => value.join(''),
|
704
|
+
},
|
705
|
+
},
|
706
|
+
),
|
707
|
+
ComponentInputMetaSchema,
|
708
|
+
);
|
709
|
+
|
710
|
+
expect(
|
711
|
+
jsonSchemaService.validateInput(
|
712
|
+
{ myProperty: propertyValue },
|
713
|
+
{ type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } },
|
714
|
+
),
|
715
|
+
).toEqual(true);
|
716
|
+
},
|
717
|
+
);
|
718
|
+
|
719
|
+
it('should error when a primitive type is provided a value that cannot be resolved by its resolvable types', () => {
|
720
|
+
const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
|
721
|
+
const jsonSchemaService = new JSONSchemaService(
|
722
|
+
new TypeResolver(
|
723
|
+
{
|
724
|
+
MyPrimitive: primitiveSchema,
|
725
|
+
},
|
726
|
+
{
|
727
|
+
MyResolvableNumber: resolvableTypeFixture('MyResolvableNumber', { type: 'number' }),
|
728
|
+
MyResolvableArray: resolvableTypeFixture('MyResolvableArray', { type: 'array' }),
|
729
|
+
},
|
730
|
+
{
|
731
|
+
MyPrimitive: {
|
732
|
+
MyResolvableNumber: (value: number) => value.toString(),
|
733
|
+
MyResolvableArray: (value: any[]) => value.join(''),
|
734
|
+
},
|
735
|
+
},
|
736
|
+
),
|
737
|
+
ComponentInputMetaSchema,
|
738
|
+
);
|
739
|
+
|
740
|
+
expect(() => {
|
741
|
+
jsonSchemaService.validateInput(
|
742
|
+
{ myProperty: true },
|
743
|
+
{ type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } },
|
744
|
+
);
|
745
|
+
}).toThrowError();
|
746
|
+
});
|
747
|
+
|
748
|
+
it.each([String('123'), Number(123), [123]])(
|
749
|
+
'should validate a primitive type when defined as a ref with resolvable value %s',
|
750
|
+
(propertyValue) => {
|
751
|
+
const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
|
752
|
+
const jsonSchemaService = new JSONSchemaService(
|
753
|
+
new TypeResolver(
|
754
|
+
{
|
755
|
+
MyPrimitive: primitiveSchema,
|
756
|
+
},
|
757
|
+
{
|
758
|
+
MyResolvableNumber: resolvableTypeFixture('MyResolvableNumber', { type: 'number' }),
|
759
|
+
MyResolvableArray: resolvableTypeFixture('MyResolvableArray', { type: 'array' }),
|
760
|
+
},
|
761
|
+
{
|
762
|
+
MyPrimitive: {
|
763
|
+
MyResolvableNumber: (value: number) => value.toString(),
|
764
|
+
MyResolvableArray: (value: any[]) => value.join(''),
|
765
|
+
},
|
766
|
+
},
|
767
|
+
),
|
768
|
+
ComponentInputMetaSchema,
|
769
|
+
);
|
770
|
+
|
771
|
+
expect(
|
772
|
+
jsonSchemaService.validateInput(
|
773
|
+
{ myProperty: propertyValue },
|
774
|
+
{
|
775
|
+
type: 'object',
|
776
|
+
properties: { myProperty: { $ref: '#/definitions/Ref' } },
|
777
|
+
definitions: { Ref: { type: 'MyPrimitive' } },
|
778
|
+
},
|
779
|
+
),
|
780
|
+
).toEqual(true);
|
781
|
+
},
|
782
|
+
);
|
783
|
+
|
784
|
+
it('should not validate on a primitive type against a resolvable type when a resolver is not defined', () => {
|
785
|
+
const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
|
786
|
+
const jsonSchemaService = new JSONSchemaService(
|
787
|
+
new TypeResolver(
|
788
|
+
{
|
789
|
+
MyPrimitive: primitiveSchema,
|
790
|
+
},
|
791
|
+
{
|
792
|
+
MyResolvableNumber: resolvableTypeFixture('MyResolvableNumber', { type: 'number' }),
|
793
|
+
MyResolvableArray: resolvableTypeFixture('MyResolvableArray', { type: 'array' }),
|
794
|
+
},
|
795
|
+
{
|
796
|
+
MyPrimitive: {
|
797
|
+
MyResolvableNumber: (value: number) => value.toString(),
|
798
|
+
},
|
799
|
+
},
|
800
|
+
),
|
801
|
+
ComponentInputMetaSchema,
|
802
|
+
);
|
803
|
+
|
804
|
+
expect(() => {
|
805
|
+
jsonSchemaService.validateInput(
|
806
|
+
{ myProperty: [123] },
|
807
|
+
{ type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } },
|
808
|
+
);
|
809
|
+
}).toThrowError();
|
810
|
+
});
|
811
|
+
|
812
|
+
it('should validate a primitive type against similar but different resolvable types', () => {
|
813
|
+
const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
|
814
|
+
const jsonSchemaService = new JSONSchemaService(
|
815
|
+
new TypeResolver(
|
816
|
+
{
|
817
|
+
MyPrimitive: primitiveSchema,
|
818
|
+
},
|
819
|
+
{
|
820
|
+
MyResolvableSrcNumber: resolvableTypeFixture('MyResolvableSrcNumber', {
|
821
|
+
type: 'object',
|
822
|
+
properties: {
|
823
|
+
src: { type: 'number' },
|
824
|
+
},
|
825
|
+
}),
|
826
|
+
MyResolvableSrcString: resolvableTypeFixture('MyResolvableSrcString', {
|
827
|
+
type: 'object',
|
828
|
+
properties: {
|
829
|
+
src: { type: 'string' },
|
830
|
+
},
|
831
|
+
}),
|
832
|
+
},
|
833
|
+
{
|
834
|
+
MyPrimitive: {
|
835
|
+
MyResolvableSrcNumber: (value: { src: number }) => value.src.toString(),
|
836
|
+
MyResolvableSrcString: (value: { src: string }) => value.src,
|
837
|
+
},
|
838
|
+
},
|
839
|
+
),
|
840
|
+
ComponentInputMetaSchema,
|
841
|
+
);
|
842
|
+
|
843
|
+
expect(
|
844
|
+
jsonSchemaService.validateInput(
|
845
|
+
{
|
846
|
+
myProperty: {
|
847
|
+
src: 123,
|
848
|
+
},
|
849
|
+
},
|
850
|
+
{ type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } },
|
851
|
+
),
|
852
|
+
).toEqual(true);
|
853
|
+
expect(
|
854
|
+
jsonSchemaService.validateInput(
|
855
|
+
{
|
856
|
+
myProperty: {
|
857
|
+
src: '123',
|
858
|
+
},
|
859
|
+
},
|
860
|
+
{ type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } },
|
861
|
+
),
|
862
|
+
).toEqual(true);
|
863
|
+
});
|
864
|
+
});
|
865
|
+
|
866
|
+
describe('resolveInput', () => {
|
867
|
+
it.each([String('123'), Number(123), [123]])(
|
868
|
+
'should resolve a primitive type from its resolvable type %s',
|
869
|
+
async (resolvableValue) => {
|
870
|
+
const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
|
871
|
+
const jsonSchemaService = new JSONSchemaService(
|
872
|
+
new TypeResolver(
|
873
|
+
{
|
874
|
+
MyPrimitive: primitiveSchema,
|
875
|
+
},
|
876
|
+
{
|
877
|
+
MyResolvableNumber: resolvableTypeFixture('MyResolvableNumber', { type: 'number' }),
|
878
|
+
MyResolvableArray: resolvableTypeFixture('MyResolvableArray', { type: 'array' }),
|
879
|
+
},
|
880
|
+
{
|
881
|
+
MyPrimitive: {
|
882
|
+
MyResolvableNumber: (value: number) => value.toString(),
|
883
|
+
MyResolvableArray: (value: any[]) => value.join(''),
|
884
|
+
},
|
885
|
+
},
|
886
|
+
),
|
887
|
+
ComponentInputMetaSchema,
|
888
|
+
);
|
889
|
+
|
890
|
+
await expect(
|
891
|
+
jsonSchemaService.resolveInput(
|
892
|
+
{ myProperty: resolvableValue },
|
893
|
+
{ type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } },
|
894
|
+
),
|
895
|
+
).resolves.toEqual({ myProperty: '123' });
|
896
|
+
},
|
897
|
+
);
|
898
|
+
|
899
|
+
it.each([
|
900
|
+
[{ src: 'MyString' }, 'MyString'],
|
901
|
+
[{ src: 1132 }, '1132'],
|
902
|
+
])('should resolve a resolvable type %s against the correct resolver to %s', async (resolvableValue, output) => {
|
903
|
+
const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
|
904
|
+
const jsonSchemaService = new JSONSchemaService(
|
905
|
+
new TypeResolver(
|
906
|
+
{
|
907
|
+
MyPrimitive: primitiveSchema,
|
908
|
+
},
|
909
|
+
{
|
910
|
+
MyResolvableSrcString: resolvableTypeFixture('MyResolvableSrcString', {
|
911
|
+
type: 'object',
|
912
|
+
properties: { src: { type: 'string' } },
|
913
|
+
}),
|
914
|
+
MyResolvableSrcNumber: resolvableTypeFixture('MyResolvableSrcNumber', {
|
915
|
+
type: 'object',
|
916
|
+
properties: { src: { type: 'number' } },
|
917
|
+
}),
|
918
|
+
},
|
919
|
+
{
|
920
|
+
MyPrimitive: {
|
921
|
+
MyResolvableSrcNumber: (value: { src: number }) => value.src.toString(),
|
922
|
+
MyResolvableSrcString: (value: { src: string }) => value.src,
|
923
|
+
},
|
924
|
+
},
|
925
|
+
),
|
926
|
+
ComponentInputMetaSchema,
|
927
|
+
);
|
928
|
+
|
929
|
+
await expect(
|
930
|
+
jsonSchemaService.resolveInput(
|
931
|
+
{ myProperty: resolvableValue },
|
932
|
+
{ type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } },
|
933
|
+
),
|
934
|
+
).resolves.toEqual({ myProperty: output });
|
935
|
+
});
|
936
|
+
});
|
521
937
|
});
|