@kravc/schema 2.7.6 → 2.8.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/README.md +19 -14
  2. package/dist/CredentialFactory.d.ts +345 -0
  3. package/dist/CredentialFactory.d.ts.map +1 -0
  4. package/dist/CredentialFactory.js +381 -0
  5. package/dist/CredentialFactory.js.map +1 -0
  6. package/dist/Schema.d.ts +448 -0
  7. package/dist/Schema.d.ts.map +1 -0
  8. package/dist/Schema.js +506 -0
  9. package/dist/Schema.js.map +1 -0
  10. package/dist/ValidationError.d.ts +70 -0
  11. package/dist/ValidationError.d.ts.map +1 -0
  12. package/dist/ValidationError.js +78 -0
  13. package/dist/ValidationError.js.map +1 -0
  14. package/dist/Validator.d.ts +483 -0
  15. package/dist/Validator.d.ts.map +1 -0
  16. package/dist/Validator.js +570 -0
  17. package/dist/Validator.js.map +1 -0
  18. package/dist/helpers/JsonSchema.d.ts +99 -0
  19. package/dist/helpers/JsonSchema.d.ts.map +1 -0
  20. package/dist/helpers/JsonSchema.js +3 -0
  21. package/dist/helpers/JsonSchema.js.map +1 -0
  22. package/dist/helpers/cleanupAttributes.d.ts +34 -0
  23. package/dist/helpers/cleanupAttributes.d.ts.map +1 -0
  24. package/dist/helpers/cleanupAttributes.js +113 -0
  25. package/dist/helpers/cleanupAttributes.js.map +1 -0
  26. package/dist/helpers/cleanupNulls.d.ts +27 -0
  27. package/dist/helpers/cleanupNulls.d.ts.map +1 -0
  28. package/dist/helpers/cleanupNulls.js +96 -0
  29. package/dist/helpers/cleanupNulls.js.map +1 -0
  30. package/dist/helpers/getReferenceIds.d.ts +169 -0
  31. package/dist/helpers/getReferenceIds.d.ts.map +1 -0
  32. package/dist/helpers/getReferenceIds.js +241 -0
  33. package/dist/helpers/getReferenceIds.js.map +1 -0
  34. package/dist/helpers/got.d.ts +60 -0
  35. package/dist/helpers/got.d.ts.map +1 -0
  36. package/dist/helpers/got.js +72 -0
  37. package/dist/helpers/got.js.map +1 -0
  38. package/dist/helpers/mapObjectProperties.d.ts +150 -0
  39. package/dist/helpers/mapObjectProperties.d.ts.map +1 -0
  40. package/dist/helpers/mapObjectProperties.js +229 -0
  41. package/dist/helpers/mapObjectProperties.js.map +1 -0
  42. package/dist/helpers/normalizeAttributes.d.ts +213 -0
  43. package/dist/helpers/normalizeAttributes.d.ts.map +1 -0
  44. package/dist/helpers/normalizeAttributes.js +243 -0
  45. package/dist/helpers/normalizeAttributes.js.map +1 -0
  46. package/dist/helpers/normalizeProperties.d.ts +168 -0
  47. package/dist/helpers/normalizeProperties.d.ts.map +1 -0
  48. package/dist/helpers/normalizeProperties.js +223 -0
  49. package/dist/helpers/normalizeProperties.js.map +1 -0
  50. package/dist/helpers/normalizeRequired.d.ts +159 -0
  51. package/dist/helpers/normalizeRequired.d.ts.map +1 -0
  52. package/dist/helpers/normalizeRequired.js +206 -0
  53. package/dist/helpers/normalizeRequired.js.map +1 -0
  54. package/dist/helpers/normalizeType.d.ts +81 -0
  55. package/dist/helpers/normalizeType.d.ts.map +1 -0
  56. package/dist/helpers/normalizeType.js +210 -0
  57. package/dist/helpers/normalizeType.js.map +1 -0
  58. package/dist/helpers/nullifyEmptyValues.d.ts +139 -0
  59. package/dist/helpers/nullifyEmptyValues.d.ts.map +1 -0
  60. package/dist/helpers/nullifyEmptyValues.js +191 -0
  61. package/dist/helpers/nullifyEmptyValues.js.map +1 -0
  62. package/dist/helpers/removeRequiredAndDefault.d.ts +106 -0
  63. package/dist/helpers/removeRequiredAndDefault.d.ts.map +1 -0
  64. package/dist/helpers/removeRequiredAndDefault.js +138 -0
  65. package/dist/helpers/removeRequiredAndDefault.js.map +1 -0
  66. package/dist/helpers/validateId.d.ts +39 -0
  67. package/dist/helpers/validateId.d.ts.map +1 -0
  68. package/dist/helpers/validateId.js +51 -0
  69. package/dist/helpers/validateId.js.map +1 -0
  70. package/dist/index.d.ts +7 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +17 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/ld/documentLoader.d.ts +8 -0
  75. package/dist/ld/documentLoader.d.ts.map +1 -0
  76. package/dist/ld/documentLoader.js +24 -0
  77. package/dist/ld/documentLoader.js.map +1 -0
  78. package/dist/ld/getLinkedDataAttributeType.d.ts +10 -0
  79. package/dist/ld/getLinkedDataAttributeType.d.ts.map +1 -0
  80. package/dist/ld/getLinkedDataAttributeType.js +32 -0
  81. package/dist/ld/getLinkedDataAttributeType.js.map +1 -0
  82. package/dist/ld/getLinkedDataContext.d.ts +19 -0
  83. package/dist/ld/getLinkedDataContext.d.ts.map +1 -0
  84. package/dist/ld/getLinkedDataContext.js +50 -0
  85. package/dist/ld/getLinkedDataContext.js.map +1 -0
  86. package/eslint.config.mjs +32 -52
  87. package/examples/credentials/createAccountCredential.ts +27 -0
  88. package/examples/credentials/createMineSweeperScoreCredential.ts +115 -0
  89. package/examples/index.ts +7 -0
  90. package/examples/schemas/FavoriteItemSchema.ts +27 -0
  91. package/examples/{Preferences.yaml → schemas/Preferences.yaml} +2 -0
  92. package/examples/schemas/PreferencesSchema.ts +29 -0
  93. package/examples/schemas/ProfileSchema.ts +91 -0
  94. package/examples/schemas/Status.yaml +3 -0
  95. package/examples/schemas/StatusSchema.ts +12 -0
  96. package/jest.config.mjs +5 -0
  97. package/package.json +27 -20
  98. package/src/CredentialFactory.ts +392 -0
  99. package/src/Schema.ts +583 -0
  100. package/src/ValidationError.ts +90 -0
  101. package/src/Validator.ts +603 -0
  102. package/src/__tests__/CredentialFactory.test.ts +588 -0
  103. package/src/__tests__/Schema.test.ts +371 -0
  104. package/src/__tests__/ValidationError.test.ts +235 -0
  105. package/src/__tests__/Validator.test.ts +787 -0
  106. package/src/helpers/JsonSchema.ts +119 -0
  107. package/src/helpers/__tests__/cleanupAttributes.test.ts +943 -0
  108. package/src/helpers/__tests__/cleanupNulls.test.ts +772 -0
  109. package/src/helpers/__tests__/getReferenceIds.test.ts +975 -0
  110. package/src/helpers/__tests__/got.test.ts +193 -0
  111. package/src/helpers/__tests__/mapObjectProperties.test.ts +1126 -0
  112. package/src/helpers/__tests__/normalizeAttributes.test.ts +1435 -0
  113. package/src/helpers/__tests__/normalizeProperties.test.ts +727 -0
  114. package/src/helpers/__tests__/normalizeRequired.test.ts +669 -0
  115. package/src/helpers/__tests__/normalizeType.test.ts +772 -0
  116. package/src/helpers/__tests__/nullifyEmptyValues.test.ts +735 -0
  117. package/src/helpers/__tests__/removeRequiredAndDefault.test.ts +734 -0
  118. package/src/helpers/__tests__/validateId.test.ts +118 -0
  119. package/src/helpers/cleanupAttributes.ts +151 -0
  120. package/src/helpers/cleanupNulls.ts +106 -0
  121. package/src/helpers/getReferenceIds.ts +273 -0
  122. package/src/helpers/got.ts +73 -0
  123. package/src/helpers/mapObjectProperties.ts +272 -0
  124. package/src/helpers/normalizeAttributes.ts +247 -0
  125. package/src/helpers/normalizeProperties.ts +249 -0
  126. package/src/helpers/normalizeRequired.ts +233 -0
  127. package/src/helpers/normalizeType.ts +235 -0
  128. package/src/helpers/nullifyEmptyValues.ts +207 -0
  129. package/src/helpers/removeRequiredAndDefault.ts +151 -0
  130. package/src/helpers/validateId.ts +53 -0
  131. package/src/index.ts +13 -0
  132. package/src/ld/__tests__/documentLoader.test.ts +57 -0
  133. package/src/ld/__tests__/getLinkedDataAttributeType.test.ts +212 -0
  134. package/src/ld/__tests__/getLinkedDataContext.test.ts +378 -0
  135. package/src/ld/documentLoader.ts +28 -0
  136. package/src/ld/getLinkedDataAttributeType.ts +46 -0
  137. package/src/ld/getLinkedDataContext.ts +80 -0
  138. package/tsconfig.json +27 -0
  139. package/types/credentials-context.d.ts +14 -0
  140. package/types/security-context.d.ts +6 -0
  141. package/examples/Status.yaml +0 -3
  142. package/examples/createAccountCredential.js +0 -27
  143. package/examples/createMineSweeperScoreCredential.js +0 -63
  144. package/examples/index.js +0 -9
  145. package/src/CredentialFactory.js +0 -67
  146. package/src/CredentialFactory.spec.js +0 -131
  147. package/src/Schema.js +0 -104
  148. package/src/Schema.spec.js +0 -172
  149. package/src/ValidationError.js +0 -31
  150. package/src/Validator.js +0 -128
  151. package/src/Validator.spec.js +0 -355
  152. package/src/helpers/cleanupAttributes.js +0 -71
  153. package/src/helpers/cleanupNulls.js +0 -42
  154. package/src/helpers/getReferenceIds.js +0 -71
  155. package/src/helpers/mapObject.js +0 -65
  156. package/src/helpers/normalizeAttributes.js +0 -28
  157. package/src/helpers/normalizeProperties.js +0 -61
  158. package/src/helpers/normalizeRequired.js +0 -37
  159. package/src/helpers/normalizeType.js +0 -41
  160. package/src/helpers/nullifyEmptyValues.js +0 -57
  161. package/src/helpers/removeRequiredAndDefault.js +0 -30
  162. package/src/helpers/validateId.js +0 -19
  163. package/src/index.d.ts +0 -25
  164. package/src/index.js +0 -8
  165. package/src/ld/documentLoader.js +0 -25
  166. package/src/ld/documentLoader.spec.js +0 -12
  167. package/src/ld/getLinkedDataContext.js +0 -63
  168. package/src/ld/getLinkedDataType.js +0 -38
  169. /package/examples/{FavoriteItem.yaml → schemas/FavoriteItem.yaml} +0 -0
  170. /package/examples/{Profile.yaml → schemas/Profile.yaml} +0 -0
