@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.
- package/README.md +19 -14
- package/dist/CredentialFactory.d.ts +345 -0
- package/dist/CredentialFactory.d.ts.map +1 -0
- package/dist/CredentialFactory.js +381 -0
- package/dist/CredentialFactory.js.map +1 -0
- package/dist/Schema.d.ts +448 -0
- package/dist/Schema.d.ts.map +1 -0
- package/dist/Schema.js +506 -0
- package/dist/Schema.js.map +1 -0
- package/dist/ValidationError.d.ts +70 -0
- package/dist/ValidationError.d.ts.map +1 -0
- package/dist/ValidationError.js +78 -0
- package/dist/ValidationError.js.map +1 -0
- package/dist/Validator.d.ts +483 -0
- package/dist/Validator.d.ts.map +1 -0
- package/dist/Validator.js +570 -0
- package/dist/Validator.js.map +1 -0
- package/dist/helpers/JsonSchema.d.ts +99 -0
- package/dist/helpers/JsonSchema.d.ts.map +1 -0
- package/dist/helpers/JsonSchema.js +3 -0
- package/dist/helpers/JsonSchema.js.map +1 -0
- package/dist/helpers/cleanupAttributes.d.ts +34 -0
- package/dist/helpers/cleanupAttributes.d.ts.map +1 -0
- package/dist/helpers/cleanupAttributes.js +113 -0
- package/dist/helpers/cleanupAttributes.js.map +1 -0
- package/dist/helpers/cleanupNulls.d.ts +27 -0
- package/dist/helpers/cleanupNulls.d.ts.map +1 -0
- package/dist/helpers/cleanupNulls.js +96 -0
- package/dist/helpers/cleanupNulls.js.map +1 -0
- package/dist/helpers/getReferenceIds.d.ts +169 -0
- package/dist/helpers/getReferenceIds.d.ts.map +1 -0
- package/dist/helpers/getReferenceIds.js +241 -0
- package/dist/helpers/getReferenceIds.js.map +1 -0
- package/dist/helpers/got.d.ts +60 -0
- package/dist/helpers/got.d.ts.map +1 -0
- package/dist/helpers/got.js +72 -0
- package/dist/helpers/got.js.map +1 -0
- package/dist/helpers/mapObjectProperties.d.ts +150 -0
- package/dist/helpers/mapObjectProperties.d.ts.map +1 -0
- package/dist/helpers/mapObjectProperties.js +229 -0
- package/dist/helpers/mapObjectProperties.js.map +1 -0
- package/dist/helpers/normalizeAttributes.d.ts +213 -0
- package/dist/helpers/normalizeAttributes.d.ts.map +1 -0
- package/dist/helpers/normalizeAttributes.js +243 -0
- package/dist/helpers/normalizeAttributes.js.map +1 -0
- package/dist/helpers/normalizeProperties.d.ts +168 -0
- package/dist/helpers/normalizeProperties.d.ts.map +1 -0
- package/dist/helpers/normalizeProperties.js +223 -0
- package/dist/helpers/normalizeProperties.js.map +1 -0
- package/dist/helpers/normalizeRequired.d.ts +159 -0
- package/dist/helpers/normalizeRequired.d.ts.map +1 -0
- package/dist/helpers/normalizeRequired.js +206 -0
- package/dist/helpers/normalizeRequired.js.map +1 -0
- package/dist/helpers/normalizeType.d.ts +81 -0
- package/dist/helpers/normalizeType.d.ts.map +1 -0
- package/dist/helpers/normalizeType.js +210 -0
- package/dist/helpers/normalizeType.js.map +1 -0
- package/dist/helpers/nullifyEmptyValues.d.ts +139 -0
- package/dist/helpers/nullifyEmptyValues.d.ts.map +1 -0
- package/dist/helpers/nullifyEmptyValues.js +191 -0
- package/dist/helpers/nullifyEmptyValues.js.map +1 -0
- package/dist/helpers/removeRequiredAndDefault.d.ts +106 -0
- package/dist/helpers/removeRequiredAndDefault.d.ts.map +1 -0
- package/dist/helpers/removeRequiredAndDefault.js +138 -0
- package/dist/helpers/removeRequiredAndDefault.js.map +1 -0
- package/dist/helpers/validateId.d.ts +39 -0
- package/dist/helpers/validateId.d.ts.map +1 -0
- package/dist/helpers/validateId.js +51 -0
- package/dist/helpers/validateId.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/ld/documentLoader.d.ts +8 -0
- package/dist/ld/documentLoader.d.ts.map +1 -0
- package/dist/ld/documentLoader.js +24 -0
- package/dist/ld/documentLoader.js.map +1 -0
- package/dist/ld/getLinkedDataAttributeType.d.ts +10 -0
- package/dist/ld/getLinkedDataAttributeType.d.ts.map +1 -0
- package/dist/ld/getLinkedDataAttributeType.js +32 -0
- package/dist/ld/getLinkedDataAttributeType.js.map +1 -0
- package/dist/ld/getLinkedDataContext.d.ts +19 -0
- package/dist/ld/getLinkedDataContext.d.ts.map +1 -0
- package/dist/ld/getLinkedDataContext.js +50 -0
- package/dist/ld/getLinkedDataContext.js.map +1 -0
- package/eslint.config.mjs +32 -52
- package/examples/credentials/createAccountCredential.ts +27 -0
- package/examples/credentials/createMineSweeperScoreCredential.ts +115 -0
- package/examples/index.ts +7 -0
- package/examples/schemas/FavoriteItemSchema.ts +27 -0
- package/examples/{Preferences.yaml → schemas/Preferences.yaml} +2 -0
- package/examples/schemas/PreferencesSchema.ts +29 -0
- package/examples/schemas/ProfileSchema.ts +91 -0
- package/examples/schemas/Status.yaml +3 -0
- package/examples/schemas/StatusSchema.ts +12 -0
- package/jest.config.mjs +5 -0
- package/package.json +27 -20
- package/src/CredentialFactory.ts +392 -0
- package/src/Schema.ts +583 -0
- package/src/ValidationError.ts +90 -0
- package/src/Validator.ts +603 -0
- package/src/__tests__/CredentialFactory.test.ts +588 -0
- package/src/__tests__/Schema.test.ts +371 -0
- package/src/__tests__/ValidationError.test.ts +235 -0
- package/src/__tests__/Validator.test.ts +787 -0
- package/src/helpers/JsonSchema.ts +119 -0
- package/src/helpers/__tests__/cleanupAttributes.test.ts +943 -0
- package/src/helpers/__tests__/cleanupNulls.test.ts +772 -0
- package/src/helpers/__tests__/getReferenceIds.test.ts +975 -0
- package/src/helpers/__tests__/got.test.ts +193 -0
- package/src/helpers/__tests__/mapObjectProperties.test.ts +1126 -0
- package/src/helpers/__tests__/normalizeAttributes.test.ts +1435 -0
- package/src/helpers/__tests__/normalizeProperties.test.ts +727 -0
- package/src/helpers/__tests__/normalizeRequired.test.ts +669 -0
- package/src/helpers/__tests__/normalizeType.test.ts +772 -0
- package/src/helpers/__tests__/nullifyEmptyValues.test.ts +735 -0
- package/src/helpers/__tests__/removeRequiredAndDefault.test.ts +734 -0
- package/src/helpers/__tests__/validateId.test.ts +118 -0
- package/src/helpers/cleanupAttributes.ts +151 -0
- package/src/helpers/cleanupNulls.ts +106 -0
- package/src/helpers/getReferenceIds.ts +273 -0
- package/src/helpers/got.ts +73 -0
- package/src/helpers/mapObjectProperties.ts +272 -0
- package/src/helpers/normalizeAttributes.ts +247 -0
- package/src/helpers/normalizeProperties.ts +249 -0
- package/src/helpers/normalizeRequired.ts +233 -0
- package/src/helpers/normalizeType.ts +235 -0
- package/src/helpers/nullifyEmptyValues.ts +207 -0
- package/src/helpers/removeRequiredAndDefault.ts +151 -0
- package/src/helpers/validateId.ts +53 -0
- package/src/index.ts +13 -0
- package/src/ld/__tests__/documentLoader.test.ts +57 -0
- package/src/ld/__tests__/getLinkedDataAttributeType.test.ts +212 -0
- package/src/ld/__tests__/getLinkedDataContext.test.ts +378 -0
- package/src/ld/documentLoader.ts +28 -0
- package/src/ld/getLinkedDataAttributeType.ts +46 -0
- package/src/ld/getLinkedDataContext.ts +80 -0
- package/tsconfig.json +27 -0
- package/types/credentials-context.d.ts +14 -0
- package/types/security-context.d.ts +6 -0
- package/examples/Status.yaml +0 -3
- package/examples/createAccountCredential.js +0 -27
- package/examples/createMineSweeperScoreCredential.js +0 -63
- package/examples/index.js +0 -9
- package/src/CredentialFactory.js +0 -67
- package/src/CredentialFactory.spec.js +0 -131
- package/src/Schema.js +0 -104
- package/src/Schema.spec.js +0 -172
- package/src/ValidationError.js +0 -31
- package/src/Validator.js +0 -128
- package/src/Validator.spec.js +0 -355
- package/src/helpers/cleanupAttributes.js +0 -71
- package/src/helpers/cleanupNulls.js +0 -42
- package/src/helpers/getReferenceIds.js +0 -71
- package/src/helpers/mapObject.js +0 -65
- package/src/helpers/normalizeAttributes.js +0 -28
- package/src/helpers/normalizeProperties.js +0 -61
- package/src/helpers/normalizeRequired.js +0 -37
- package/src/helpers/normalizeType.js +0 -41
- package/src/helpers/nullifyEmptyValues.js +0 -57
- package/src/helpers/removeRequiredAndDefault.js +0 -30
- package/src/helpers/validateId.js +0 -19
- package/src/index.d.ts +0 -25
- package/src/index.js +0 -8
- package/src/ld/documentLoader.js +0 -25
- package/src/ld/documentLoader.spec.js +0 -12
- package/src/ld/getLinkedDataContext.js +0 -63
- package/src/ld/getLinkedDataType.js +0 -38
- /package/examples/{FavoriteItem.yaml → schemas/FavoriteItem.yaml} +0 -0
- /package/examples/{Profile.yaml → schemas/Profile.yaml} +0 -0
|
@@ -0,0 +1,943 @@
|
|
|
1
|
+
import cleanupAttributes from '../cleanupAttributes';
|
|
2
|
+
import type { ObjectSchema } from '../JsonSchema';
|
|
3
|
+
|
|
4
|
+
describe('cleanupAttributes(object, jsonSchema, schemasMap)', () => {
|
|
5
|
+
describe('enum schema', () => {
|
|
6
|
+
it('should return early and not modify object when schema is an enum', () => {
|
|
7
|
+
const object = { field1: 'value1', field2: 'value2' };
|
|
8
|
+
const enumSchema = { enum: ['value1', 'value2', 'value3'] };
|
|
9
|
+
const schemasMap = {};
|
|
10
|
+
|
|
11
|
+
cleanupAttributes(object, enumSchema, schemasMap);
|
|
12
|
+
|
|
13
|
+
expect(object).toEqual({ field1: 'value1', field2: 'value2' });
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('object schema', () => {
|
|
18
|
+
it('should delete properties not defined in schema', () => {
|
|
19
|
+
const object = {
|
|
20
|
+
validField: 'value1',
|
|
21
|
+
invalidField: 'value2',
|
|
22
|
+
anotherInvalid: 'value3'
|
|
23
|
+
};
|
|
24
|
+
const schema: ObjectSchema = {
|
|
25
|
+
id: 'test-schema',
|
|
26
|
+
properties: {
|
|
27
|
+
validField: { type: 'string' }
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
cleanupAttributes(object, schema);
|
|
32
|
+
|
|
33
|
+
expect(object).toEqual({ validField: 'value1' });
|
|
34
|
+
expect(object).not.toHaveProperty('invalidField');
|
|
35
|
+
expect(object).not.toHaveProperty('anotherInvalid');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should keep all properties that are defined in schema', () => {
|
|
39
|
+
const object = {
|
|
40
|
+
field1: 'value1',
|
|
41
|
+
field2: 'value2',
|
|
42
|
+
field3: 'value3'
|
|
43
|
+
};
|
|
44
|
+
const schema: ObjectSchema = {
|
|
45
|
+
id: 'test-schema',
|
|
46
|
+
properties: {
|
|
47
|
+
field1: { type: 'string' },
|
|
48
|
+
field2: { type: 'string' },
|
|
49
|
+
field3: { type: 'string' }
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
cleanupAttributes(object, schema);
|
|
54
|
+
|
|
55
|
+
expect(object).toEqual({
|
|
56
|
+
field1: 'value1',
|
|
57
|
+
field2: 'value2',
|
|
58
|
+
field3: 'value3'
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should handle empty object', () => {
|
|
63
|
+
const object = {};
|
|
64
|
+
const schema: ObjectSchema = {
|
|
65
|
+
id: 'test-schema',
|
|
66
|
+
properties: {
|
|
67
|
+
field1: { type: 'string' }
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
cleanupAttributes(object, schema);
|
|
72
|
+
|
|
73
|
+
expect(object).toEqual({});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should handle object with no properties in schema', () => {
|
|
77
|
+
const object = {
|
|
78
|
+
field1: 'value1',
|
|
79
|
+
field2: 'value2'
|
|
80
|
+
};
|
|
81
|
+
const schema = {
|
|
82
|
+
id: 'test-schema',
|
|
83
|
+
properties: {}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
cleanupAttributes(object, schema);
|
|
87
|
+
|
|
88
|
+
expect(object).toEqual({});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('reference properties ($ref)', () => {
|
|
93
|
+
it('should recursively cleanup referenced schema properties', () => {
|
|
94
|
+
const object = {
|
|
95
|
+
refField: {
|
|
96
|
+
validField: 'value1',
|
|
97
|
+
invalidField: 'value2'
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const schema = {
|
|
101
|
+
id: 'test-schema',
|
|
102
|
+
properties: {
|
|
103
|
+
refField: { $ref: 'referenced-schema' }
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const referencedSchema: ObjectSchema = {
|
|
107
|
+
id: 'referenced-schema',
|
|
108
|
+
properties: {
|
|
109
|
+
validField: { type: 'string' }
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const schemasMap = {
|
|
113
|
+
'referenced-schema': referencedSchema
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
117
|
+
|
|
118
|
+
expect(object.refField).toEqual({ validField: 'value1' });
|
|
119
|
+
expect(object.refField).not.toHaveProperty('invalidField');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should handle nested references', () => {
|
|
123
|
+
const object = {
|
|
124
|
+
refField: {
|
|
125
|
+
nestedRef: {
|
|
126
|
+
validField: 'value1',
|
|
127
|
+
invalidField: 'value2'
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const schema = {
|
|
132
|
+
id: 'test-schema',
|
|
133
|
+
properties: {
|
|
134
|
+
refField: { $ref: 'level1-schema' }
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const level1Schema = {
|
|
138
|
+
id: 'level1-schema',
|
|
139
|
+
properties: {
|
|
140
|
+
nestedRef: { $ref: 'level2-schema' }
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const level2Schema: ObjectSchema = {
|
|
144
|
+
id: 'level2-schema',
|
|
145
|
+
properties: {
|
|
146
|
+
validField: { type: 'string' }
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const schemasMap = {
|
|
150
|
+
'level1-schema': level1Schema,
|
|
151
|
+
'level2-schema': level2Schema
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
155
|
+
|
|
156
|
+
expect(object.refField.nestedRef).toEqual({ validField: 'value1' });
|
|
157
|
+
expect(object.refField.nestedRef).not.toHaveProperty('invalidField');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should throw error when referenced schema is not found', () => {
|
|
161
|
+
const object = {
|
|
162
|
+
refField: {
|
|
163
|
+
field: 'value'
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const schema = {
|
|
167
|
+
id: 'test-schema',
|
|
168
|
+
properties: {
|
|
169
|
+
refField: { $ref: 'non-existent-schema' }
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
const schemasMap = {};
|
|
173
|
+
|
|
174
|
+
expect(() => {
|
|
175
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
176
|
+
}).toThrow('Schema "non-existent-schema" not found');
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should skip cleanup when reference property value is null', () => {
|
|
180
|
+
const object = {
|
|
181
|
+
refField: null
|
|
182
|
+
};
|
|
183
|
+
const schema = {
|
|
184
|
+
id: 'test-schema',
|
|
185
|
+
properties: {
|
|
186
|
+
refField: { $ref: 'referenced-schema' }
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
const referencedSchema: ObjectSchema = {
|
|
190
|
+
id: 'referenced-schema',
|
|
191
|
+
properties: {
|
|
192
|
+
validField: { type: 'string' }
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const schemasMap = {
|
|
196
|
+
'referenced-schema': referencedSchema
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
200
|
+
|
|
201
|
+
expect(object.refField).toBeNull();
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('should skip cleanup when reference property value is undefined', () => {
|
|
205
|
+
const object = {
|
|
206
|
+
refField: undefined
|
|
207
|
+
};
|
|
208
|
+
const schema = {
|
|
209
|
+
id: 'test-schema',
|
|
210
|
+
properties: {
|
|
211
|
+
refField: { $ref: 'referenced-schema' }
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const referencedSchema: ObjectSchema = {
|
|
215
|
+
id: 'referenced-schema',
|
|
216
|
+
properties: {
|
|
217
|
+
validField: { type: 'string' }
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
const schemasMap = {
|
|
221
|
+
'referenced-schema': referencedSchema
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
225
|
+
|
|
226
|
+
expect(object.refField).toBeUndefined();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should skip cleanup when reference property value is a primitive', () => {
|
|
230
|
+
const object = {
|
|
231
|
+
refField: 'string-value'
|
|
232
|
+
};
|
|
233
|
+
const schema = {
|
|
234
|
+
id: 'test-schema',
|
|
235
|
+
properties: {
|
|
236
|
+
refField: { $ref: 'referenced-schema' }
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const referencedSchema: ObjectSchema = {
|
|
240
|
+
id: 'referenced-schema',
|
|
241
|
+
properties: {
|
|
242
|
+
validField: { type: 'string' }
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
const schemasMap = {
|
|
246
|
+
'referenced-schema': referencedSchema
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
250
|
+
|
|
251
|
+
expect(object.refField).toBe('string-value');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should skip cleanup when reference property value is an array', () => {
|
|
255
|
+
const object = {
|
|
256
|
+
refField: ['item1', 'item2']
|
|
257
|
+
};
|
|
258
|
+
const schema = {
|
|
259
|
+
id: 'test-schema',
|
|
260
|
+
properties: {
|
|
261
|
+
refField: { $ref: 'referenced-schema' }
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
const referencedSchema: ObjectSchema = {
|
|
265
|
+
id: 'referenced-schema',
|
|
266
|
+
properties: {
|
|
267
|
+
validField: { type: 'string' }
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
const schemasMap = {
|
|
271
|
+
'referenced-schema': referencedSchema
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
275
|
+
|
|
276
|
+
expect(object.refField).toEqual(['item1', 'item2']);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
describe('object properties', () => {
|
|
281
|
+
it('should recursively cleanup nested object properties', () => {
|
|
282
|
+
const object = {
|
|
283
|
+
nestedObject: {
|
|
284
|
+
validField: 'value1',
|
|
285
|
+
invalidField: 'value2'
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
const schema = {
|
|
289
|
+
id: 'test-schema',
|
|
290
|
+
properties: {
|
|
291
|
+
nestedObject: {
|
|
292
|
+
type: 'object' as const,
|
|
293
|
+
properties: {
|
|
294
|
+
validField: { type: 'string' }
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
} as ObjectSchema;
|
|
299
|
+
const schemasMap = {};
|
|
300
|
+
|
|
301
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
302
|
+
|
|
303
|
+
expect(object.nestedObject).toEqual({ validField: 'value1' });
|
|
304
|
+
expect(object.nestedObject).not.toHaveProperty('invalidField');
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should handle deeply nested objects', () => {
|
|
308
|
+
const object = {
|
|
309
|
+
level1: {
|
|
310
|
+
level2: {
|
|
311
|
+
level3: {
|
|
312
|
+
validField: 'value1',
|
|
313
|
+
invalidField: 'value2'
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
const schema = {
|
|
319
|
+
id: 'test-schema',
|
|
320
|
+
properties: {
|
|
321
|
+
level1: {
|
|
322
|
+
type: 'object' as const,
|
|
323
|
+
properties: {
|
|
324
|
+
level2: {
|
|
325
|
+
type: 'object' as const,
|
|
326
|
+
properties: {
|
|
327
|
+
level3: {
|
|
328
|
+
type: 'object' as const,
|
|
329
|
+
properties: {
|
|
330
|
+
validField: { type: 'string' }
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
} as ObjectSchema;
|
|
339
|
+
const schemasMap = {};
|
|
340
|
+
|
|
341
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
342
|
+
|
|
343
|
+
expect(object.level1.level2.level3).toEqual({ validField: 'value1' });
|
|
344
|
+
expect(object.level1.level2.level3).not.toHaveProperty('invalidField');
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should handle object type with undefined properties (tests destructuring default)', () => {
|
|
348
|
+
// Create a manually constructed schema with undefined properties to test the default destructuring
|
|
349
|
+
const object = {
|
|
350
|
+
nestedObject: {
|
|
351
|
+
someField: 'value'
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
const schema = {
|
|
355
|
+
id: 'test-schema',
|
|
356
|
+
properties: {
|
|
357
|
+
nestedObject: {
|
|
358
|
+
type: 'object' as const,
|
|
359
|
+
// properties is intentionally undefined to test the default = {} on line 58
|
|
360
|
+
properties: undefined
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} as ObjectSchema;
|
|
364
|
+
const schemasMap = {};
|
|
365
|
+
|
|
366
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
367
|
+
|
|
368
|
+
// Should handle undefined properties by using default {}
|
|
369
|
+
expect(object.nestedObject).toEqual({});
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('should skip cleanup when object property value is null', () => {
|
|
373
|
+
const object = {
|
|
374
|
+
nestedObject: null
|
|
375
|
+
};
|
|
376
|
+
const schema = {
|
|
377
|
+
id: 'test-schema',
|
|
378
|
+
properties: {
|
|
379
|
+
nestedObject: {
|
|
380
|
+
type: 'object' as const,
|
|
381
|
+
properties: {
|
|
382
|
+
validField: { type: 'string' }
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
} as ObjectSchema;
|
|
387
|
+
const schemasMap = {};
|
|
388
|
+
|
|
389
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
390
|
+
|
|
391
|
+
expect(object.nestedObject).toBeNull();
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('should skip cleanup when object property value is undefined', () => {
|
|
395
|
+
const object = {
|
|
396
|
+
nestedObject: undefined
|
|
397
|
+
};
|
|
398
|
+
const schema = {
|
|
399
|
+
id: 'test-schema',
|
|
400
|
+
properties: {
|
|
401
|
+
nestedObject: {
|
|
402
|
+
type: 'object' as const,
|
|
403
|
+
properties: {
|
|
404
|
+
validField: { type: 'string' }
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
} as ObjectSchema;
|
|
409
|
+
const schemasMap = {};
|
|
410
|
+
|
|
411
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
412
|
+
|
|
413
|
+
expect(object.nestedObject).toBeUndefined();
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('should skip cleanup when object property value is a primitive', () => {
|
|
417
|
+
const object = {
|
|
418
|
+
nestedObject: 'string-value'
|
|
419
|
+
};
|
|
420
|
+
const schema = {
|
|
421
|
+
id: 'test-schema',
|
|
422
|
+
properties: {
|
|
423
|
+
nestedObject: {
|
|
424
|
+
type: 'object' as const,
|
|
425
|
+
properties: {
|
|
426
|
+
validField: { type: 'string' }
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
} as ObjectSchema;
|
|
431
|
+
const schemasMap = {};
|
|
432
|
+
|
|
433
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
434
|
+
|
|
435
|
+
expect(object.nestedObject).toBe('string-value');
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('should skip cleanup when object property value is an array', () => {
|
|
439
|
+
const object = {
|
|
440
|
+
nestedObject: ['item1', 'item2']
|
|
441
|
+
};
|
|
442
|
+
const schema = {
|
|
443
|
+
id: 'test-schema',
|
|
444
|
+
properties: {
|
|
445
|
+
nestedObject: {
|
|
446
|
+
type: 'object' as const,
|
|
447
|
+
properties: {
|
|
448
|
+
validField: { type: 'string' }
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
} as ObjectSchema;
|
|
453
|
+
const schemasMap = {};
|
|
454
|
+
|
|
455
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
456
|
+
|
|
457
|
+
expect(object.nestedObject).toEqual(['item1', 'item2']);
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
describe('array properties', () => {
|
|
462
|
+
it('should cleanup array items with reference schema', () => {
|
|
463
|
+
const object = {
|
|
464
|
+
arrayField: [
|
|
465
|
+
{ validField: 'value1', invalidField: 'value2' },
|
|
466
|
+
{ validField: 'value3', invalidField: 'value4' }
|
|
467
|
+
]
|
|
468
|
+
};
|
|
469
|
+
const schema = {
|
|
470
|
+
id: 'test-schema',
|
|
471
|
+
properties: {
|
|
472
|
+
arrayField: {
|
|
473
|
+
type: 'array' as const,
|
|
474
|
+
items: { $ref: 'item-schema' }
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
} as ObjectSchema;
|
|
478
|
+
const itemSchema: ObjectSchema = {
|
|
479
|
+
id: 'item-schema',
|
|
480
|
+
properties: {
|
|
481
|
+
validField: { type: 'string' }
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
const schemasMap = {
|
|
485
|
+
'item-schema': itemSchema
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
489
|
+
|
|
490
|
+
expect(object.arrayField).toHaveLength(2);
|
|
491
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1' });
|
|
492
|
+
expect(object.arrayField[0]).not.toHaveProperty('invalidField');
|
|
493
|
+
expect(object.arrayField[1]).toEqual({ validField: 'value3' });
|
|
494
|
+
expect(object.arrayField[1]).not.toHaveProperty('invalidField');
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
it('should cleanup array items with object schema', () => {
|
|
498
|
+
const object = {
|
|
499
|
+
arrayField: [
|
|
500
|
+
{ validField: 'value1', invalidField: 'value2' },
|
|
501
|
+
{ validField: 'value3', invalidField: 'value4' }
|
|
502
|
+
]
|
|
503
|
+
};
|
|
504
|
+
const schema = {
|
|
505
|
+
id: 'test-schema',
|
|
506
|
+
properties: {
|
|
507
|
+
arrayField: {
|
|
508
|
+
type: 'array' as const,
|
|
509
|
+
items: {
|
|
510
|
+
type: 'object' as const,
|
|
511
|
+
properties: {
|
|
512
|
+
validField: { type: 'string' }
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
} as ObjectSchema;
|
|
518
|
+
const schemasMap = {};
|
|
519
|
+
|
|
520
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
521
|
+
|
|
522
|
+
expect(object.arrayField).toHaveLength(2);
|
|
523
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1' });
|
|
524
|
+
expect(object.arrayField[0]).not.toHaveProperty('invalidField');
|
|
525
|
+
expect(object.arrayField[1]).toEqual({ validField: 'value3' });
|
|
526
|
+
expect(object.arrayField[1]).not.toHaveProperty('invalidField');
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it('should handle empty arrays', () => {
|
|
530
|
+
const object = {
|
|
531
|
+
arrayField: []
|
|
532
|
+
};
|
|
533
|
+
const schema = {
|
|
534
|
+
id: 'test-schema',
|
|
535
|
+
properties: {
|
|
536
|
+
arrayField: {
|
|
537
|
+
type: 'array' as const,
|
|
538
|
+
items: { $ref: 'item-schema' }
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
} as ObjectSchema;
|
|
542
|
+
const itemSchema: ObjectSchema = {
|
|
543
|
+
id: 'item-schema',
|
|
544
|
+
properties: {
|
|
545
|
+
validField: { type: 'string' }
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
const schemasMap = {
|
|
549
|
+
'item-schema': itemSchema
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
553
|
+
|
|
554
|
+
expect(object.arrayField).toEqual([]);
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
it('should handle arrays with mixed valid and invalid properties', () => {
|
|
558
|
+
const object = {
|
|
559
|
+
arrayField: [
|
|
560
|
+
{ validField: 'value1' },
|
|
561
|
+
{ validField: 'value2', invalidField: 'value3' },
|
|
562
|
+
{ invalidField: 'value4' }
|
|
563
|
+
]
|
|
564
|
+
};
|
|
565
|
+
const schema = {
|
|
566
|
+
id: 'test-schema',
|
|
567
|
+
properties: {
|
|
568
|
+
arrayField: {
|
|
569
|
+
type: 'array' as const,
|
|
570
|
+
items: {
|
|
571
|
+
type: 'object' as const,
|
|
572
|
+
properties: {
|
|
573
|
+
validField: { type: 'string' }
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
} as ObjectSchema;
|
|
579
|
+
const schemasMap = {};
|
|
580
|
+
|
|
581
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
582
|
+
|
|
583
|
+
expect(object.arrayField).toHaveLength(3);
|
|
584
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1' });
|
|
585
|
+
expect(object.arrayField[1]).toEqual({ validField: 'value2' });
|
|
586
|
+
expect(object.arrayField[1]).not.toHaveProperty('invalidField');
|
|
587
|
+
expect(object.arrayField[2]).toEqual({});
|
|
588
|
+
expect(object.arrayField[2]).not.toHaveProperty('invalidField');
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
it('should skip cleanup when array property value is not an array', () => {
|
|
592
|
+
const object = {
|
|
593
|
+
arrayField: 'not-an-array'
|
|
594
|
+
};
|
|
595
|
+
const schema = {
|
|
596
|
+
id: 'test-schema',
|
|
597
|
+
properties: {
|
|
598
|
+
arrayField: {
|
|
599
|
+
type: 'array' as const,
|
|
600
|
+
items: {
|
|
601
|
+
type: 'object' as const,
|
|
602
|
+
properties: {
|
|
603
|
+
validField: { type: 'string' }
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
} as ObjectSchema;
|
|
609
|
+
const schemasMap = {};
|
|
610
|
+
|
|
611
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
612
|
+
|
|
613
|
+
expect(object.arrayField).toBe('not-an-array');
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it('should skip cleanup when array property value is null', () => {
|
|
617
|
+
const object = {
|
|
618
|
+
arrayField: null
|
|
619
|
+
};
|
|
620
|
+
const schema = {
|
|
621
|
+
id: 'test-schema',
|
|
622
|
+
properties: {
|
|
623
|
+
arrayField: {
|
|
624
|
+
type: 'array' as const,
|
|
625
|
+
items: {
|
|
626
|
+
type: 'object' as const,
|
|
627
|
+
properties: {
|
|
628
|
+
validField: { type: 'string' }
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
} as ObjectSchema;
|
|
634
|
+
const schemasMap = {};
|
|
635
|
+
|
|
636
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
637
|
+
|
|
638
|
+
expect(object.arrayField).toBeNull();
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
it('should skip cleanup when array property value is undefined', () => {
|
|
642
|
+
const object = {
|
|
643
|
+
arrayField: undefined
|
|
644
|
+
};
|
|
645
|
+
const schema = {
|
|
646
|
+
id: 'test-schema',
|
|
647
|
+
properties: {
|
|
648
|
+
arrayField: {
|
|
649
|
+
type: 'array' as const,
|
|
650
|
+
items: {
|
|
651
|
+
type: 'object' as const,
|
|
652
|
+
properties: {
|
|
653
|
+
validField: { type: 'string' }
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
} as ObjectSchema;
|
|
659
|
+
const schemasMap = {};
|
|
660
|
+
|
|
661
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
662
|
+
|
|
663
|
+
expect(object.arrayField).toBeUndefined();
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it('should skip cleanup for array items that are null', () => {
|
|
667
|
+
const object = {
|
|
668
|
+
arrayField: [
|
|
669
|
+
{ validField: 'value1' },
|
|
670
|
+
null,
|
|
671
|
+
{ validField: 'value2' }
|
|
672
|
+
]
|
|
673
|
+
};
|
|
674
|
+
const schema = {
|
|
675
|
+
id: 'test-schema',
|
|
676
|
+
properties: {
|
|
677
|
+
arrayField: {
|
|
678
|
+
type: 'array' as const,
|
|
679
|
+
items: {
|
|
680
|
+
type: 'object' as const,
|
|
681
|
+
properties: {
|
|
682
|
+
validField: { type: 'string' }
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
} as ObjectSchema;
|
|
688
|
+
const schemasMap = {};
|
|
689
|
+
|
|
690
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
691
|
+
|
|
692
|
+
expect(object.arrayField).toHaveLength(3);
|
|
693
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1' });
|
|
694
|
+
expect(object.arrayField[1]).toBeNull();
|
|
695
|
+
expect(object.arrayField[2]).toEqual({ validField: 'value2' });
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
it('should skip cleanup for array items that are undefined', () => {
|
|
699
|
+
const object = {
|
|
700
|
+
arrayField: [
|
|
701
|
+
{ validField: 'value1' },
|
|
702
|
+
undefined,
|
|
703
|
+
{ validField: 'value2' }
|
|
704
|
+
]
|
|
705
|
+
};
|
|
706
|
+
const schema = {
|
|
707
|
+
id: 'test-schema',
|
|
708
|
+
properties: {
|
|
709
|
+
arrayField: {
|
|
710
|
+
type: 'array' as const,
|
|
711
|
+
items: {
|
|
712
|
+
type: 'object' as const,
|
|
713
|
+
properties: {
|
|
714
|
+
validField: { type: 'string' }
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
} as ObjectSchema;
|
|
720
|
+
const schemasMap = {};
|
|
721
|
+
|
|
722
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
723
|
+
|
|
724
|
+
expect(object.arrayField).toHaveLength(3);
|
|
725
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1' });
|
|
726
|
+
expect(object.arrayField[1]).toBeUndefined();
|
|
727
|
+
expect(object.arrayField[2]).toEqual({ validField: 'value2' });
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
it('should skip cleanup for array items that are primitives', () => {
|
|
731
|
+
const object = {
|
|
732
|
+
arrayField: [
|
|
733
|
+
{ validField: 'value1' },
|
|
734
|
+
'string-item',
|
|
735
|
+
123,
|
|
736
|
+
true,
|
|
737
|
+
{ validField: 'value2' }
|
|
738
|
+
]
|
|
739
|
+
};
|
|
740
|
+
const schema = {
|
|
741
|
+
id: 'test-schema',
|
|
742
|
+
properties: {
|
|
743
|
+
arrayField: {
|
|
744
|
+
type: 'array' as const,
|
|
745
|
+
items: {
|
|
746
|
+
type: 'object' as const,
|
|
747
|
+
properties: {
|
|
748
|
+
validField: { type: 'string' }
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
} as ObjectSchema;
|
|
754
|
+
const schemasMap = {};
|
|
755
|
+
|
|
756
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
757
|
+
|
|
758
|
+
expect(object.arrayField).toHaveLength(5);
|
|
759
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1' });
|
|
760
|
+
expect(object.arrayField[1]).toBe('string-item');
|
|
761
|
+
expect(object.arrayField[2]).toBe(123);
|
|
762
|
+
expect(object.arrayField[3]).toBe(true);
|
|
763
|
+
expect(object.arrayField[4]).toEqual({ validField: 'value2' });
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
it('should skip cleanup for array items that are arrays', () => {
|
|
767
|
+
const object = {
|
|
768
|
+
arrayField: [
|
|
769
|
+
{ validField: 'value1' },
|
|
770
|
+
['nested', 'array'],
|
|
771
|
+
{ validField: 'value2' }
|
|
772
|
+
]
|
|
773
|
+
};
|
|
774
|
+
const schema = {
|
|
775
|
+
id: 'test-schema',
|
|
776
|
+
properties: {
|
|
777
|
+
arrayField: {
|
|
778
|
+
type: 'array' as const,
|
|
779
|
+
items: {
|
|
780
|
+
type: 'object' as const,
|
|
781
|
+
properties: {
|
|
782
|
+
validField: { type: 'string' }
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
} as ObjectSchema;
|
|
788
|
+
const schemasMap = {};
|
|
789
|
+
|
|
790
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
791
|
+
|
|
792
|
+
expect(object.arrayField).toHaveLength(3);
|
|
793
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1' });
|
|
794
|
+
expect(object.arrayField[1]).toEqual(['nested', 'array']);
|
|
795
|
+
expect(object.arrayField[2]).toEqual({ validField: 'value2' });
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
describe('complex nested scenarios', () => {
|
|
800
|
+
it('should handle object with mix of reference, object, and array properties', () => {
|
|
801
|
+
const object = {
|
|
802
|
+
refField: {
|
|
803
|
+
validField: 'value1',
|
|
804
|
+
invalidField: 'value2'
|
|
805
|
+
},
|
|
806
|
+
nestedObject: {
|
|
807
|
+
validField: 'value3',
|
|
808
|
+
invalidField: 'value4'
|
|
809
|
+
},
|
|
810
|
+
arrayField: [
|
|
811
|
+
{ validField: 'value5', invalidField: 'value6' }
|
|
812
|
+
],
|
|
813
|
+
invalidTopLevel: 'should be deleted'
|
|
814
|
+
};
|
|
815
|
+
const schema = {
|
|
816
|
+
id: 'test-schema',
|
|
817
|
+
properties: {
|
|
818
|
+
refField: { $ref: 'ref-schema' },
|
|
819
|
+
nestedObject: {
|
|
820
|
+
type: 'object' as const,
|
|
821
|
+
properties: {
|
|
822
|
+
validField: { type: 'string' }
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
arrayField: {
|
|
826
|
+
type: 'array' as const,
|
|
827
|
+
items: {
|
|
828
|
+
type: 'object' as const,
|
|
829
|
+
properties: {
|
|
830
|
+
validField: { type: 'string' }
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
} as ObjectSchema;
|
|
836
|
+
const refSchema: ObjectSchema = {
|
|
837
|
+
id: 'ref-schema',
|
|
838
|
+
properties: {
|
|
839
|
+
validField: { type: 'string' }
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
const schemasMap = {
|
|
843
|
+
'ref-schema': refSchema
|
|
844
|
+
};
|
|
845
|
+
|
|
846
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
847
|
+
|
|
848
|
+
expect(object).not.toHaveProperty('invalidTopLevel');
|
|
849
|
+
expect(object.refField).toEqual({ validField: 'value1' });
|
|
850
|
+
expect(object.refField).not.toHaveProperty('invalidField');
|
|
851
|
+
expect(object.nestedObject).toEqual({ validField: 'value3' });
|
|
852
|
+
expect(object.nestedObject).not.toHaveProperty('invalidField');
|
|
853
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value5' });
|
|
854
|
+
expect(object.arrayField[0]).not.toHaveProperty('invalidField');
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
it('should handle array of objects with nested references', () => {
|
|
858
|
+
const object = {
|
|
859
|
+
arrayField: [
|
|
860
|
+
{
|
|
861
|
+
refField: {
|
|
862
|
+
validField: 'value1',
|
|
863
|
+
invalidField: 'value2'
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
]
|
|
867
|
+
};
|
|
868
|
+
const schema = {
|
|
869
|
+
id: 'test-schema',
|
|
870
|
+
properties: {
|
|
871
|
+
arrayField: {
|
|
872
|
+
type: 'array' as const,
|
|
873
|
+
items: {
|
|
874
|
+
type: 'object' as const,
|
|
875
|
+
properties: {
|
|
876
|
+
refField: { $ref: 'nested-ref-schema' }
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
} as ObjectSchema;
|
|
882
|
+
const nestedRefSchema: ObjectSchema = {
|
|
883
|
+
id: 'nested-ref-schema',
|
|
884
|
+
properties: {
|
|
885
|
+
validField: { type: 'string' }
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
const schemasMap = {
|
|
889
|
+
'nested-ref-schema': nestedRefSchema
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
893
|
+
|
|
894
|
+
expect(object.arrayField[0].refField).toEqual({ validField: 'value1' });
|
|
895
|
+
expect(object.arrayField[0].refField).not.toHaveProperty('invalidField');
|
|
896
|
+
});
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
describe('edge cases and error handling', () => {
|
|
900
|
+
it('should skip cleanup when array property has undefined items', () => {
|
|
901
|
+
const object = {
|
|
902
|
+
arrayField: [
|
|
903
|
+
{ validField: 'value1', invalidField: 'value2' },
|
|
904
|
+
{ validField: 'value3', invalidField: 'value4' }
|
|
905
|
+
]
|
|
906
|
+
};
|
|
907
|
+
const schema = {
|
|
908
|
+
id: 'test-schema',
|
|
909
|
+
properties: {
|
|
910
|
+
arrayField: {
|
|
911
|
+
type: 'array' as const
|
|
912
|
+
// items is intentionally undefined
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
} as ObjectSchema;
|
|
916
|
+
const schemasMap = {};
|
|
917
|
+
|
|
918
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
919
|
+
|
|
920
|
+
// Should not modify array items when items schema is undefined
|
|
921
|
+
expect(object.arrayField).toHaveLength(2);
|
|
922
|
+
expect(object.arrayField[0]).toEqual({ validField: 'value1', invalidField: 'value2' });
|
|
923
|
+
expect(object.arrayField[1]).toEqual({ validField: 'value3', invalidField: 'value4' });
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
it('should return early when objectSchema has undefined properties', () => {
|
|
927
|
+
const object = {
|
|
928
|
+
field1: 'value1',
|
|
929
|
+
field2: 'value2'
|
|
930
|
+
};
|
|
931
|
+
const schema = {
|
|
932
|
+
id: 'test-schema'
|
|
933
|
+
// properties is intentionally undefined (malformed schema)
|
|
934
|
+
} as unknown as ObjectSchema;
|
|
935
|
+
const schemasMap = {};
|
|
936
|
+
|
|
937
|
+
cleanupAttributes(object, schema, schemasMap);
|
|
938
|
+
|
|
939
|
+
// Should not modify object when properties is undefined
|
|
940
|
+
expect(object).toEqual({ field1: 'value1', field2: 'value2' });
|
|
941
|
+
});
|
|
942
|
+
});
|
|
943
|
+
});
|