@squiz/dx-json-schema-lib 1.12.0-alpha.9 → 1.12.1-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/.npm/_logs/2023-02-27T04_50_27_819Z-debug-0.log +39 -0
  2. package/jest.config.ts +0 -6
  3. package/lib/JsonValidationService.d.ts +35 -0
  4. package/lib/JsonValidationService.js +127 -1
  5. package/lib/JsonValidationService.js.map +1 -1
  6. package/lib/JsonValidationService.spec.js +288 -0
  7. package/lib/JsonValidationService.spec.js.map +1 -1
  8. package/lib/errors/JsonResolutionError.d.ts +5 -0
  9. package/lib/errors/JsonResolutionError.js +12 -0
  10. package/lib/errors/JsonResolutionError.js.map +1 -0
  11. package/lib/index.d.ts +2 -0
  12. package/lib/index.js +2 -0
  13. package/lib/index.js.map +1 -1
  14. package/lib/jsonTypeResolution/arbitraryTypeResolution.d.ts +61 -0
  15. package/lib/jsonTypeResolution/arbitraryTypeResolution.js +61 -0
  16. package/lib/jsonTypeResolution/arbitraryTypeResolution.js.map +1 -0
  17. package/lib/jsonTypeResolution/arbitraryTypeResolution.spec.d.ts +1 -0
  18. package/lib/jsonTypeResolution/arbitraryTypeResolution.spec.js +100 -0
  19. package/lib/jsonTypeResolution/arbitraryTypeResolution.spec.js.map +1 -0
  20. package/lib/jsonTypeResolution/index.d.ts +76 -0
  21. package/lib/jsonTypeResolution/index.js +35 -0
  22. package/lib/jsonTypeResolution/index.js.map +1 -0
  23. package/lib/jsonTypeResolution/primitiveTypes.d.ts +10 -0
  24. package/lib/jsonTypeResolution/primitiveTypes.js +27 -0
  25. package/lib/jsonTypeResolution/primitiveTypes.js.map +1 -0
  26. package/lib/jsonTypeResolution/resolvableTypes.d.ts +12 -0
  27. package/lib/jsonTypeResolution/resolvableTypes.js +30 -0
  28. package/lib/jsonTypeResolution/resolvableTypes.js.map +1 -0
  29. package/lib/manifest/v1/v1.json +4 -3
  30. package/lib/manifest/v1/v1.spec.js +58 -0
  31. package/lib/manifest/v1/v1.spec.js.map +1 -1
  32. package/package.json +5 -4
  33. package/src/JsonValidationService.spec.ts +417 -1
  34. package/src/JsonValidationService.ts +154 -1
  35. package/src/errors/JsonResolutionError.ts +5 -0
  36. package/src/index.ts +3 -0
  37. package/src/jsonTypeResolution/arbitraryTypeResolution.spec.ts +134 -0
  38. package/src/jsonTypeResolution/arbitraryTypeResolution.ts +100 -0
  39. package/src/jsonTypeResolution/index.ts +16 -0
  40. package/src/jsonTypeResolution/primitiveTypes.ts +32 -0
  41. package/src/jsonTypeResolution/resolvableTypes.ts +37 -0
  42. package/src/manifest/v1/v1.json +4 -3
  43. package/src/manifest/v1/v1.spec.ts +96 -0
  44. 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.0-alpha.9",
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": "28.0.8",
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": "0d3ee3d767b9834b5ce8ca914976ff7331f5bf21"
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
  });