@@ -0,0 +1,1126 @@
1
+ import Schema from '../../Schema';
2
+ import mapObjectProperties from '../mapObjectProperties';
3
+ import type { JsonSchema } from '../JsonSchema';
4
+
5
+ describe('mapObjectProperties(object, jsonSchema, schemasMap, callback)', () => {
6
+ describe('enum schema', () => {
7
+ it('should not call callback for enum schema', () => {
8
+ const enumSchema = new Schema({ enum: ['value1', 'value2', 'value3'] }, 'enum-schema');
9
+ const object = { value: 'value1' };
10
+ const schemasMap = {};
11
+ const callback = jest.fn();
12
+
13
+ mapObjectProperties(object, enumSchema.jsonSchema, schemasMap, callback);
14
+
15
+ expect(callback).not.toHaveBeenCalled();
16
+ });
17
+ });
18
+
19
+ describe('empty object', () => {
20
+ it('should not call callback for empty object with no properties', () => {
21
+ const schema = new Schema({}, 'empty-schema');
22
+ const object = {};
23
+ const schemasMap = {};
24
+ const callback = jest.fn();
25
+
26
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
27
+
28
+ expect(callback).not.toHaveBeenCalled();
29
+ });
30
+ });
31
+
32
+ describe('simple properties', () => {
33
+ it('should call callback for each property in object', () => {
34
+ const schema = new Schema(
35
+ {
36
+ stringField: { type: 'string' },
37
+ numberField: { type: 'number' },
38
+ booleanField: { type: 'boolean' }
39
+ },
40
+ 'test-schema'
41
+ );
42
+ const object = {
43
+ stringField: 'test',
44
+ numberField: 42,
45
+ booleanField: true
46
+ };
47
+ const schemasMap = {};
48
+ const callback = jest.fn();
49
+
50
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
51
+
52
+ expect(callback).toHaveBeenCalledTimes(3);
53
+ expect(callback).toHaveBeenCalledWith('stringField', expect.objectContaining({ type: 'string' }), object);
54
+ expect(callback).toHaveBeenCalledWith('numberField', expect.objectContaining({ type: 'number' }), object);
55
+ expect(callback).toHaveBeenCalledWith('booleanField', expect.objectContaining({ type: 'boolean' }), object);
56
+ });
57
+
58
+ it('should call callback even when property value is null', () => {
59
+ const schema = new Schema(
60
+ {
61
+ nullField: { type: 'string' }
62
+ },
63
+ 'test-schema'
64
+ );
65
+ const object = {
66
+ nullField: null
67
+ };
68
+ const schemasMap = {};
69
+ const callback = jest.fn();
70
+
71
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
72
+
73
+ expect(callback).toHaveBeenCalledTimes(1);
74
+ expect(callback).toHaveBeenCalledWith('nullField', expect.any(Object), object);
75
+ });
76
+
77
+ it('should skip undefined values and not recurse', () => {
78
+ const schema = new Schema(
79
+ {
80
+ definedField: { type: 'string' },
81
+ undefinedField: { type: 'string' }
82
+ },
83
+ 'test-schema'
84
+ );
85
+ const object = {
86
+ definedField: 'value',
87
+ undefinedField: undefined
88
+ };
89
+ const schemasMap = {};
90
+ const callback = jest.fn();
91
+
92
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
93
+
94
+ expect(callback).toHaveBeenCalledTimes(2);
95
+ expect(callback).toHaveBeenCalledWith('definedField', expect.any(Object), object);
96
+ expect(callback).toHaveBeenCalledWith('undefinedField', expect.any(Object), object);
97
+ });
98
+ });
99
+
100
+ describe('reference properties ($ref)', () => {
101
+ it('should call callback for reference property and recurse into referenced schema', () => {
102
+ const schema = new Schema(
103
+ {
104
+ refField: { $ref: 'referenced-schema' }
105
+ },
106
+ 'test-schema'
107
+ );
108
+ const referencedSchema = new Schema(
109
+ {
110
+ nestedField: { type: 'string' }
111
+ },
112
+ 'referenced-schema'
113
+ );
114
+ const object = {
115
+ refField: {
116
+ nestedField: 'nested-value'
117
+ }
118
+ };
119
+ const schemasMap = {
120
+ 'referenced-schema': referencedSchema.jsonSchema
121
+ };
122
+ const callback = jest.fn();
123
+
124
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
125
+
126
+ expect(callback).toHaveBeenCalledTimes(2);
127
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'referenced-schema' }), object);
128
+ expect(callback).toHaveBeenCalledWith('nestedField', expect.objectContaining({ type: 'string' }), object.refField);
129
+ });
130
+
131
+ it('should handle nested references recursively', () => {
132
+ const schema = new Schema(
133
+ {
134
+ refField: { $ref: 'level1-schema' }
135
+ },
136
+ 'test-schema'
137
+ );
138
+ const level1Schema = new Schema(
139
+ {
140
+ nestedRef: { $ref: 'level2-schema' }
141
+ },
142
+ 'level1-schema'
143
+ );
144
+ const level2Schema = new Schema(
145
+ {
146
+ deepField: { type: 'string' }
147
+ },
148
+ 'level2-schema'
149
+ );
150
+ const object = {
151
+ refField: {
152
+ nestedRef: {
153
+ deepField: 'deep-value'
154
+ }
155
+ }
156
+ };
157
+ const schemasMap = {
158
+ 'level1-schema': level1Schema.jsonSchema,
159
+ 'level2-schema': level2Schema.jsonSchema
160
+ };
161
+ const callback = jest.fn();
162
+
163
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
164
+
165
+ expect(callback).toHaveBeenCalledTimes(3);
166
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'level1-schema' }), object);
167
+ expect(callback).toHaveBeenCalledWith('nestedRef', expect.objectContaining({ $ref: 'level2-schema' }), object.refField);
168
+ expect(callback).toHaveBeenCalledWith('deepField', expect.objectContaining({ type: 'string' }), object.refField.nestedRef);
169
+ });
170
+
171
+ it('should call callback but skip recursion when reference value is undefined', () => {
172
+ const schema = new Schema(
173
+ {
174
+ refField: { $ref: 'referenced-schema' }
175
+ },
176
+ 'test-schema'
177
+ );
178
+ const referencedSchema = new Schema(
179
+ {
180
+ nestedField: { type: 'string' }
181
+ },
182
+ 'referenced-schema'
183
+ );
184
+ const object = {
185
+ refField: undefined
186
+ };
187
+ const schemasMap = {
188
+ 'referenced-schema': referencedSchema.jsonSchema
189
+ };
190
+ const callback = jest.fn();
191
+
192
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
193
+
194
+ expect(callback).toHaveBeenCalledTimes(1);
195
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'referenced-schema' }), object);
196
+ });
197
+
198
+ it('should call callback but skip recursion when reference value is null', () => {
199
+ const schema = new Schema(
200
+ {
201
+ refField: { $ref: 'referenced-schema' }
202
+ },
203
+ 'test-schema'
204
+ );
205
+ const referencedSchema = new Schema(
206
+ {
207
+ nestedField: { type: 'string' }
208
+ },
209
+ 'referenced-schema'
210
+ );
211
+ const object = {
212
+ refField: null
213
+ };
214
+ const schemasMap = {
215
+ 'referenced-schema': referencedSchema.jsonSchema
216
+ };
217
+ const callback = jest.fn();
218
+
219
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
220
+
221
+ expect(callback).toHaveBeenCalledTimes(1);
222
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'referenced-schema' }), object);
223
+ });
224
+
225
+ it('should call callback but skip recursion when reference value is a primitive', () => {
226
+ const schema = new Schema(
227
+ {
228
+ refField: { $ref: 'referenced-schema' }
229
+ },
230
+ 'test-schema'
231
+ );
232
+ const referencedSchema = new Schema(
233
+ {
234
+ nestedField: { type: 'string' }
235
+ },
236
+ 'referenced-schema'
237
+ );
238
+ const object = {
239
+ refField: 'primitive-value'
240
+ };
241
+ const schemasMap = {
242
+ 'referenced-schema': referencedSchema.jsonSchema
243
+ };
244
+ const callback = jest.fn();
245
+
246
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
247
+
248
+ expect(callback).toHaveBeenCalledTimes(1);
249
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'referenced-schema' }), object);
250
+ });
251
+
252
+ it('should call callback but skip recursion when reference value is an array', () => {
253
+ const schema = new Schema(
254
+ {
255
+ refField: { $ref: 'referenced-schema' }
256
+ },
257
+ 'test-schema'
258
+ );
259
+ const referencedSchema = new Schema(
260
+ {
261
+ nestedField: { type: 'string' }
262
+ },
263
+ 'referenced-schema'
264
+ );
265
+ const object = {
266
+ refField: ['item1', 'item2']
267
+ };
268
+ const schemasMap = {
269
+ 'referenced-schema': referencedSchema.jsonSchema
270
+ };
271
+ const callback = jest.fn();
272
+
273
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
274
+
275
+ expect(callback).toHaveBeenCalledTimes(1);
276
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'referenced-schema' }), object);
277
+ });
278
+
279
+ it('should throw error when referenced schema is not found in schemasMap', () => {
280
+ const schema = new Schema(
281
+ {
282
+ refField: { $ref: 'non-existent-schema' }
283
+ },
284
+ 'test-schema'
285
+ );
286
+ const object = {
287
+ refField: {
288
+ nestedField: 'value'
289
+ }
290
+ };
291
+ const schemasMap = {};
292
+ const callback = jest.fn();
293
+
294
+ expect(() => {
295
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
296
+ }).toThrow('Schema "non-existent-schema" not found');
297
+ });
298
+ });
299
+
300
+ describe('nested object properties', () => {
301
+ it('should call callback for nested object property and recurse into nested object', () => {
302
+ const schema = new Schema(
303
+ {
304
+ nestedObject: {
305
+ type: 'object',
306
+ properties: {
307
+ nestedField: { type: 'string' }
308
+ }
309
+ }
310
+ },
311
+ 'test-schema'
312
+ );
313
+ const object = {
314
+ nestedObject: {
315
+ nestedField: 'nested-value'
316
+ }
317
+ };
318
+ const schemasMap = {};
319
+ const callback = jest.fn();
320
+
321
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
322
+
323
+ expect(callback).toHaveBeenCalledTimes(2);
324
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
325
+ expect(callback).toHaveBeenCalledWith('nestedField', expect.objectContaining({ type: 'string' }), object.nestedObject);
326
+ });
327
+
328
+ it('should handle deeply nested object properties', () => {
329
+ const schema = new Schema(
330
+ {
331
+ level1: {
332
+ type: 'object',
333
+ properties: {
334
+ level2: {
335
+ type: 'object',
336
+ properties: {
337
+ deepField: { type: 'string' }
338
+ }
339
+ }
340
+ }
341
+ }
342
+ },
343
+ 'test-schema'
344
+ );
345
+ const object = {
346
+ level1: {
347
+ level2: {
348
+ deepField: 'deep-value'
349
+ }
350
+ }
351
+ };
352
+ const schemasMap = {};
353
+ const callback = jest.fn();
354
+
355
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
356
+
357
+ expect(callback).toHaveBeenCalledTimes(3);
358
+ expect(callback).toHaveBeenCalledWith('level1', expect.objectContaining({ type: 'object' }), object);
359
+ expect(callback).toHaveBeenCalledWith('level2', expect.objectContaining({ type: 'object' }), object.level1);
360
+ expect(callback).toHaveBeenCalledWith('deepField', expect.objectContaining({ type: 'string' }), object.level1.level2);
361
+ });
362
+
363
+ it('should call callback but skip recursion when nested object value is undefined', () => {
364
+ const schema = new Schema(
365
+ {
366
+ nestedObject: {
367
+ type: 'object',
368
+ properties: {
369
+ nestedField: { type: 'string' }
370
+ }
371
+ }
372
+ },
373
+ 'test-schema'
374
+ );
375
+ const object = {
376
+ nestedObject: undefined
377
+ };
378
+ const schemasMap = {};
379
+ const callback = jest.fn();
380
+
381
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
382
+
383
+ expect(callback).toHaveBeenCalledTimes(1);
384
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
385
+ });
386
+
387
+ it('should call callback but skip recursion when nested object value is null', () => {
388
+ const schema = new Schema(
389
+ {
390
+ nestedObject: {
391
+ type: 'object',
392
+ properties: {
393
+ nestedField: { type: 'string' }
394
+ }
395
+ }
396
+ },
397
+ 'test-schema'
398
+ );
399
+ const object = {
400
+ nestedObject: null
401
+ };
402
+ const schemasMap = {};
403
+ const callback = jest.fn();
404
+
405
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
406
+
407
+ expect(callback).toHaveBeenCalledTimes(1);
408
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
409
+ });
410
+
411
+ it('should call callback but skip recursion when nested object value is a primitive', () => {
412
+ const schema = new Schema(
413
+ {
414
+ nestedObject: {
415
+ type: 'object',
416
+ properties: {
417
+ nestedField: { type: 'string' }
418
+ }
419
+ }
420
+ },
421
+ 'test-schema'
422
+ );
423
+ const object = {
424
+ nestedObject: 'primitive-value'
425
+ };
426
+ const schemasMap = {};
427
+ const callback = jest.fn();
428
+
429
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
430
+
431
+ expect(callback).toHaveBeenCalledTimes(1);
432
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
433
+ });
434
+
435
+ it('should call callback but skip recursion when nested object value is an array', () => {
436
+ const schema = new Schema(
437
+ {
438
+ nestedObject: {
439
+ type: 'object',
440
+ properties: {
441
+ nestedField: { type: 'string' }
442
+ }
443
+ }
444
+ },
445
+ 'test-schema'
446
+ );
447
+ const object = {
448
+ nestedObject: ['item1', 'item2']
449
+ };
450
+ const schemasMap = {};
451
+ const callback = jest.fn();
452
+
453
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
454
+
455
+ expect(callback).toHaveBeenCalledTimes(1);
456
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
457
+ });
458
+
459
+ it('should handle nested object with no properties', () => {
460
+ const schema = new Schema(
461
+ {
462
+ nestedObject: {
463
+ type: 'object',
464
+ properties: {}
465
+ }
466
+ },
467
+ 'test-schema'
468
+ );
469
+ const object = {
470
+ nestedObject: {}
471
+ };
472
+ const schemasMap = {};
473
+ const callback = jest.fn();
474
+
475
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
476
+
477
+ expect(callback).toHaveBeenCalledTimes(1);
478
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
479
+ });
480
+
481
+ it('should handle object type with undefined properties (tests destructuring default)', () => {
482
+ // Create a schema object manually without normalization to test the default destructuring
483
+ const jsonSchema = {
484
+ id: 'test-schema',
485
+ properties: {
486
+ nestedObject: {
487
+ type: 'object' as const,
488
+ // properties is intentionally undefined to test the default = {} on line 62
489
+ }
490
+ }
491
+ };
492
+ const object = {
493
+ nestedObject: {
494
+ someField: 'value'
495
+ }
496
+ };
497
+ const schemasMap = {};
498
+ const callback = jest.fn();
499
+
500
+ mapObjectProperties(object, jsonSchema, schemasMap, callback);
501
+
502
+ expect(callback).toHaveBeenCalledTimes(1);
503
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
504
+ });
505
+ });
506
+
507
+ describe('array properties', () => {
508
+ it('should call callback for array property and recurse into each array item with reference schema', () => {
509
+ const schema = new Schema(
510
+ {
511
+ arrayField: {
512
+ type: 'array',
513
+ items: { $ref: 'item-schema' }
514
+ }
515
+ },
516
+ 'test-schema'
517
+ );
518
+ const itemSchema = new Schema(
519
+ {
520
+ itemField: { type: 'string' }
521
+ },
522
+ 'item-schema'
523
+ );
524
+ const object = {
525
+ arrayField: [
526
+ { itemField: 'value1' },
527
+ { itemField: 'value2' }
528
+ ]
529
+ };
530
+ const schemasMap = {
531
+ 'item-schema': itemSchema.jsonSchema
532
+ };
533
+ const callback = jest.fn();
534
+
535
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
536
+
537
+ expect(callback).toHaveBeenCalledTimes(3);
538
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
539
+ expect(callback).toHaveBeenCalledWith('itemField', expect.objectContaining({ type: 'string' }), object.arrayField[0]);
540
+ expect(callback).toHaveBeenCalledWith('itemField', expect.objectContaining({ type: 'string' }), object.arrayField[1]);
541
+ });
542
+
543
+ it('should call callback for array property and recurse into each array item with object schema', () => {
544
+ const schema = new Schema(
545
+ {
546
+ arrayField: {
547
+ type: 'array',
548
+ items: {
549
+ type: 'object',
550
+ properties: {
551
+ itemField: { type: 'string' }
552
+ }
553
+ }
554
+ }
555
+ },
556
+ 'test-schema'
557
+ );
558
+ const object = {
559
+ arrayField: [
560
+ { itemField: 'value1' },
561
+ { itemField: 'value2' }
562
+ ]
563
+ };
564
+ const schemasMap = {};
565
+ const callback = jest.fn();
566
+
567
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
568
+
569
+ expect(callback).toHaveBeenCalledTimes(3);
570
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
571
+ expect(callback).toHaveBeenCalledWith('itemField', expect.objectContaining({ type: 'string' }), object.arrayField[0]);
572
+ expect(callback).toHaveBeenCalledWith('itemField', expect.objectContaining({ type: 'string' }), object.arrayField[1]);
573
+ });
574
+
575
+ it('should handle empty array', () => {
576
+ const schema = new Schema(
577
+ {
578
+ arrayField: {
579
+ type: 'array',
580
+ items: { $ref: 'item-schema' }
581
+ }
582
+ },
583
+ 'test-schema'
584
+ );
585
+ const itemSchema = new Schema(
586
+ {
587
+ itemField: { type: 'string' }
588
+ },
589
+ 'item-schema'
590
+ );
591
+ const object = {
592
+ arrayField: []
593
+ };
594
+ const schemasMap = {
595
+ 'item-schema': itemSchema.jsonSchema
596
+ };
597
+ const callback = jest.fn();
598
+
599
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
600
+
601
+ expect(callback).toHaveBeenCalledTimes(1);
602
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
603
+ });
604
+
605
+ it('should call callback but skip recursion when array value is undefined', () => {
606
+ const schema = new Schema(
607
+ {
608
+ arrayField: {
609
+ type: 'array',
610
+ items: { $ref: 'item-schema' }
611
+ }
612
+ },
613
+ 'test-schema'
614
+ );
615
+ const itemSchema = new Schema(
616
+ {
617
+ itemField: { type: 'string' }
618
+ },
619
+ 'item-schema'
620
+ );
621
+ const object = {
622
+ arrayField: undefined
623
+ };
624
+ const schemasMap = {
625
+ 'item-schema': itemSchema.jsonSchema
626
+ };
627
+ const callback = jest.fn();
628
+
629
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
630
+
631
+ expect(callback).toHaveBeenCalledTimes(1);
632
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
633
+ });
634
+
635
+ it('should call callback but skip recursion when array value is null', () => {
636
+ const schema = new Schema(
637
+ {
638
+ arrayField: {
639
+ type: 'array',
640
+ items: { $ref: 'item-schema' }
641
+ }
642
+ },
643
+ 'test-schema'
644
+ );
645
+ const itemSchema = new Schema(
646
+ {
647
+ itemField: { type: 'string' }
648
+ },
649
+ 'item-schema'
650
+ );
651
+ const object = {
652
+ arrayField: null
653
+ };
654
+ const schemasMap = {
655
+ 'item-schema': itemSchema.jsonSchema
656
+ };
657
+ const callback = jest.fn();
658
+
659
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
660
+
661
+ expect(callback).toHaveBeenCalledTimes(1);
662
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
663
+ });
664
+
665
+ it('should call callback but skip recursion when array property has undefined items schema', () => {
666
+ const schema = new Schema(
667
+ {
668
+ arrayField: {
669
+ type: 'array'
670
+ // items is intentionally undefined
671
+ }
672
+ },
673
+ 'test-schema'
674
+ );
675
+ const object = {
676
+ arrayField: [
677
+ { itemField: 'value1' },
678
+ { itemField: 'value2' }
679
+ ]
680
+ };
681
+ const schemasMap = {};
682
+ const callback = jest.fn();
683
+
684
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
685
+
686
+ expect(callback).toHaveBeenCalledTimes(1);
687
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
688
+ });
689
+
690
+ it('should call callback but skip recursion for array items that are null', () => {
691
+ const schema = new Schema(
692
+ {
693
+ arrayField: {
694
+ type: 'array',
695
+ items: { $ref: 'item-schema' }
696
+ }
697
+ },
698
+ 'test-schema'
699
+ );
700
+ const itemSchema = new Schema(
701
+ {
702
+ itemField: { type: 'string' }
703
+ },
704
+ 'item-schema'
705
+ );
706
+ const object = {
707
+ arrayField: [
708
+ null,
709
+ { itemField: 'value2' },
710
+ null
711
+ ]
712
+ };
713
+ const schemasMap = {
714
+ 'item-schema': itemSchema.jsonSchema
715
+ };
716
+ const callback = jest.fn();
717
+
718
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
719
+
720
+ expect(callback).toHaveBeenCalledTimes(2);
721
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
722
+ expect(callback).toHaveBeenCalledWith('itemField', expect.objectContaining({ type: 'string' }), object.arrayField[1]);
723
+ });
724
+
725
+ it('should call callback but skip recursion for array items that are primitives', () => {
726
+ const schema = new Schema(
727
+ {
728
+ arrayField: {
729
+ type: 'array',
730
+ items: { $ref: 'item-schema' }
731
+ }
732
+ },
733
+ 'test-schema'
734
+ );
735
+ const itemSchema = new Schema(
736
+ {
737
+ itemField: { type: 'string' }
738
+ },
739
+ 'item-schema'
740
+ );
741
+ const object = {
742
+ arrayField: [
743
+ 'primitive1',
744
+ { itemField: 'value2' },
745
+ 'primitive3'
746
+ ]
747
+ };
748
+ const schemasMap = {
749
+ 'item-schema': itemSchema.jsonSchema
750
+ };
751
+ const callback = jest.fn();
752
+
753
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
754
+
755
+ expect(callback).toHaveBeenCalledTimes(2);
756
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
757
+ expect(callback).toHaveBeenCalledWith('itemField', expect.objectContaining({ type: 'string' }), object.arrayField[1]);
758
+ });
759
+
760
+ it('should call callback but skip recursion for array items that are arrays', () => {
761
+ const schema = new Schema(
762
+ {
763
+ arrayField: {
764
+ type: 'array',
765
+ items: { $ref: 'item-schema' }
766
+ }
767
+ },
768
+ 'test-schema'
769
+ );
770
+ const itemSchema = new Schema(
771
+ {
772
+ itemField: { type: 'string' }
773
+ },
774
+ 'item-schema'
775
+ );
776
+ const object = {
777
+ arrayField: [
778
+ ['nested', 'array'],
779
+ { itemField: 'value2' },
780
+ ['another', 'array']
781
+ ]
782
+ };
783
+ const schemasMap = {
784
+ 'item-schema': itemSchema.jsonSchema
785
+ };
786
+ const callback = jest.fn();
787
+
788
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
789
+
790
+ expect(callback).toHaveBeenCalledTimes(2);
791
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
792
+ expect(callback).toHaveBeenCalledWith('itemField', expect.objectContaining({ type: 'string' }), object.arrayField[1]);
793
+ });
794
+
795
+ it('should handle nested references in array items', () => {
796
+ const schema = new Schema(
797
+ {
798
+ arrayField: {
799
+ type: 'array',
800
+ items: { $ref: 'item-schema' }
801
+ }
802
+ },
803
+ 'test-schema'
804
+ );
805
+ const itemSchema = new Schema(
806
+ {
807
+ refField: { $ref: 'nested-item-schema' }
808
+ },
809
+ 'item-schema'
810
+ );
811
+ const nestedItemSchema = new Schema(
812
+ {
813
+ nestedField: { type: 'string' }
814
+ },
815
+ 'nested-item-schema'
816
+ );
817
+ const object = {
818
+ arrayField: [
819
+ { refField: { nestedField: 'value1' } },
820
+ { refField: { nestedField: 'value2' } }
821
+ ]
822
+ };
823
+ const schemasMap = {
824
+ 'item-schema': itemSchema.jsonSchema,
825
+ 'nested-item-schema': nestedItemSchema.jsonSchema
826
+ };
827
+ const callback = jest.fn();
828
+
829
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
830
+
831
+ expect(callback).toHaveBeenCalledTimes(5);
832
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
833
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'nested-item-schema' }), object.arrayField[0]);
834
+ expect(callback).toHaveBeenCalledWith('nestedField', expect.objectContaining({ type: 'string' }), object.arrayField[0].refField);
835
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'nested-item-schema' }), object.arrayField[1]);
836
+ expect(callback).toHaveBeenCalledWith('nestedField', expect.objectContaining({ type: 'string' }), object.arrayField[1].refField);
837
+ });
838
+ });
839
+
840
+ describe('complex nested scenarios', () => {
841
+ it('should handle mix of reference, object, and array properties', () => {
842
+ const schema = new Schema(
843
+ {
844
+ refField: { $ref: 'ref-schema' },
845
+ nestedObject: {
846
+ type: 'object',
847
+ properties: {
848
+ nestedField: { type: 'string' }
849
+ }
850
+ },
851
+ arrayField: {
852
+ type: 'array',
853
+ items: { $ref: 'array-item-schema' }
854
+ }
855
+ },
856
+ 'test-schema'
857
+ );
858
+ const refSchema = new Schema(
859
+ {
860
+ refFieldProperty: { type: 'string' }
861
+ },
862
+ 'ref-schema'
863
+ );
864
+ const arrayItemSchema = new Schema(
865
+ {
866
+ itemField: { type: 'string' }
867
+ },
868
+ 'array-item-schema'
869
+ );
870
+ const object = {
871
+ refField: {
872
+ refFieldProperty: 'ref-value'
873
+ },
874
+ nestedObject: {
875
+ nestedField: 'nested-value'
876
+ },
877
+ arrayField: [
878
+ { itemField: 'item1' },
879
+ { itemField: 'item2' }
880
+ ]
881
+ };
882
+ const schemasMap = {
883
+ 'ref-schema': refSchema.jsonSchema,
884
+ 'array-item-schema': arrayItemSchema.jsonSchema
885
+ };
886
+ const callback = jest.fn();
887
+
888
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
889
+
890
+ expect(callback).toHaveBeenCalledTimes(7);
891
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'ref-schema' }), object);
892
+ expect(callback).toHaveBeenCalledWith('refFieldProperty', expect.any(Object), object.refField);
893
+ expect(callback).toHaveBeenCalledWith('nestedObject', expect.objectContaining({ type: 'object' }), object);
894
+ expect(callback).toHaveBeenCalledWith('nestedField', expect.any(Object), object.nestedObject);
895
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
896
+ expect(callback).toHaveBeenCalledWith('itemField', expect.any(Object), object.arrayField[0]);
897
+ expect(callback).toHaveBeenCalledWith('itemField', expect.any(Object), object.arrayField[1]);
898
+ });
899
+
900
+ it('should handle array of objects with nested references', () => {
901
+ const schema = new Schema(
902
+ {
903
+ arrayField: {
904
+ type: 'array',
905
+ items: {
906
+ type: 'object',
907
+ properties: {
908
+ refField: { $ref: 'array-nested-ref-schema' }
909
+ }
910
+ }
911
+ }
912
+ },
913
+ 'test-schema'
914
+ );
915
+ const arrayNestedRefSchema = new Schema(
916
+ {
917
+ nestedRef: { $ref: 'deep-nested-schema' }
918
+ },
919
+ 'array-nested-ref-schema'
920
+ );
921
+ const deepNestedSchema = new Schema(
922
+ {
923
+ deepField: { type: 'string' }
924
+ },
925
+ 'deep-nested-schema'
926
+ );
927
+ const object = {
928
+ arrayField: [
929
+ {
930
+ refField: {
931
+ nestedRef: {
932
+ deepField: 'deep-value1'
933
+ }
934
+ }
935
+ },
936
+ {
937
+ refField: {
938
+ nestedRef: {
939
+ deepField: 'deep-value2'
940
+ }
941
+ }
942
+ }
943
+ ]
944
+ };
945
+ const schemasMap = {
946
+ 'array-nested-ref-schema': arrayNestedRefSchema.jsonSchema,
947
+ 'deep-nested-schema': deepNestedSchema.jsonSchema
948
+ };
949
+ const callback = jest.fn();
950
+
951
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
952
+
953
+ expect(callback).toHaveBeenCalledTimes(7);
954
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
955
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'array-nested-ref-schema' }), object.arrayField[0]);
956
+ expect(callback).toHaveBeenCalledWith('nestedRef', expect.objectContaining({ $ref: 'deep-nested-schema' }), object.arrayField[0].refField);
957
+ expect(callback).toHaveBeenCalledWith('deepField', expect.any(Object), object.arrayField[0].refField.nestedRef);
958
+ expect(callback).toHaveBeenCalledWith('refField', expect.objectContaining({ $ref: 'array-nested-ref-schema' }), object.arrayField[1]);
959
+ expect(callback).toHaveBeenCalledWith('nestedRef', expect.objectContaining({ $ref: 'deep-nested-schema' }), object.arrayField[1].refField);
960
+ expect(callback).toHaveBeenCalledWith('deepField', expect.any(Object), object.arrayField[1].refField.nestedRef);
961
+ });
962
+
963
+ it('should pass correct object context to callback at each level', () => {
964
+ const schema = new Schema(
965
+ {
966
+ topField: { type: 'string' },
967
+ nestedObject: {
968
+ type: 'object',
969
+ properties: {
970
+ nestedField: { type: 'string' }
971
+ }
972
+ }
973
+ },
974
+ 'test-schema'
975
+ );
976
+ const object = {
977
+ topField: 'top-value',
978
+ nestedObject: {
979
+ nestedField: 'nested-value'
980
+ }
981
+ };
982
+ const schemasMap = {};
983
+ const callback = jest.fn();
984
+
985
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
986
+
987
+ expect(callback).toHaveBeenCalledTimes(3);
988
+ expect(callback).toHaveBeenNthCalledWith(1, 'topField', expect.any(Object), object);
989
+ expect(callback).toHaveBeenNthCalledWith(2, 'nestedObject', expect.any(Object), object);
990
+ expect(callback).toHaveBeenNthCalledWith(3, 'nestedField', expect.any(Object), object.nestedObject);
991
+ });
992
+ });
993
+
994
+ describe('edge cases', () => {
995
+ it('should handle object with only undefined values', () => {
996
+ const schema = new Schema(
997
+ {
998
+ field1: { type: 'string' },
999
+ field2: { type: 'number' }
1000
+ },
1001
+ 'test-schema'
1002
+ );
1003
+ const object = {
1004
+ field1: undefined,
1005
+ field2: undefined
1006
+ };
1007
+ const schemasMap = {};
1008
+ const callback = jest.fn();
1009
+
1010
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
1011
+
1012
+ expect(callback).toHaveBeenCalledTimes(2);
1013
+ expect(callback).toHaveBeenCalledWith('field1', expect.any(Object), object);
1014
+ expect(callback).toHaveBeenCalledWith('field2', expect.any(Object), object);
1015
+ });
1016
+
1017
+ it('should handle object with only null values', () => {
1018
+ const schema = new Schema(
1019
+ {
1020
+ field1: { type: 'string' },
1021
+ field2: { type: 'number' }
1022
+ },
1023
+ 'test-schema'
1024
+ );
1025
+ const object = {
1026
+ field1: null,
1027
+ field2: null
1028
+ };
1029
+ const schemasMap = {};
1030
+ const callback = jest.fn();
1031
+
1032
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
1033
+
1034
+ expect(callback).toHaveBeenCalledTimes(2);
1035
+ expect(callback).toHaveBeenCalledWith('field1', expect.any(Object), object);
1036
+ expect(callback).toHaveBeenCalledWith('field2', expect.any(Object), object);
1037
+ });
1038
+
1039
+ it('should handle array with items that have no properties', () => {
1040
+ const schema = new Schema(
1041
+ {
1042
+ arrayField: {
1043
+ type: 'array',
1044
+ items: {
1045
+ type: 'object'
1046
+ }
1047
+ }
1048
+ },
1049
+ 'test-schema'
1050
+ );
1051
+ const object = {
1052
+ arrayField: [
1053
+ {},
1054
+ {}
1055
+ ]
1056
+ };
1057
+ const schemasMap = {};
1058
+ const callback = jest.fn();
1059
+
1060
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
1061
+
1062
+ expect(callback).toHaveBeenCalledTimes(1);
1063
+ expect(callback).toHaveBeenCalledWith('arrayField', expect.objectContaining({ type: 'array' }), object);
1064
+ });
1065
+
1066
+ it('should handle schema with undefined properties (malformed schema)', () => {
1067
+ const jsonSchema = {
1068
+ id: 'test-schema'
1069
+ // properties is intentionally undefined (malformed schema)
1070
+ } as unknown as JsonSchema;
1071
+ const object = {
1072
+ field1: 'value1',
1073
+ field2: 'value2'
1074
+ };
1075
+ const schemasMap = {};
1076
+ const callback = jest.fn();
1077
+
1078
+ mapObjectProperties(object, jsonSchema, schemasMap, callback);
1079
+
1080
+ expect(callback).not.toHaveBeenCalled();
1081
+ });
1082
+
1083
+ it('should handle callback that modifies the object', () => {
1084
+ const schema = new Schema(
1085
+ {
1086
+ field: { type: 'string' }
1087
+ },
1088
+ 'test-schema'
1089
+ );
1090
+ const object = {
1091
+ field: 'original'
1092
+ };
1093
+ const schemasMap = {};
1094
+ const callback = jest.fn((propertyName, propertySchema, obj) => {
1095
+ if (propertyName === 'field') {
1096
+ obj[propertyName] = 'modified';
1097
+ }
1098
+ });
1099
+
1100
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
1101
+
1102
+ expect(callback).toHaveBeenCalledTimes(1);
1103
+ expect(object.field).toBe('modified');
1104
+ });
1105
+
1106
+ it('should handle callback that throws an error', () => {
1107
+ const schema = new Schema(
1108
+ {
1109
+ field: { type: 'string' }
1110
+ },
1111
+ 'test-schema'
1112
+ );
1113
+ const object = {
1114
+ field: 'value'
1115
+ };
1116
+ const schemasMap = {};
1117
+ const callback = jest.fn(() => {
1118
+ throw new Error('Callback error');
1119
+ });
1120
+
1121
+ expect(() => {
1122
+ mapObjectProperties(object, schema.jsonSchema, schemasMap, callback);
1123
+ }).toThrow('Callback error');
1124
+ });
1125
+ });
1126
+ });