@squiz/dx-json-schema-lib 1.79.0 → 1.80.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/jest.config.ts +13 -2
  3. package/lib/JsonSchemaService.d.ts +34 -0
  4. package/lib/JsonSchemaService.js +140 -0
  5. package/lib/JsonSchemaService.js.map +1 -0
  6. package/lib/JsonSchemaService.spec.d.ts +1 -0
  7. package/lib/JsonSchemaService.spec.js +1807 -0
  8. package/lib/JsonSchemaService.spec.js.map +1 -0
  9. package/lib/JsonValidationService.d.ts +11 -33
  10. package/lib/JsonValidationService.js +43 -194
  11. package/lib/JsonValidationService.js.map +1 -1
  12. package/lib/JsonValidationService.spec.js +19 -1800
  13. package/lib/JsonValidationService.spec.js.map +1 -1
  14. package/lib/index.d.ts +1 -0
  15. package/lib/index.js +1 -0
  16. package/lib/index.js.map +1 -1
  17. package/lib/jsonTypeResolution/TypeResolver.d.ts +0 -1
  18. package/lib/jsonTypeResolution/TypeResolver.js +0 -3
  19. package/lib/jsonTypeResolution/TypeResolver.js.map +1 -1
  20. package/lib/jsonTypeResolution/TypeResolver.spec.js +10 -0
  21. package/lib/jsonTypeResolution/TypeResolver.spec.js.map +1 -1
  22. package/lib/manifest/v1/DxComponentInputSchema.spec.js +18 -0
  23. package/lib/manifest/v1/DxComponentInputSchema.spec.js.map +1 -1
  24. package/lib/manifest/v1/DxContentMetaSchema.json +24 -32
  25. package/lib/manifest/v1/JobV1.d.ts +23 -18
  26. package/lib/manifest/v1/__test__/schemas/invalidUiMetadata.json +31 -0
  27. package/lib/manifest/v1/v1.d.ts +23 -18
  28. package/lib/manifest/v1/v1.spec.js +3 -66
  29. package/lib/manifest/v1/v1.spec.js.map +1 -1
  30. package/lib/processValidationResult.d.ts +2 -0
  31. package/lib/processValidationResult.js +24 -0
  32. package/lib/processValidationResult.js.map +1 -0
  33. package/lib/validators/customKeywordValidators.d.ts +2 -0
  34. package/lib/validators/customKeywordValidators.js +47 -0
  35. package/lib/validators/customKeywordValidators.js.map +1 -0
  36. package/lib/validators/customKeywordValidators.spec.d.ts +1 -0
  37. package/lib/validators/customKeywordValidators.spec.js +100 -0
  38. package/lib/validators/customKeywordValidators.spec.js.map +1 -0
  39. package/package.json +1 -1
  40. package/src/JsonSchemaService.spec.ts +2198 -0
  41. package/src/JsonSchemaService.ts +159 -0
  42. package/src/JsonValidationService.spec.ts +26 -2195
  43. package/src/JsonValidationService.ts +64 -226
  44. package/src/index.ts +1 -0
  45. package/src/jsonTypeResolution/TypeResolver.spec.ts +12 -0
  46. package/src/jsonTypeResolution/TypeResolver.ts +0 -4
  47. package/src/manifest/v1/DxComponentInputSchema.spec.ts +21 -0
  48. package/src/manifest/v1/DxContentMetaSchema.json +24 -32
  49. package/src/manifest/v1/JobV1.ts +23 -23
  50. package/src/manifest/v1/__test__/schemas/invalidUiMetadata.json +31 -0
  51. package/src/manifest/v1/v1.spec.ts +3 -73
  52. package/src/manifest/v1/v1.ts +23 -23
  53. package/src/processValidationResult.ts +20 -0
  54. package/src/validators/customKeywordValidators.spec.ts +171 -0
  55. package/src/validators/customKeywordValidators.ts +53 -0
  56. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,1807 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const JsonSchemaService_1 = require("./JsonSchemaService");
4
+ const SchemaValidationError_1 = require("./errors/SchemaValidationError");
5
+ const TypeResolver_1 = require("./jsonTypeResolution/TypeResolver");
6
+ const primitiveTypes_1 = require("./primitiveTypes");
7
+ const TypeResolverBuilder_1 = require("./jsonTypeResolution/TypeResolverBuilder");
8
+ const resolvableTypes_1 = require("./resolvableTypes");
9
+ function expectToThrowErrorMatchingTypeAndMessage(
10
+ // eslint-disable-next-line @typescript-eslint/ban-types
11
+ received,
12
+ // eslint-disable-next-line @typescript-eslint/ban-types
13
+ errorType, message, validationExpected) {
14
+ let error = null;
15
+ try {
16
+ received();
17
+ }
18
+ catch (e) {
19
+ error = e;
20
+ }
21
+ expect(error).toBeDefined();
22
+ expect(error === null || error === void 0 ? void 0 : error.message).toEqual(message);
23
+ expect(error).toBeInstanceOf(errorType);
24
+ expect(error === null || error === void 0 ? void 0 : error.validationData).toEqual(validationExpected);
25
+ }
26
+ const defaultSchema = {
27
+ type: 'object',
28
+ properties: {
29
+ myProperty: {
30
+ type: 'string',
31
+ },
32
+ },
33
+ required: ['myProperty'],
34
+ };
35
+ function primitiveTypeFixture(title, schema = defaultSchema) {
36
+ return (0, TypeResolver_1.PrimitiveType)({
37
+ ...schema,
38
+ title,
39
+ });
40
+ }
41
+ function resolvableTypeFixture(title, schema = defaultSchema) {
42
+ return (0, TypeResolver_1.ResolvableType)({
43
+ ...schema,
44
+ title,
45
+ });
46
+ }
47
+ describe('JsonSchemaService', () => {
48
+ let jsonSchemaService;
49
+ beforeAll(() => {
50
+ const typeResolver = new TypeResolver_1.TypeResolver([primitiveTypes_1.FormattedTextType]);
51
+ jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(typeResolver, JsonSchemaService_1.ComponentInputMetaSchema);
52
+ });
53
+ describe('validateContentSchema', () => {
54
+ it('should return true for a valid content schema', () => {
55
+ const contentSchema = {
56
+ type: 'object',
57
+ properties: {
58
+ 'my-input': { type: 'number' },
59
+ },
60
+ required: ['my-input'],
61
+ };
62
+ const result = jsonSchemaService.validateInput(contentSchema);
63
+ expect(result).toBe(true);
64
+ });
65
+ it('should return false for an invalid content schema, where the required property is missed from a child object', () => {
66
+ const contentSchema = {
67
+ type: 'object',
68
+ properties: {
69
+ 'my-input': {
70
+ type: 'object',
71
+ properties: {
72
+ 'my-deep-input': { type: 'object' },
73
+ },
74
+ },
75
+ },
76
+ required: ['my-input'],
77
+ };
78
+ expectToThrowErrorMatchingTypeAndMessage(() => {
79
+ jsonSchemaService.validateInput(contentSchema);
80
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: The required property `required` is missing at `#/properties/my-input`', {
81
+ '#/properties/my-input': [
82
+ {
83
+ data: { key: 'required', pointer: '#/properties/my-input' },
84
+ message: 'The required property `required` is missing at `#/properties/my-input`',
85
+ },
86
+ ],
87
+ });
88
+ });
89
+ it('should throw a SchemaValidationError for an invalid content schema, top level type must be object', () => {
90
+ const contentSchema = {
91
+ type: 'array',
92
+ items: {
93
+ type: 'object',
94
+ properties: {
95
+ 'my-input': { type: 'number' },
96
+ },
97
+ required: ['my-input'],
98
+ },
99
+ };
100
+ expectToThrowErrorMatchingTypeAndMessage(() => {
101
+ jsonSchemaService.validateInput(contentSchema);
102
+ }, SchemaValidationError_1.SchemaValidationError, `failed validation: Expected value at \`#/type\` to be \`object\`, but value given is \`array\``, {
103
+ '#/type': [
104
+ {
105
+ data: { expected: 'object', pointer: '#/type', value: 'array' },
106
+ message: 'Expected value at `#/type` to be `object`, but value given is `array`',
107
+ },
108
+ ],
109
+ });
110
+ });
111
+ it('should throw a SchemaValidationError for an invalid content schema missing the required property', () => {
112
+ const contentSchema = {
113
+ type: 'object',
114
+ properties: {
115
+ 'my-input': { type: 'number' },
116
+ },
117
+ };
118
+ expectToThrowErrorMatchingTypeAndMessage(() => {
119
+ jsonSchemaService.validateInput(contentSchema);
120
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: The required property `required` is missing at `#`', {
121
+ '#': [
122
+ { data: { key: 'required', pointer: '#' }, message: 'The required property `required` is missing at `#`' },
123
+ ],
124
+ });
125
+ });
126
+ });
127
+ describe('SquizImage input', () => {
128
+ it('should validate a squizImage input', () => {
129
+ const schema = {
130
+ type: 'object',
131
+ properties: {
132
+ image: {
133
+ type: 'SquizImage',
134
+ },
135
+ },
136
+ };
137
+ const value = {
138
+ name: 'My Image',
139
+ alt: 'My Image that did not load',
140
+ caption: 'This above is a loaded image',
141
+ imageVariations: {
142
+ original: {
143
+ url: 'https://picsum.photos/200/300',
144
+ width: 100,
145
+ height: 100,
146
+ byteSize: 1000,
147
+ mimeType: 'image/jpeg',
148
+ aspectRatio: '1:1',
149
+ sha1Hash: '1234567890abcdef1234567890abcdef12345678',
150
+ },
151
+ },
152
+ };
153
+ expect(jsonSchemaService.validateInput(value, schema)).toEqual(true);
154
+ });
155
+ it('should error if SquizImage type is missing required properties', async () => {
156
+ const schema = {
157
+ type: 'object',
158
+ properties: {
159
+ myProp: {
160
+ type: 'SquizImage',
161
+ },
162
+ },
163
+ };
164
+ const value = {
165
+ // @ts-expect-error - missing required properties
166
+ myProp: {
167
+ alt: 'alt',
168
+ caption: 'caption',
169
+ name: 'name',
170
+ },
171
+ };
172
+ expectToThrowErrorMatchingTypeAndMessage(() => {
173
+ jsonSchemaService.validateInput(value, schema);
174
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: Expected `Object {"alt":"alt","caption":"caption","name":"name"}` (object) in `#/myProp` to be of type `SquizImage`', {
175
+ '#/myProp': [
176
+ {
177
+ data: {
178
+ expected: 'SquizImage',
179
+ pointer: '#/myProp',
180
+ received: 'object',
181
+ value: { alt: 'alt', caption: 'caption', name: 'name' },
182
+ },
183
+ message: 'Expected `Object {"alt":"alt","caption":"caption","name":"name"}` (object) in `#/myProp` to be of type `SquizImage`',
184
+ },
185
+ ],
186
+ });
187
+ });
188
+ });
189
+ describe('FormattedText input', () => {
190
+ it('should handle type as an array', () => {
191
+ const functionInputSchema = {
192
+ type: 'object',
193
+ properties: {
194
+ 'my-input': { type: ['number', 'string'] },
195
+ },
196
+ required: ['my-input'],
197
+ };
198
+ expect(jsonSchemaService.validateInput({
199
+ 'my-input': 'formattedText',
200
+ }, functionInputSchema)).toEqual(true);
201
+ expect(jsonSchemaService.validateInput({
202
+ 'my-input': 123,
203
+ }, functionInputSchema)).toEqual(true);
204
+ });
205
+ it.failing('should handle type is an array of both string and FormattedText', () => {
206
+ const formattedText = [
207
+ {
208
+ tag: 'p',
209
+ type: 'tag',
210
+ children: [
211
+ { type: 'text', value: 'This is some ' },
212
+ { type: 'text', value: 'Link to asset 12345' },
213
+ { type: 'text', value: ' with an image ' },
214
+ { type: 'text', value: '.' },
215
+ ],
216
+ },
217
+ ];
218
+ const functionInputSchema = {
219
+ type: 'object',
220
+ properties: {
221
+ 'my-input': { type: ['FormattedText', 'string'] },
222
+ },
223
+ required: ['my-input'],
224
+ };
225
+ expect(jsonSchemaService.validateInput({
226
+ 'my-input': formattedText,
227
+ }, functionInputSchema)).toEqual(true);
228
+ expect(jsonSchemaService.validateInput({
229
+ 'my-input': 'hello',
230
+ }, functionInputSchema)).toEqual(true);
231
+ });
232
+ it('should return true if input is formatted text', () => {
233
+ const functionInputSchema = {
234
+ type: 'object',
235
+ properties: {
236
+ 'my-input': { type: 'FormattedText' },
237
+ },
238
+ required: ['my-input'],
239
+ };
240
+ const formattedText = [
241
+ {
242
+ tag: 'p',
243
+ type: 'tag',
244
+ children: [
245
+ { type: 'text', value: 'This is some ' },
246
+ { type: 'text', value: 'Link to asset 12345' },
247
+ { type: 'text', value: ' with an image ' },
248
+ { type: 'text', value: '.' },
249
+ ],
250
+ },
251
+ ];
252
+ const inputValue = {
253
+ 'my-input': formattedText,
254
+ };
255
+ expect(() => jsonSchemaService.validateInput(inputValue, functionInputSchema)).not.toThrow();
256
+ });
257
+ it('should throw an error if the FormattedText input is not formatted text', () => {
258
+ const functionInputSchema = {
259
+ type: 'object',
260
+ properties: {
261
+ 'my-input': { type: 'FormattedText' },
262
+ },
263
+ required: ['my-input'],
264
+ };
265
+ const inputValue = {
266
+ 'my-input': 123,
267
+ };
268
+ expectToThrowErrorMatchingTypeAndMessage(() => {
269
+ jsonSchemaService.validateInput(inputValue, functionInputSchema);
270
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `123` in `#/my-input` does not match any given oneof schema', {
271
+ '#/my-input': [
272
+ {
273
+ data: {
274
+ errors: [
275
+ {
276
+ code: 'type-error',
277
+ data: { expected: 'array', pointer: '#/my-input', received: 'number', value: 123 },
278
+ message: 'Expected `123` (number) in `#/my-input` to be of type `array`',
279
+ name: 'TypeError',
280
+ type: 'error',
281
+ },
282
+ ],
283
+ oneOf: [{ $ref: 'FormattedText.json' }],
284
+ pointer: '#/my-input',
285
+ value: '123',
286
+ },
287
+ message: 'Value `123` in `#/my-input` does not match any given oneof schema',
288
+ },
289
+ ],
290
+ });
291
+ });
292
+ it('should throw an error if the FormattedText input is invalid formatted text', () => {
293
+ const functionInputSchema = {
294
+ type: 'object',
295
+ properties: {
296
+ 'my-input': { type: 'FormattedText' },
297
+ },
298
+ required: ['my-input'],
299
+ };
300
+ const inputValue = {
301
+ 'my-input': {
302
+ something: 'aa',
303
+ },
304
+ };
305
+ expectToThrowErrorMatchingTypeAndMessage(() => {
306
+ jsonSchemaService.validateInput(inputValue, functionInputSchema);
307
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `{"something":"aa"}` in `#/my-input` does not match any given oneof schema', {
308
+ '#/my-input': [
309
+ {
310
+ data: {
311
+ errors: [
312
+ {
313
+ code: 'type-error',
314
+ data: { expected: 'array', pointer: '#/my-input', received: 'object', value: { something: 'aa' } },
315
+ message: 'Expected `Object {"something":"aa"}` (object) in `#/my-input` to be of type `array`',
316
+ name: 'TypeError',
317
+ type: 'error',
318
+ },
319
+ ],
320
+ oneOf: [{ $ref: 'FormattedText.json' }],
321
+ pointer: '#/my-input',
322
+ value: '{"something":"aa"}',
323
+ },
324
+ message: 'Value `{"something":"aa"}` in `#/my-input` does not match any given oneof schema',
325
+ },
326
+ ],
327
+ });
328
+ });
329
+ it('should throw an error if the FormattedText input is invalid formatted text (deeply nested)', () => {
330
+ const functionInputSchema = {
331
+ type: 'object',
332
+ properties: {
333
+ 'my-input': { type: 'FormattedText' },
334
+ },
335
+ required: ['my-input'],
336
+ };
337
+ const formattedText = [
338
+ {
339
+ tag: 'p',
340
+ type: 'tag',
341
+ children: [
342
+ { type: 'text', value: 'This is some ' },
343
+ { type: 'text', value: 'Link to asset 12345' },
344
+ { type: 'text', value: ' with an image ' },
345
+ { type: 'text', value: 123 },
346
+ { type: 'text', value: '.' },
347
+ ],
348
+ },
349
+ ];
350
+ const inputValue = {
351
+ 'my-input': formattedText,
352
+ };
353
+ expectToThrowErrorMatchingTypeAndMessage(() => {
354
+ jsonSchemaService.validateInput(inputValue, functionInputSchema);
355
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `[{"tag":"p","type":"tag","children":[{"type":"text","value":"This is some "},{"type":"text","value":"Link to asset 12345"},{"type":"text","value":" with an image "},{"type":"text","value":123},{"type":"text","value":"."}]}]` in `#/my-input` does not match any given oneof schema', {
356
+ '#/my-input': [
357
+ {
358
+ data: {
359
+ errors: [
360
+ {
361
+ code: 'any-of-error',
362
+ data: {
363
+ anyOf: [
364
+ { $ref: '#/definitions/HigherOrderFormattedNodes' },
365
+ { $ref: '#/definitions/BaseFormattedNodes' },
366
+ ],
367
+ pointer: '#/my-input/0',
368
+ value: {
369
+ children: [
370
+ { type: 'text', value: 'This is some ' },
371
+ { type: 'text', value: 'Link to asset 12345' },
372
+ { type: 'text', value: ' with an image ' },
373
+ { type: 'text', value: 123 },
374
+ { type: 'text', value: '.' },
375
+ ],
376
+ tag: 'p',
377
+ type: 'tag',
378
+ },
379
+ },
380
+ message: 'Object at `#/my-input/0` does not match any schema',
381
+ name: 'AnyOfError',
382
+ type: 'error',
383
+ },
384
+ ],
385
+ oneOf: [{ $ref: 'FormattedText.json' }],
386
+ pointer: '#/my-input',
387
+ value: '[{"tag":"p","type":"tag","children":[{"type":"text","value":"This is some "},{"type":"text","value":"Link to asset 12345"},{"type":"text","value":" with an image "},{"type":"text","value":123},{"type":"text","value":"."}]}]',
388
+ },
389
+ message: 'Value `[{"tag":"p","type":"tag","children":[{"type":"text","value":"This is some "},{"type":"text","value":"Link to asset 12345"},{"type":"text","value":" with an image "},{"type":"text","value":123},{"type":"text","value":"."}]}]` in `#/my-input` does not match any given oneof schema',
390
+ },
391
+ ],
392
+ });
393
+ });
394
+ it('should validate an array of formatted texts', () => {
395
+ const formattedText = [
396
+ {
397
+ tag: 'p',
398
+ type: 'tag',
399
+ children: [{ type: 'text', value: 'hello' }],
400
+ },
401
+ ];
402
+ const schema = {
403
+ type: 'object',
404
+ properties: {
405
+ arr: {
406
+ type: 'array',
407
+ items: { type: 'FormattedText' },
408
+ },
409
+ },
410
+ };
411
+ const value = {
412
+ arr: [formattedText],
413
+ };
414
+ expect(jsonSchemaService.validateInput(value, schema)).toEqual(true);
415
+ });
416
+ it('should throw an error if the FormattedText input is invalid formatted text (deeply, deeply nested)', () => {
417
+ const formattedText = [
418
+ {
419
+ tag: 'p',
420
+ type: 'tag',
421
+ children: [{ type: 'text', value: 'hello' }],
422
+ },
423
+ ];
424
+ const inputValue = {
425
+ 'my-input': formattedText,
426
+ deep: {
427
+ arr: [
428
+ {
429
+ prop: formattedText,
430
+ formattedTextArray: [formattedText, formattedText, { bad: 'data' }],
431
+ },
432
+ ],
433
+ },
434
+ };
435
+ const functionInputSchema = {
436
+ type: 'object',
437
+ properties: {
438
+ 'my-input': { type: 'FormattedText' },
439
+ deep: {
440
+ type: 'object',
441
+ properties: {
442
+ arr: {
443
+ type: 'array',
444
+ items: {
445
+ type: 'object',
446
+ required: ['prop', 'formattedTextArray'],
447
+ properties: {
448
+ prop: 'FormattedText',
449
+ formattedTextArray: {
450
+ type: 'array',
451
+ items: {
452
+ type: 'FormattedText',
453
+ },
454
+ },
455
+ },
456
+ },
457
+ },
458
+ },
459
+ required: ['arr'],
460
+ },
461
+ },
462
+ required: ['my-input', 'deep'],
463
+ };
464
+ expectToThrowErrorMatchingTypeAndMessage(() => {
465
+ jsonSchemaService.validateInput(inputValue, functionInputSchema);
466
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `{"bad":"data"}` in `#/deep/arr/0/formattedTextArray/2` does not match any given oneof schema', {
467
+ '#/deep/arr/0/formattedTextArray/2': [
468
+ {
469
+ data: {
470
+ errors: [
471
+ {
472
+ code: 'type-error',
473
+ data: {
474
+ expected: 'array',
475
+ pointer: '#/deep/arr/0/formattedTextArray/2',
476
+ received: 'object',
477
+ value: { bad: 'data' },
478
+ },
479
+ message: 'Expected `Object {"bad":"data"}` (object) in `#/deep/arr/0/formattedTextArray/2` to be of type `array`',
480
+ name: 'TypeError',
481
+ type: 'error',
482
+ },
483
+ ],
484
+ oneOf: [{ $ref: 'FormattedText.json' }],
485
+ pointer: '#/deep/arr/0/formattedTextArray/2',
486
+ value: '{"bad":"data"}',
487
+ },
488
+ message: 'Value `{"bad":"data"}` in `#/deep/arr/0/formattedTextArray/2` does not match any given oneof schema',
489
+ },
490
+ ],
491
+ });
492
+ });
493
+ it('should validate a FormattedText value when the schema is a $ref', async () => {
494
+ const formattedText = [
495
+ {
496
+ tag: 'p',
497
+ type: 'tag',
498
+ children: [{ type: 'text', value: 'hello' }],
499
+ },
500
+ ];
501
+ const schema = {
502
+ type: 'object',
503
+ properties: {
504
+ 'my-input': { $ref: '#/definitions/FormattedText' },
505
+ },
506
+ definitions: {
507
+ FormattedText: { type: 'FormattedText' },
508
+ },
509
+ required: ['my-input'],
510
+ };
511
+ const value = {
512
+ 'my-input': formattedText,
513
+ };
514
+ expect(jsonSchemaService.validateInput(value, schema)).toEqual(true);
515
+ });
516
+ it('should error when a FormattedText value is invalid when the schema is a $ref', async () => {
517
+ const schema = {
518
+ type: 'object',
519
+ properties: {
520
+ 'my-input': { $ref: '#/definitions/FormattedText' },
521
+ },
522
+ definitions: {
523
+ FormattedText: { type: 'FormattedText' },
524
+ },
525
+ required: ['my-input'],
526
+ };
527
+ const value = {
528
+ 'my-input': { bad: 'data' },
529
+ };
530
+ expectToThrowErrorMatchingTypeAndMessage(() => {
531
+ jsonSchemaService.validateInput(value, schema);
532
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `{"bad":"data"}` in `#/my-input` does not match any given oneof schema', {
533
+ '#/my-input': [
534
+ {
535
+ data: {
536
+ errors: [
537
+ {
538
+ code: 'type-error',
539
+ data: { expected: 'array', pointer: '#/my-input', received: 'object', value: { bad: 'data' } },
540
+ message: 'Expected `Object {"bad":"data"}` (object) in `#/my-input` to be of type `array`',
541
+ name: 'TypeError',
542
+ type: 'error',
543
+ },
544
+ ],
545
+ oneOf: [{ $ref: 'FormattedText.json' }],
546
+ pointer: '#/my-input',
547
+ value: '{"bad":"data"}',
548
+ },
549
+ message: 'Value `{"bad":"data"}` in `#/my-input` does not match any given oneof schema',
550
+ },
551
+ ],
552
+ });
553
+ });
554
+ it('should validate a FormattedText value when the schema is a $ref to a $ref', async () => {
555
+ const formattedText = [
556
+ {
557
+ tag: 'p',
558
+ type: 'tag',
559
+ children: [{ type: 'text', value: 'hello' }],
560
+ },
561
+ ];
562
+ const schema = {
563
+ type: 'object',
564
+ properties: {
565
+ 'my-input': { $ref: '#/definitions/FormattedText' },
566
+ },
567
+ definitions: {
568
+ FormattedText: { $ref: '#/definitions/FormattedText2' },
569
+ FormattedText2: { type: 'FormattedText' },
570
+ },
571
+ required: ['my-input'],
572
+ };
573
+ const value = {
574
+ 'my-input': formattedText,
575
+ };
576
+ expect(jsonSchemaService.validateInput(value, schema)).toEqual(true);
577
+ });
578
+ it('should validate a FormattedText value when the schema is in an if/then/else', async () => {
579
+ const formattedText = [
580
+ {
581
+ tag: 'p',
582
+ type: 'tag',
583
+ children: [{ type: 'text', value: 'hello' }],
584
+ },
585
+ ];
586
+ const schema = {
587
+ type: 'object',
588
+ properties: {
589
+ 'my-input': {
590
+ if: { type: 'string' },
591
+ then: { type: 'string' },
592
+ else: { type: 'FormattedText' },
593
+ },
594
+ },
595
+ required: ['my-input'],
596
+ };
597
+ const value = {
598
+ 'my-input': formattedText,
599
+ };
600
+ expect(jsonSchemaService.validateInput(value, schema)).toEqual(true);
601
+ });
602
+ it('should allow an empty array', async () => {
603
+ const schema = {
604
+ type: 'object',
605
+ properties: {
606
+ 'my-input': { type: 'FormattedText' },
607
+ },
608
+ required: [],
609
+ };
610
+ expect(jsonSchemaService.validateInput({ 'my-input': [] }, schema)).toEqual(true);
611
+ });
612
+ it.each([
613
+ ['with attributes', { title: 'Link title' }],
614
+ ['without attributes', undefined],
615
+ ])('should validate link-to-matrix-asset - %s', (_, attributes) => {
616
+ const formattedText = [
617
+ {
618
+ type: 'link-to-matrix-asset',
619
+ matrixIdentifier: 'matrix-identifier',
620
+ matrixDomain: 'https://matrix-api-url',
621
+ target: '_blank',
622
+ matrixAssetId: '12345',
623
+ children: [{ type: 'text', value: 'hello' }],
624
+ attributes,
625
+ },
626
+ ];
627
+ const schema = {
628
+ type: 'object',
629
+ properties: {
630
+ myInput: {
631
+ type: 'FormattedText',
632
+ },
633
+ },
634
+ };
635
+ const value = {
636
+ myInput: formattedText,
637
+ };
638
+ expect(jsonSchemaService.validateInput(value, schema)).toBe(true);
639
+ });
640
+ it('should throw if link-to-matrix-asset contains a reserved attribute', () => {
641
+ const formattedText = [
642
+ {
643
+ type: 'link-to-matrix-asset',
644
+ matrixIdentifier: 'matrix-identifier',
645
+ matrixDomain: 'https://matrix-api-url',
646
+ target: '_blank',
647
+ matrixAssetId: '12345',
648
+ children: [{ type: 'text', value: 'hello' }],
649
+ attributes: {
650
+ // href is reserved (resolved from the selected Matrix asset)
651
+ href: 'https://www.my-matrix.squiz.net',
652
+ },
653
+ },
654
+ ];
655
+ const schema = {
656
+ type: 'object',
657
+ properties: {
658
+ myInput: {
659
+ type: 'FormattedText',
660
+ },
661
+ },
662
+ };
663
+ const value = {
664
+ myInput: formattedText,
665
+ };
666
+ expect(() => jsonSchemaService.validateInput(value, schema)).toThrow(/does not match any given oneof schema/);
667
+ });
668
+ it.each([
669
+ ['with attributes', { title: 'Link title' }],
670
+ ['without attributes', undefined],
671
+ ])('should validate matrix-image - %s', (_, attributes) => {
672
+ const formattedText = [
673
+ {
674
+ type: 'matrix-image',
675
+ matrixIdentifier: 'matrix-identifier',
676
+ matrixDomain: 'https://matrix-api-url',
677
+ matrixAssetId: '12345',
678
+ attributes,
679
+ },
680
+ ];
681
+ const schema = {
682
+ type: 'object',
683
+ properties: {
684
+ myInput: {
685
+ type: 'FormattedText',
686
+ },
687
+ },
688
+ };
689
+ const value = {
690
+ myInput: formattedText,
691
+ };
692
+ expect(jsonSchemaService.validateInput(value, schema)).toBe(true);
693
+ });
694
+ it('should throw if matrix-image contains a reserved attribute', () => {
695
+ const formattedText = [
696
+ {
697
+ type: 'matrix-image',
698
+ matrixIdentifier: 'matrix-identifier',
699
+ matrixDomain: 'https://matrix-api-url',
700
+ matrixAssetId: '12345',
701
+ attributes: {
702
+ // src is reserved (resolved from the selected Matrix asset)
703
+ src: 'https://www.my-matrix.squiz.net/image.png',
704
+ },
705
+ },
706
+ ];
707
+ const schema = {
708
+ type: 'object',
709
+ properties: {
710
+ myInput: {
711
+ type: 'FormattedText',
712
+ },
713
+ },
714
+ };
715
+ const value = {
716
+ myInput: formattedText,
717
+ };
718
+ expect(() => jsonSchemaService.validateInput(value, schema)).toThrow(/does not match any given oneof schema/);
719
+ });
720
+ it.each([
721
+ ['with attributes', { title: 'Link title' }],
722
+ ['without attributes', undefined],
723
+ ])('should validate dam-image - %s', (_, attributes) => {
724
+ const formattedText = [
725
+ {
726
+ type: 'dam-image',
727
+ damSystemIdentifier: 'dam-identifier',
728
+ damObjectId: '12345',
729
+ damSystemType: 'bynder',
730
+ attributes,
731
+ },
732
+ ];
733
+ const schema = {
734
+ type: 'object',
735
+ properties: {
736
+ myInput: {
737
+ type: 'FormattedText',
738
+ },
739
+ },
740
+ };
741
+ const value = {
742
+ myInput: formattedText,
743
+ };
744
+ expect(jsonSchemaService.validateInput(value, schema)).toBe(true);
745
+ });
746
+ it('should throw if dam-image contains a reserved attribute', () => {
747
+ const formattedText = [
748
+ {
749
+ type: 'dam-image',
750
+ damSystemIdentifier: 'dam-identifier',
751
+ damObjectId: '12345',
752
+ damSystemType: 'bynder',
753
+ attributes: {
754
+ // src is reserved (resolved from the selected DAM asset)
755
+ src: 'https://www.my-matrix.squiz.net/image.png',
756
+ },
757
+ },
758
+ ];
759
+ const schema = {
760
+ type: 'object',
761
+ properties: {
762
+ myInput: {
763
+ type: 'FormattedText',
764
+ },
765
+ },
766
+ };
767
+ const value = {
768
+ myInput: formattedText,
769
+ };
770
+ expect(() => jsonSchemaService.validateInput(value, schema)).toThrow(/does not match any given oneof schema/);
771
+ });
772
+ });
773
+ describe('standard inputs', () => {
774
+ const functionInputSchema = {
775
+ type: 'object',
776
+ properties: {
777
+ 'my-input': { type: 'number' },
778
+ },
779
+ required: ['my-input'],
780
+ };
781
+ it('should return true for valid input values', () => {
782
+ const inputValue = {
783
+ 'my-input': 123,
784
+ };
785
+ const result = jsonSchemaService.validateInput(inputValue, functionInputSchema);
786
+ expect(result).toBe(true);
787
+ });
788
+ it('should throw a SchemaValidationError for invalid input type', () => {
789
+ const inputValue = {
790
+ 'my-input': '123',
791
+ };
792
+ expectToThrowErrorMatchingTypeAndMessage(() => {
793
+ jsonSchemaService.validateInput(inputValue, functionInputSchema);
794
+ }, SchemaValidationError_1.SchemaValidationError, `failed validation: Expected \`123\` (string) in \`#/my-input\` to be of type \`number\``, {
795
+ '#/my-input': [
796
+ {
797
+ data: { expected: 'number', pointer: '#/my-input', received: 'string', value: '123' },
798
+ message: 'Expected `123` (string) in `#/my-input` to be of type `number`',
799
+ },
800
+ ],
801
+ });
802
+ });
803
+ it('should throw a SchemaValidationError for invalid input missing properties', () => {
804
+ const inputValue = {};
805
+ expectToThrowErrorMatchingTypeAndMessage(() => {
806
+ jsonSchemaService.validateInput(inputValue, functionInputSchema);
807
+ }, SchemaValidationError_1.SchemaValidationError, `failed validation: The required property \`my-input\` is missing at \`#\``, {
808
+ '#': [
809
+ { data: { key: 'my-input', pointer: '#' }, message: 'The required property `my-input` is missing at `#`' },
810
+ ],
811
+ });
812
+ });
813
+ it('should throw a SchemaValidationError with a truncated enum value list if there are more than 5 enum options', () => {
814
+ expectToThrowErrorMatchingTypeAndMessage(() => {
815
+ jsonSchemaService.validateInput({ enum: 'z' }, { type: 'object', properties: { enum: { type: 'string', enum: ['a', 'b', 'c', 'd', 'e', 'f', 'g'] } } });
816
+ }, SchemaValidationError_1.SchemaValidationError, 'failed validation: Expected given value `z` in #/enum` to be one of `[a, b, c, d, e, ... 2 more]`', {
817
+ '#/enum': [
818
+ {
819
+ data: { pointer: '#/enum', value: 'z', values: ['a', 'b', 'c', 'd', 'e', 'f', 'g'] },
820
+ message: 'Expected given value `z` in #/enum` to be one of `[a, b, c, d, e, ... 2 more]`',
821
+ },
822
+ ],
823
+ });
824
+ });
825
+ // TODO DEVX-658
826
+ it.skip('should throw a SchemaValidationError for invalid input additional properties', () => {
827
+ const inputValue = {
828
+ 'my-input': 123,
829
+ 'my-input-2': 123,
830
+ };
831
+ expect(() => {
832
+ jsonSchemaService.validateInput(inputValue, functionInputSchema);
833
+ }).toThrowErrorMatchingInlineSnapshot();
834
+ });
835
+ });
836
+ describe('validateInput', () => {
837
+ it.each([String('123'), Number(123), [123]])('should validate any primitive type with its resolvable type %s', (propertyValue) => {
838
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
839
+ const MyResolvableNumber = resolvableTypeFixture('MyResolvableNumber', { type: 'number' });
840
+ const MyResolvableArray = resolvableTypeFixture('MyResolvableArray', { type: 'array' });
841
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [MyResolvableNumber, MyResolvableArray], {
842
+ MyPrimitive: {
843
+ // @ts-expect-error - fixture is unknown but we know the actual shape
844
+ MyResolvableNumber: (value) => value.toString(),
845
+ // @ts-expect-error - fixture is unknown but we know the actual shape
846
+ MyResolvableArray: (value) => value.join(''),
847
+ },
848
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
849
+ expect(jsonSchemaService.validateInput({ myProperty: propertyValue }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } })).toEqual(true);
850
+ });
851
+ it('should error when a primitive type is provided a value that cannot be resolved by its resolvable types', () => {
852
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
853
+ const MyResolvableNumber = resolvableTypeFixture('MyResolvableNumber', { type: 'number' });
854
+ const MyResolvableArray = resolvableTypeFixture('MyResolvableArray', { type: 'array' });
855
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [MyResolvableNumber, MyResolvableArray], {
856
+ MyPrimitive: {
857
+ // @ts-expect-error - fixture is unknown but we know the actual shape
858
+ MyResolvableNumber: (value) => value.toString(),
859
+ // @ts-expect-error - fixture is unknown but we know the actual shape
860
+ MyResolvableArray: (value) => value.join(''),
861
+ },
862
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
863
+ expect(() => {
864
+ jsonSchemaService.validateInput({ myProperty: true }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } });
865
+ }).toThrowError();
866
+ });
867
+ it.each([String('123'), Number(123), [123]])('should validate a primitive type when defined as a ref with resolvable value %s', (propertyValue) => {
868
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
869
+ const MyResolvableNumber = resolvableTypeFixture('MyResolvableNumber', { type: 'number' });
870
+ const MyResolvableArray = resolvableTypeFixture('MyResolvableArray', { type: 'array' });
871
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [MyResolvableNumber, MyResolvableArray], {
872
+ MyPrimitive: {
873
+ // @ts-expect-error - fixture is unknown but we know the actual shape
874
+ MyResolvableNumber: (value) => value.toString(),
875
+ // @ts-expect-error - fixture is unknown but we know the actual shape
876
+ MyResolvableArray: (value) => value.join(''),
877
+ },
878
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
879
+ expect(jsonSchemaService.validateInput({ myProperty: propertyValue }, {
880
+ type: 'object',
881
+ properties: { myProperty: { $ref: '#/definitions/Ref' } },
882
+ definitions: { Ref: { type: 'MyPrimitive' } },
883
+ })).toEqual(true);
884
+ });
885
+ it('should not validate on a primitive type against a resolvable type when a resolver is not defined', () => {
886
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
887
+ const MyResolvableNumber = resolvableTypeFixture('MyResolvableNumber', { type: 'number' });
888
+ const MyResolvableArray = resolvableTypeFixture('MyResolvableArray', { type: 'array' });
889
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [MyResolvableNumber, MyResolvableArray], {
890
+ MyPrimitive: {
891
+ // @ts-expect-error - fixture is unknown but we know the actual shape
892
+ MyResolvableNumber: (value) => value.toString(),
893
+ },
894
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
895
+ expect(() => {
896
+ jsonSchemaService.validateInput({ myProperty: [123] }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } });
897
+ }).toThrowError();
898
+ });
899
+ it('should validate a primitive type against similar but different resolvable types', () => {
900
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
901
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [
902
+ resolvableTypeFixture('MyResolvableSrcNumber', {
903
+ type: 'object',
904
+ properties: {
905
+ src: { type: 'number' },
906
+ },
907
+ }),
908
+ resolvableTypeFixture('MyResolvableSrcString', {
909
+ type: 'object',
910
+ properties: {
911
+ src: { type: 'string' },
912
+ },
913
+ }),
914
+ ], {
915
+ MyPrimitive: {
916
+ // @ts-expect-error - fixture is unknown but we know the actual shape
917
+ MyResolvableSrcNumber: (value) => value.src.toString(),
918
+ // @ts-expect-error - fixture is unknown but we know the actual shape
919
+ MyResolvableSrcString: (value) => value.src,
920
+ },
921
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
922
+ expect(jsonSchemaService.validateInput({
923
+ myProperty: {
924
+ src: 123,
925
+ },
926
+ }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } })).toEqual(true);
927
+ expect(jsonSchemaService.validateInput({
928
+ myProperty: {
929
+ src: '123',
930
+ },
931
+ }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } })).toEqual(true);
932
+ });
933
+ });
934
+ describe('resolveInput', () => {
935
+ it.each([String('123'), Number(123), [123]])('should resolve a primitive type from its resolvable type %s', async (resolvableValue) => {
936
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
937
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [
938
+ resolvableTypeFixture('MyResolvableNumber', { type: 'number' }),
939
+ resolvableTypeFixture('MyResolvableArray', { type: 'array' }),
940
+ ], {
941
+ MyPrimitive: {
942
+ // @ts-expect-error - fixture is unknown but we know the actual shape
943
+ MyResolvableNumber: (value) => value.toString(),
944
+ // @ts-expect-error - fixture is unknown but we know the actual shape
945
+ MyResolvableArray: (value) => value.join(''),
946
+ },
947
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
948
+ await expect(jsonSchemaService.resolveInput({ myProperty: resolvableValue }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } })).resolves.toEqual({ myProperty: '123' });
949
+ });
950
+ it.each([
951
+ [{ src: 'MyString' }, 'MyString'],
952
+ [{ src: 1132 }, '1132'],
953
+ ])('should resolve a resolvable type %s against the correct resolver to %s', async (resolvableValue, output) => {
954
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
955
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [
956
+ resolvableTypeFixture('MyResolvableSrcString', {
957
+ type: 'object',
958
+ properties: { src: { type: 'string' } },
959
+ }),
960
+ resolvableTypeFixture('MyResolvableSrcNumber', {
961
+ type: 'object',
962
+ properties: { src: { type: 'number' } },
963
+ }),
964
+ ], {
965
+ MyPrimitive: {
966
+ // @ts-expect-error - fixture is unknown but we know the actual shape
967
+ MyResolvableSrcNumber: (value) => value.src.toString(),
968
+ // @ts-expect-error - fixture is unknown but we know the actual shape
969
+ MyResolvableSrcString: (value) => value.src,
970
+ },
971
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
972
+ await expect(jsonSchemaService.resolveInput({ myProperty: resolvableValue }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' } } })).resolves.toEqual({ myProperty: output });
973
+ });
974
+ it('should resolve a primitive type from its resolvable type %s', async () => {
975
+ const primitiveSchema = primitiveTypeFixture('MyPrimitive', { type: 'string' });
976
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(new TypeResolver_1.TypeResolver([primitiveSchema], [resolvableTypeFixture('MyResolvableWithError', { type: 'number' })], {
977
+ MyPrimitive: {
978
+ // @ts-expect-error - fixture is unknown but we know the actual shape
979
+ MyResolvableWithError: (_value) => {
980
+ throw new Error('Failed resolving!!');
981
+ },
982
+ },
983
+ }), JsonSchemaService_1.ComponentInputMetaSchema);
984
+ await expect(jsonSchemaService.resolveInput({ myProperty: 123, myProperty2: 234 }, { type: 'object', properties: { myProperty: { type: 'MyPrimitive' }, myProperty2: { type: 'MyPrimitive' } } })).rejects.toThrowErrorMatchingInlineSnapshot(`
985
+ "Error(s) occurred when resolving JSON:
986
+ Error: Error resolving JSON at #/myProperty: Failed resolving!!
987
+ Error: Error resolving JSON at #/myProperty2: Failed resolving!!"
988
+ `);
989
+ });
990
+ it('should resolve a FormattedText empty list', async () => {
991
+ const types = TypeResolverBuilder_1.TypeResolverBuilder.new().addPrimitive(primitiveTypes_1.FormattedTextType).build();
992
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(types, JsonSchemaService_1.ComponentInputMetaSchema);
993
+ await expect(jsonSchemaService.resolveInput({ myProp: [] }, { type: 'object', properties: { myProp: { type: 'FormattedText' } }, required: [] })).resolves.toEqual({ myProp: [] });
994
+ });
995
+ });
996
+ });
997
+ describe('JSONSchemaService - validation', () => {
998
+ const typeResolver = TypeResolverBuilder_1.TypeResolverBuilder.new()
999
+ .addPrimitive(primitiveTypes_1.SquizImageType)
1000
+ .addPrimitive(primitiveTypes_1.SquizLinkType)
1001
+ .addPrimitive(primitiveTypes_1.FormattedTextType)
1002
+ .build();
1003
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(typeResolver, JsonSchemaService_1.ComponentInputMetaSchema);
1004
+ it('should validate a schema with all the squiz primitive types', () => {
1005
+ const schema = {
1006
+ type: 'object',
1007
+ properties: {
1008
+ image: { type: 'SquizImage' },
1009
+ link: { type: 'SquizLink' },
1010
+ text: { type: 'FormattedText' },
1011
+ },
1012
+ required: ['image', 'link', 'text'],
1013
+ };
1014
+ const formattedText = [
1015
+ {
1016
+ tag: 'p',
1017
+ type: 'tag',
1018
+ children: [{ type: 'text', value: 'hello' }],
1019
+ },
1020
+ ];
1021
+ const input = {
1022
+ image: {
1023
+ name: 'test-image.jpeg',
1024
+ imageVariations: {
1025
+ original: {
1026
+ aspectRatio: '1:1',
1027
+ height: 100,
1028
+ width: 100,
1029
+ url: 'https://www.squiz.net',
1030
+ byteSize: 100,
1031
+ mimeType: 'image/jpeg',
1032
+ sha1Hash: '123',
1033
+ },
1034
+ },
1035
+ },
1036
+ link: {
1037
+ text: 'test-link',
1038
+ url: 'https://www.squiz.net',
1039
+ target: '_blank',
1040
+ },
1041
+ text: formattedText,
1042
+ };
1043
+ const result = jsonSchemaService.validateInput(input, schema);
1044
+ expect(result).toEqual(true);
1045
+ });
1046
+ it('should validate a schema with all the squiz primitive types and matrix-asset-uri format', () => {
1047
+ const schema = {
1048
+ type: 'object',
1049
+ properties: {
1050
+ image: { type: 'SquizImage' },
1051
+ link: { type: 'SquizLink' },
1052
+ text: { type: 'FormattedText' },
1053
+ asset: {
1054
+ type: 'string',
1055
+ format: 'matrix-asset-uri',
1056
+ },
1057
+ },
1058
+ required: ['image', 'link', 'text', 'asset'],
1059
+ };
1060
+ const formattedText = [
1061
+ {
1062
+ tag: 'p',
1063
+ type: 'tag',
1064
+ children: [{ type: 'text', value: 'hello' }],
1065
+ },
1066
+ ];
1067
+ const input = {
1068
+ image: {
1069
+ name: 'test-image.jpeg',
1070
+ imageVariations: {
1071
+ original: {
1072
+ aspectRatio: '1:1',
1073
+ height: 100,
1074
+ width: 100,
1075
+ url: 'https://www.squiz.net',
1076
+ byteSize: 100,
1077
+ mimeType: 'image/jpeg',
1078
+ sha1Hash: '123',
1079
+ },
1080
+ },
1081
+ },
1082
+ link: {
1083
+ text: 'test-link',
1084
+ url: 'https://www.squiz.net',
1085
+ target: '_blank',
1086
+ },
1087
+ text: formattedText,
1088
+ asset: 'matrix-asset://identifier/123',
1089
+ };
1090
+ const result = jsonSchemaService.validateInput(input, schema);
1091
+ expect(result).toEqual(true);
1092
+ });
1093
+ it('should catch validation errors when there is a schema with all the squiz primitive types', () => {
1094
+ const schema = {
1095
+ type: 'object',
1096
+ properties: {
1097
+ image: { type: 'SquizImage' },
1098
+ link: { type: 'SquizLink' },
1099
+ text: { type: 'FormattedText' },
1100
+ },
1101
+ required: ['image', 'link', 'text'],
1102
+ };
1103
+ const formattedText = [
1104
+ //@ts-expect-error - wrong type
1105
+ {
1106
+ children: [{ type: 'text', value: 'hello' }],
1107
+ },
1108
+ ];
1109
+ const input = {
1110
+ image: {
1111
+ name: 'test-image.jpeg',
1112
+ imageVariations: {
1113
+ //@ts-expect-error - wrong type
1114
+ original: {
1115
+ width: 100,
1116
+ url: 'https://www.squiz.net',
1117
+ byteSize: 100,
1118
+ mimeType: 'image/jpeg',
1119
+ sha1Hash: '123',
1120
+ },
1121
+ },
1122
+ },
1123
+ //@ts-expect-error - wrong type
1124
+ link: {
1125
+ text: 'test-link',
1126
+ target: '_blank',
1127
+ },
1128
+ text: formattedText,
1129
+ };
1130
+ expectToThrowErrorMatchingTypeAndMessage(() => jsonSchemaService.validateInput(input, schema), SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `{"name":"test-image.jpeg","imageVariations":{"original":{"width":100,"url":"https://www.squiz.net","byteSize":100,"mimeType":"image/jpeg","sha1Hash":"123"}}}` in `#/image` does not match any given oneof schema,\nValue `{"text":"test-link","target":"_blank"}` in `#/link` does not match any given oneof schema,\nValue `[{"children":[{"type":"text","value":"hello"}]}]` in `#/text` does not match any given oneof schema', {
1131
+ '#/image': [
1132
+ {
1133
+ data: {
1134
+ errors: [
1135
+ {
1136
+ code: 'required-property-error',
1137
+ data: { key: 'height', pointer: '#/image/imageVariations/original' },
1138
+ message: 'The required property `height` is missing at `#/image/imageVariations/original`',
1139
+ name: 'RequiredPropertyError',
1140
+ type: 'error',
1141
+ },
1142
+ {
1143
+ code: 'required-property-error',
1144
+ data: { key: 'aspectRatio', pointer: '#/image/imageVariations/original' },
1145
+ message: 'The required property `aspectRatio` is missing at `#/image/imageVariations/original`',
1146
+ name: 'RequiredPropertyError',
1147
+ type: 'error',
1148
+ },
1149
+ ],
1150
+ oneOf: [{ $ref: 'SquizImage.json' }],
1151
+ pointer: '#/image',
1152
+ value: '{"name":"test-image.jpeg","imageVariations":{"original":{"width":100,"url":"https://www.squiz.net","byteSize":100,"mimeType":"image/jpeg","sha1Hash":"123"}}}',
1153
+ },
1154
+ message: 'Value `{"name":"test-image.jpeg","imageVariations":{"original":{"width":100,"url":"https://www.squiz.net","byteSize":100,"mimeType":"image/jpeg","sha1Hash":"123"}}}` in `#/image` does not match any given oneof schema',
1155
+ },
1156
+ ],
1157
+ '#/link': [
1158
+ {
1159
+ data: {
1160
+ errors: [
1161
+ {
1162
+ code: 'required-property-error',
1163
+ data: { key: 'url', pointer: '#/link' },
1164
+ message: 'The required property `url` is missing at `#/link`',
1165
+ name: 'RequiredPropertyError',
1166
+ type: 'error',
1167
+ },
1168
+ ],
1169
+ oneOf: [{ $ref: 'SquizLink.json' }],
1170
+ pointer: '#/link',
1171
+ value: '{"text":"test-link","target":"_blank"}',
1172
+ },
1173
+ message: 'Value `{"text":"test-link","target":"_blank"}` in `#/link` does not match any given oneof schema',
1174
+ },
1175
+ ],
1176
+ '#/text': [
1177
+ {
1178
+ data: {
1179
+ errors: [
1180
+ {
1181
+ code: 'any-of-error',
1182
+ data: {
1183
+ anyOf: [
1184
+ { $ref: '#/definitions/HigherOrderFormattedNodes' },
1185
+ { $ref: '#/definitions/BaseFormattedNodes' },
1186
+ ],
1187
+ pointer: '#/text/0',
1188
+ value: { children: [{ type: 'text', value: 'hello' }] },
1189
+ },
1190
+ message: 'Object at `#/text/0` does not match any schema',
1191
+ name: 'AnyOfError',
1192
+ type: 'error',
1193
+ },
1194
+ ],
1195
+ oneOf: [{ $ref: 'FormattedText.json' }],
1196
+ pointer: '#/text',
1197
+ value: '[{"children":[{"type":"text","value":"hello"}]}]',
1198
+ },
1199
+ message: 'Value `[{"children":[{"type":"text","value":"hello"}]}]` in `#/text` does not match any given oneof schema',
1200
+ },
1201
+ ],
1202
+ });
1203
+ });
1204
+ it('should catch validation errors when invalid matrix-asset-uri is provided with invalid other squiz primitive types ', () => {
1205
+ const schema = {
1206
+ type: 'object',
1207
+ properties: {
1208
+ image: { type: 'SquizImage' },
1209
+ link: { type: 'SquizLink' },
1210
+ text: { type: 'FormattedText' },
1211
+ asset: {
1212
+ type: 'string',
1213
+ format: 'matrix-asset-uri',
1214
+ },
1215
+ },
1216
+ required: ['image', 'link', 'text', 'asset'],
1217
+ };
1218
+ const formattedText = [
1219
+ //@ts-expect-error - wrong type
1220
+ {
1221
+ children: [{ type: 'text', value: 'hello' }],
1222
+ },
1223
+ ];
1224
+ const input = {
1225
+ image: {
1226
+ name: 'test-image.jpeg',
1227
+ imageVariations: {
1228
+ //@ts-expect-error - wrong type
1229
+ original: {
1230
+ width: 100,
1231
+ url: 'https://www.squiz.net',
1232
+ byteSize: 100,
1233
+ mimeType: 'image/jpeg',
1234
+ sha1Hash: '123',
1235
+ },
1236
+ },
1237
+ },
1238
+ //@ts-expect-error - wrong type
1239
+ link: {
1240
+ text: 'test-link',
1241
+ target: '_blank',
1242
+ },
1243
+ text: formattedText,
1244
+ // @ts-expect-error - wrong type
1245
+ asset: 'matrix://123',
1246
+ };
1247
+ expectToThrowErrorMatchingTypeAndMessage(() => jsonSchemaService.validateInput(input, schema), SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `{"name":"test-image.jpeg","imageVariations":{"original":{"width":100,"url":"https://www.squiz.net","byteSize":100,"mimeType":"image/jpeg","sha1Hash":"123"}}}` in `#/image` does not match any given oneof schema,\nValue `{"text":"test-link","target":"_blank"}` in `#/link` does not match any given oneof schema,\nValue `[{"children":[{"type":"text","value":"hello"}]}]` in `#/text` does not match any given oneof schema,\nValue matrix-asset-uri (matrix://123) in `#/asset` is not a valid matrix asset uri', {
1248
+ '#/asset': [
1249
+ {
1250
+ data: {
1251
+ errors: {
1252
+ assetId: {
1253
+ data: { expected: /^\d+(?::.+)?$/, received: '' },
1254
+ message: 'Matrix Asset Id has invalid format, must match /^d+(?::.+)?$/',
1255
+ },
1256
+ scheme: {
1257
+ data: { expected: 'matrix-asset', received: 'matrix' },
1258
+ message: 'Uri scheme is invalid, must match "matrix-asset"',
1259
+ },
1260
+ },
1261
+ pointer: '#/asset',
1262
+ value: 'matrix://123',
1263
+ },
1264
+ message: 'Value matrix-asset-uri (matrix://123) in `#/asset` is not a valid matrix asset uri',
1265
+ },
1266
+ ],
1267
+ '#/image': [
1268
+ {
1269
+ data: {
1270
+ errors: [
1271
+ {
1272
+ code: 'required-property-error',
1273
+ data: { key: 'height', pointer: '#/image/imageVariations/original' },
1274
+ message: 'The required property `height` is missing at `#/image/imageVariations/original`',
1275
+ name: 'RequiredPropertyError',
1276
+ type: 'error',
1277
+ },
1278
+ {
1279
+ code: 'required-property-error',
1280
+ data: { key: 'aspectRatio', pointer: '#/image/imageVariations/original' },
1281
+ message: 'The required property `aspectRatio` is missing at `#/image/imageVariations/original`',
1282
+ name: 'RequiredPropertyError',
1283
+ type: 'error',
1284
+ },
1285
+ ],
1286
+ oneOf: [{ $ref: 'SquizImage.json' }],
1287
+ pointer: '#/image',
1288
+ value: '{"name":"test-image.jpeg","imageVariations":{"original":{"width":100,"url":"https://www.squiz.net","byteSize":100,"mimeType":"image/jpeg","sha1Hash":"123"}}}',
1289
+ },
1290
+ message: 'Value `{"name":"test-image.jpeg","imageVariations":{"original":{"width":100,"url":"https://www.squiz.net","byteSize":100,"mimeType":"image/jpeg","sha1Hash":"123"}}}` in `#/image` does not match any given oneof schema',
1291
+ },
1292
+ ],
1293
+ '#/link': [
1294
+ {
1295
+ data: {
1296
+ errors: [
1297
+ {
1298
+ code: 'required-property-error',
1299
+ data: { key: 'url', pointer: '#/link' },
1300
+ message: 'The required property `url` is missing at `#/link`',
1301
+ name: 'RequiredPropertyError',
1302
+ type: 'error',
1303
+ },
1304
+ ],
1305
+ oneOf: [{ $ref: 'SquizLink.json' }],
1306
+ pointer: '#/link',
1307
+ value: '{"text":"test-link","target":"_blank"}',
1308
+ },
1309
+ message: 'Value `{"text":"test-link","target":"_blank"}` in `#/link` does not match any given oneof schema',
1310
+ },
1311
+ ],
1312
+ '#/text': [
1313
+ {
1314
+ data: {
1315
+ errors: [
1316
+ {
1317
+ code: 'any-of-error',
1318
+ data: {
1319
+ anyOf: [
1320
+ { $ref: '#/definitions/HigherOrderFormattedNodes' },
1321
+ { $ref: '#/definitions/BaseFormattedNodes' },
1322
+ ],
1323
+ pointer: '#/text/0',
1324
+ value: { children: [{ type: 'text', value: 'hello' }] },
1325
+ },
1326
+ message: 'Object at `#/text/0` does not match any schema',
1327
+ name: 'AnyOfError',
1328
+ type: 'error',
1329
+ },
1330
+ ],
1331
+ oneOf: [{ $ref: 'FormattedText.json' }],
1332
+ pointer: '#/text',
1333
+ value: '[{"children":[{"type":"text","value":"hello"}]}]',
1334
+ },
1335
+ message: 'Value `[{"children":[{"type":"text","value":"hello"}]}]` in `#/text` does not match any given oneof schema',
1336
+ },
1337
+ ],
1338
+ });
1339
+ });
1340
+ it('should validate when MatrixAssetType is being used for a squiz primitive type with resolver', () => {
1341
+ const typeResolver = TypeResolverBuilder_1.TypeResolverBuilder.new()
1342
+ .addPrimitive(primitiveTypes_1.SquizImageType)
1343
+ .addPrimitive(primitiveTypes_1.SquizLinkType)
1344
+ .addPrimitive(primitiveTypes_1.FormattedTextType)
1345
+ .addResolver(primitiveTypes_1.SquizImageType, resolvableTypes_1.MatrixAssetType, () => {
1346
+ return {
1347
+ name: '',
1348
+ imageVariations: {
1349
+ original: {
1350
+ width: 0,
1351
+ height: 0,
1352
+ url: '',
1353
+ mimeType: '',
1354
+ byteSize: 0,
1355
+ sha1Hash: '',
1356
+ aspectRatio: '',
1357
+ },
1358
+ },
1359
+ };
1360
+ })
1361
+ .build();
1362
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(typeResolver, JsonSchemaService_1.ComponentInputMetaSchema);
1363
+ const schema = {
1364
+ type: 'object',
1365
+ properties: {
1366
+ image: { type: 'SquizImage' },
1367
+ link: { type: 'SquizLink' },
1368
+ text: { type: 'FormattedText' },
1369
+ asset: {
1370
+ type: 'string',
1371
+ format: 'matrix-asset-uri',
1372
+ },
1373
+ },
1374
+ required: ['image', 'link', 'text', 'asset'],
1375
+ };
1376
+ const formattedText = [
1377
+ {
1378
+ tag: 'p',
1379
+ type: 'tag',
1380
+ children: [{ type: 'text', value: 'hello' }],
1381
+ },
1382
+ ];
1383
+ const input = {
1384
+ image: {
1385
+ matrixAssetId: '123',
1386
+ matrixIdentifier: 'identifier',
1387
+ matrixDomain: 'domain',
1388
+ },
1389
+ link: {
1390
+ text: 'test-link',
1391
+ url: 'https://www.squiz.net',
1392
+ target: '_blank',
1393
+ },
1394
+ text: formattedText,
1395
+ asset: 'matrix-asset://identifier/123',
1396
+ };
1397
+ expect(jsonSchemaService.validateInput(input, schema)).toEqual(true);
1398
+ });
1399
+ it('it should catch MatrixAssetType validation errors when being use for squiz primitive type with resolver', () => {
1400
+ const typeResolver = TypeResolverBuilder_1.TypeResolverBuilder.new()
1401
+ .addPrimitive(primitiveTypes_1.SquizImageType)
1402
+ .addPrimitive(primitiveTypes_1.SquizLinkType)
1403
+ .addPrimitive(primitiveTypes_1.FormattedTextType)
1404
+ .addResolver(primitiveTypes_1.SquizImageType, resolvableTypes_1.MatrixAssetType, () => {
1405
+ return {
1406
+ name: '',
1407
+ imageVariations: {
1408
+ original: {
1409
+ width: 0,
1410
+ height: 0,
1411
+ url: '',
1412
+ mimeType: '',
1413
+ byteSize: 0,
1414
+ sha1Hash: '',
1415
+ aspectRatio: '',
1416
+ },
1417
+ },
1418
+ };
1419
+ })
1420
+ .build();
1421
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(typeResolver, JsonSchemaService_1.ComponentInputMetaSchema);
1422
+ const schema = {
1423
+ type: 'object',
1424
+ properties: {
1425
+ image: { type: 'SquizImage' },
1426
+ },
1427
+ required: ['image'],
1428
+ };
1429
+ const input = {
1430
+ //@ts-expect-error - intentionally invalid input
1431
+ image: {
1432
+ matrixIdentifier: 'identifier',
1433
+ },
1434
+ };
1435
+ expectToThrowErrorMatchingTypeAndMessage(() => jsonSchemaService.validateInput(input, schema), SchemaValidationError_1.SchemaValidationError, 'failed validation: Value `{"matrixIdentifier":"identifier"}` in `#/image` does not match any given oneof schema', {
1436
+ '#/image': [
1437
+ {
1438
+ data: {
1439
+ errors: [
1440
+ {
1441
+ code: 'required-property-error',
1442
+ data: { key: 'name', pointer: '#/image' },
1443
+ message: 'The required property `name` is missing at `#/image`',
1444
+ name: 'RequiredPropertyError',
1445
+ type: 'error',
1446
+ },
1447
+ {
1448
+ code: 'required-property-error',
1449
+ data: { key: 'imageVariations', pointer: '#/image' },
1450
+ message: 'The required property `imageVariations` is missing at `#/image`',
1451
+ name: 'RequiredPropertyError',
1452
+ type: 'error',
1453
+ },
1454
+ {
1455
+ code: 'required-property-error',
1456
+ data: { key: 'matrixAssetId', pointer: '#/image' },
1457
+ message: 'The required property `matrixAssetId` is missing at `#/image`',
1458
+ name: 'RequiredPropertyError',
1459
+ type: 'error',
1460
+ },
1461
+ ],
1462
+ oneOf: [{ $ref: 'SquizImage.json' }, { $ref: 'MatrixAsset.json' }],
1463
+ pointer: '#/image',
1464
+ value: '{"matrixIdentifier":"identifier"}',
1465
+ },
1466
+ message: 'Value `{"matrixIdentifier":"identifier"}` in `#/image` does not match any given oneof schema',
1467
+ },
1468
+ ],
1469
+ });
1470
+ });
1471
+ it('should only resolve an array of items containing resolvable types, other arrays are unaffected', async () => {
1472
+ const typeResolver = TypeResolverBuilder_1.TypeResolverBuilder.new()
1473
+ .addPrimitive(primitiveTypes_1.SquizImageType)
1474
+ .addPrimitive(primitiveTypes_1.SquizLinkType)
1475
+ .addPrimitive(primitiveTypes_1.FormattedTextType)
1476
+ .addResolver(primitiveTypes_1.SquizImageType, resolvableTypes_1.MatrixAssetType, () => {
1477
+ return {
1478
+ name: '',
1479
+ imageVariations: {
1480
+ original: {
1481
+ width: 0,
1482
+ height: 0,
1483
+ url: '',
1484
+ mimeType: '',
1485
+ byteSize: 0,
1486
+ sha1Hash: '',
1487
+ aspectRatio: '',
1488
+ },
1489
+ },
1490
+ };
1491
+ })
1492
+ .addResolver(primitiveTypes_1.SquizLinkType, resolvableTypes_1.MatrixAssetLinkType, () => {
1493
+ return {
1494
+ text: 'link text',
1495
+ url: 'www.test.com',
1496
+ target: '_self',
1497
+ };
1498
+ })
1499
+ .build();
1500
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(typeResolver, JsonSchemaService_1.ComponentInputMetaSchema);
1501
+ const schema = {
1502
+ type: 'object',
1503
+ properties: {
1504
+ images: {
1505
+ description: 'Gallery images',
1506
+ type: 'array',
1507
+ items: {
1508
+ type: 'SquizImage',
1509
+ },
1510
+ },
1511
+ squizLink: {
1512
+ title: 'Squiz link',
1513
+ type: 'array',
1514
+ items: {
1515
+ type: 'SquizLink',
1516
+ },
1517
+ },
1518
+ //custom format
1519
+ multiLine: {
1520
+ title: 'Multi-line (textarea)',
1521
+ type: 'array',
1522
+ items: {
1523
+ type: 'string',
1524
+ format: 'multi-line',
1525
+ },
1526
+ },
1527
+ //string array
1528
+ listOfStrings: {
1529
+ type: 'array',
1530
+ title: 'A list of strings',
1531
+ items: {
1532
+ type: 'string',
1533
+ default: 'Holy smokes',
1534
+ },
1535
+ },
1536
+ },
1537
+ required: ['images', 'links'],
1538
+ };
1539
+ const input = {
1540
+ images: [
1541
+ {
1542
+ matrixDomain: 'https://feaas-page-render-us.dev.matrix.squiz.cloud/59',
1543
+ matrixAssetId: '160',
1544
+ matrixIdentifier: 'feaas-matrix-us',
1545
+ },
1546
+ ],
1547
+ squizLink: [
1548
+ {
1549
+ matrixDomain: 'https://feaas-page-render-us.dev.matrix.squiz.cloud/59',
1550
+ matrixAssetId: '160',
1551
+ matrixIdentifier: 'feaas-matrix-us',
1552
+ target: '_self',
1553
+ },
1554
+ ],
1555
+ multiline: ['wow', 'much', 'multiline'],
1556
+ listOfStrings: ['very', 'string'],
1557
+ };
1558
+ const result = await jsonSchemaService.resolveInput(input, schema);
1559
+ expect(result).toEqual({
1560
+ images: [
1561
+ {
1562
+ imageVariations: {
1563
+ original: { aspectRatio: '', byteSize: 0, height: 0, mimeType: '', sha1Hash: '', url: '', width: 0 },
1564
+ },
1565
+ name: '',
1566
+ },
1567
+ ],
1568
+ squizLink: [
1569
+ {
1570
+ text: 'link text',
1571
+ url: 'www.test.com',
1572
+ target: '_self',
1573
+ },
1574
+ ],
1575
+ multiline: ['wow', 'much', 'multiline'],
1576
+ listOfStrings: ['very', 'string'],
1577
+ });
1578
+ });
1579
+ it('should resolve multiple primitive type array items in multi-level nested array structures', async () => {
1580
+ const typeResolver = TypeResolverBuilder_1.TypeResolverBuilder.new()
1581
+ .addPrimitive(primitiveTypes_1.SquizLinkType)
1582
+ .addResolver(primitiveTypes_1.SquizLinkType, resolvableTypes_1.MatrixAssetLinkType, (input) => {
1583
+ if ('matrixIdentifier' in input) {
1584
+ return {
1585
+ text: 'link text',
1586
+ url: `www.test.com/asset/${input.matrixAssetId}`,
1587
+ target: input.target,
1588
+ };
1589
+ }
1590
+ return input;
1591
+ })
1592
+ .build();
1593
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(typeResolver, JsonSchemaService_1.ComponentInputMetaSchema);
1594
+ const schema = {
1595
+ type: 'object',
1596
+ properties: {
1597
+ object1: {
1598
+ type: 'object',
1599
+ required: [],
1600
+ properties: {
1601
+ array1: {
1602
+ type: 'array',
1603
+ items: {
1604
+ type: 'object',
1605
+ properties: {
1606
+ linksArray: {
1607
+ type: 'array',
1608
+ items: {
1609
+ type: 'SquizLink',
1610
+ },
1611
+ },
1612
+ },
1613
+ },
1614
+ },
1615
+ },
1616
+ },
1617
+ },
1618
+ };
1619
+ const input = {
1620
+ object1: {
1621
+ array1: [
1622
+ {
1623
+ linksArray: [
1624
+ {
1625
+ url: '#LineOne',
1626
+ text: 'Link One',
1627
+ target: '_blank',
1628
+ },
1629
+ {
1630
+ url: '#LineTwo',
1631
+ text: 'Link Two',
1632
+ target: '_blank',
1633
+ },
1634
+ {
1635
+ matrixAssetId: '100',
1636
+ matrixDomain: 'my-matrix.squiz.net',
1637
+ matrixIdentifier: 'my-matrix-identifier',
1638
+ target: '_blank',
1639
+ },
1640
+ ],
1641
+ },
1642
+ ],
1643
+ },
1644
+ };
1645
+ const result = await jsonSchemaService.resolveInput(input, schema);
1646
+ expect(result).toEqual({
1647
+ object1: {
1648
+ array1: [
1649
+ {
1650
+ linksArray: [
1651
+ {
1652
+ url: '#LineOne',
1653
+ text: 'Link One',
1654
+ target: '_blank',
1655
+ },
1656
+ {
1657
+ url: '#LineTwo',
1658
+ text: 'Link Two',
1659
+ target: '_blank',
1660
+ },
1661
+ {
1662
+ url: 'www.test.com/asset/100',
1663
+ text: 'link text',
1664
+ target: '_blank',
1665
+ },
1666
+ ],
1667
+ },
1668
+ ],
1669
+ },
1670
+ });
1671
+ });
1672
+ it('should not use the resolver for primitive items in a resolvable array', async () => {
1673
+ const mockMatrixAssetResolver = jest.fn((input) => {
1674
+ return {
1675
+ name: input.matrixAssetId,
1676
+ imageVariations: {
1677
+ original: {
1678
+ width: 0,
1679
+ height: 0,
1680
+ url: '',
1681
+ mimeType: '',
1682
+ byteSize: 0,
1683
+ sha1Hash: '',
1684
+ aspectRatio: '',
1685
+ },
1686
+ },
1687
+ };
1688
+ });
1689
+ const mockMatrixLinkResolver = jest.fn((input) => {
1690
+ return {
1691
+ text: input.matrixAssetId,
1692
+ url: 'www.test.com',
1693
+ target: '_self',
1694
+ };
1695
+ });
1696
+ const typeResolver = TypeResolverBuilder_1.TypeResolverBuilder.new()
1697
+ .addPrimitive(primitiveTypes_1.SquizImageType)
1698
+ .addPrimitive(primitiveTypes_1.SquizLinkType)
1699
+ .addPrimitive(primitiveTypes_1.FormattedTextType)
1700
+ .addResolver(primitiveTypes_1.SquizImageType, resolvableTypes_1.MatrixAssetType, mockMatrixAssetResolver)
1701
+ .addResolver(primitiveTypes_1.SquizLinkType, resolvableTypes_1.MatrixAssetLinkType, mockMatrixLinkResolver)
1702
+ .build();
1703
+ const jsonSchemaService = new JsonSchemaService_1.JSONSchemaService(typeResolver, JsonSchemaService_1.ComponentInputMetaSchema);
1704
+ const schema = {
1705
+ type: 'object',
1706
+ properties: {
1707
+ images: {
1708
+ description: 'Gallery images',
1709
+ type: 'array',
1710
+ items: {
1711
+ type: 'SquizImage',
1712
+ },
1713
+ },
1714
+ squizLink: {
1715
+ title: 'Squiz link',
1716
+ type: 'array',
1717
+ items: {
1718
+ type: 'SquizLink',
1719
+ },
1720
+ },
1721
+ //custom format
1722
+ multiLine: {
1723
+ title: 'Multi-line (textarea)',
1724
+ type: 'array',
1725
+ items: {
1726
+ type: 'string',
1727
+ format: 'multi-line',
1728
+ },
1729
+ },
1730
+ //string array
1731
+ listOfStrings: {
1732
+ type: 'array',
1733
+ title: 'A list of strings',
1734
+ items: {
1735
+ type: 'string',
1736
+ default: 'Holy smokes',
1737
+ },
1738
+ },
1739
+ },
1740
+ required: ['images', 'links'],
1741
+ };
1742
+ const input = {
1743
+ images: [
1744
+ {
1745
+ matrixDomain: 'https://feaas-page-render-us.dev.matrix.squiz.cloud/59',
1746
+ matrixAssetId: '160',
1747
+ matrixIdentifier: 'feaas-matrix-us',
1748
+ },
1749
+ {
1750
+ imageVariations: {
1751
+ original: { aspectRatio: '', byteSize: 0, height: 0, mimeType: '', sha1Hash: '', url: '', width: 0 },
1752
+ },
1753
+ name: '',
1754
+ },
1755
+ ],
1756
+ squizLink: [
1757
+ {
1758
+ matrixDomain: 'https://feaas-page-render-us.dev.matrix.squiz.cloud/59',
1759
+ matrixAssetId: '160',
1760
+ matrixIdentifier: 'feaas-matrix-us',
1761
+ target: '_self',
1762
+ },
1763
+ {
1764
+ text: 'link text',
1765
+ url: 'www.test.com',
1766
+ target: '_self',
1767
+ },
1768
+ ],
1769
+ multiline: ['wow', 'much', 'multiline'],
1770
+ listOfStrings: ['very', 'string'],
1771
+ };
1772
+ const result = await jsonSchemaService.resolveInput(input, schema);
1773
+ expect(result).toEqual({
1774
+ images: [
1775
+ {
1776
+ imageVariations: {
1777
+ original: { aspectRatio: '', byteSize: 0, height: 0, mimeType: '', sha1Hash: '', url: '', width: 0 },
1778
+ },
1779
+ name: input.images[0].matrixAssetId,
1780
+ },
1781
+ {
1782
+ imageVariations: {
1783
+ original: { aspectRatio: '', byteSize: 0, height: 0, mimeType: '', sha1Hash: '', url: '', width: 0 },
1784
+ },
1785
+ name: '',
1786
+ },
1787
+ ],
1788
+ squizLink: [
1789
+ {
1790
+ text: input.squizLink[0].matrixAssetId,
1791
+ url: 'www.test.com',
1792
+ target: '_self',
1793
+ },
1794
+ {
1795
+ text: 'link text',
1796
+ url: 'www.test.com',
1797
+ target: '_self',
1798
+ },
1799
+ ],
1800
+ multiline: ['wow', 'much', 'multiline'],
1801
+ listOfStrings: ['very', 'string'],
1802
+ });
1803
+ expect(mockMatrixAssetResolver).toHaveBeenCalledTimes(1);
1804
+ expect(mockMatrixLinkResolver).toHaveBeenCalledTimes(1);
1805
+ });
1806
+ });
1807
+ //# sourceMappingURL=JsonSchemaService.spec.js.map