apify-schema-tools 2.0.1
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/.cspell/custom-dictionary.txt +4 -0
- package/.husky/pre-commit +33 -0
- package/.node-version +1 -0
- package/CHANGELOG.md +88 -0
- package/LICENSE +201 -0
- package/README.md +312 -0
- package/biome.json +31 -0
- package/dist/apify-schema-tools.d.ts +3 -0
- package/dist/apify-schema-tools.d.ts.map +1 -0
- package/dist/apify-schema-tools.js +197 -0
- package/dist/apify-schema-tools.js.map +1 -0
- package/dist/apify.d.ts +11 -0
- package/dist/apify.d.ts.map +1 -0
- package/dist/apify.js +107 -0
- package/dist/apify.js.map +1 -0
- package/dist/configuration.d.ts +43 -0
- package/dist/configuration.d.ts.map +1 -0
- package/dist/configuration.js +87 -0
- package/dist/configuration.js.map +1 -0
- package/dist/filesystem.d.ts +8 -0
- package/dist/filesystem.d.ts.map +1 -0
- package/dist/filesystem.js +16 -0
- package/dist/filesystem.js.map +1 -0
- package/dist/json-schemas.d.ts +34 -0
- package/dist/json-schemas.d.ts.map +1 -0
- package/dist/json-schemas.js +185 -0
- package/dist/json-schemas.js.map +1 -0
- package/dist/typescript.d.ts +26 -0
- package/dist/typescript.d.ts.map +1 -0
- package/dist/typescript.js +316 -0
- package/dist/typescript.js.map +1 -0
- package/package.json +60 -0
- package/samples/all-defaults/.actor/actor.json +15 -0
- package/samples/all-defaults/.actor/dataset_schema.json +32 -0
- package/samples/all-defaults/.actor/input_schema.json +53 -0
- package/samples/all-defaults/src/generated/dataset.ts +24 -0
- package/samples/all-defaults/src/generated/input-utils.ts +60 -0
- package/samples/all-defaults/src/generated/input.ts +42 -0
- package/samples/all-defaults/src-schemas/dataset-item.json +28 -0
- package/samples/all-defaults/src-schemas/input.json +73 -0
- package/samples/deep-merged-schemas/.actor/actor.json +15 -0
- package/samples/deep-merged-schemas/.actor/dataset_schema.json +37 -0
- package/samples/deep-merged-schemas/.actor/input_schema.json +61 -0
- package/samples/deep-merged-schemas/add-schemas/dataset-item.json +10 -0
- package/samples/deep-merged-schemas/add-schemas/input.json +33 -0
- package/samples/deep-merged-schemas/src/generated/dataset.ts +28 -0
- package/samples/deep-merged-schemas/src/generated/input-utils.ts +66 -0
- package/samples/deep-merged-schemas/src/generated/input.ts +47 -0
- package/samples/deep-merged-schemas/src-schemas/dataset-item.json +28 -0
- package/samples/deep-merged-schemas/src-schemas/input.json +73 -0
- package/samples/merged-schemas/.actor/actor.json +15 -0
- package/samples/merged-schemas/.actor/dataset_schema.json +37 -0
- package/samples/merged-schemas/.actor/input_schema.json +58 -0
- package/samples/merged-schemas/add-schemas/dataset-item.json +10 -0
- package/samples/merged-schemas/add-schemas/input.json +33 -0
- package/samples/merged-schemas/src/generated/dataset.ts +28 -0
- package/samples/merged-schemas/src/generated/input-utils.ts +57 -0
- package/samples/merged-schemas/src/generated/input.ts +42 -0
- package/samples/merged-schemas/src-schemas/dataset-item.json +28 -0
- package/samples/merged-schemas/src-schemas/input.json +73 -0
- package/samples/package-json-config/.actor/actor.json +15 -0
- package/samples/package-json-config/.actor/dataset_schema.json +32 -0
- package/samples/package-json-config/.actor/input_schema.json +53 -0
- package/samples/package-json-config/custom-src-schemas/dataset-item.json +28 -0
- package/samples/package-json-config/custom-src-schemas/input.json +73 -0
- package/samples/package-json-config/package.json +11 -0
- package/samples/package-json-config/src/custom-generated/dataset.ts +24 -0
- package/samples/package-json-config/src/custom-generated/input-utils.ts +60 -0
- package/samples/package-json-config/src/custom-generated/input.ts +42 -0
- package/src/apify-schema-tools.ts +302 -0
- package/src/apify.ts +124 -0
- package/src/configuration.ts +110 -0
- package/src/filesystem.ts +18 -0
- package/src/json-schemas.ts +252 -0
- package/src/typescript.ts +381 -0
- package/test/apify-schema-tools.test.ts +2064 -0
- package/test/apify.test.ts +28 -0
- package/test/common.ts +19 -0
- package/test/configuration.test.ts +642 -0
- package/test/json-schemas.test.ts +587 -0
- package/test/typescript.test.ts +817 -0
- package/tsconfig.json +18 -0
- package/update-samples.sh +27 -0
|
@@ -0,0 +1,817 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { cleanupTestDirectory, getTestDir, setupTestDirectory } from "./common";
|
|
4
|
+
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { readFile } from "../src/filesystem.js";
|
|
7
|
+
import type { ObjectSchema } from "../src/json-schemas";
|
|
8
|
+
import {
|
|
9
|
+
compareTypescriptInterfaces,
|
|
10
|
+
jsonSchemaToTypeScriptInterface,
|
|
11
|
+
parseTypeScriptInterface,
|
|
12
|
+
readGeneratedTypeScriptFile,
|
|
13
|
+
serializeTypeScriptInterface,
|
|
14
|
+
writeTypeScriptFile,
|
|
15
|
+
} from "../src/typescript.js";
|
|
16
|
+
|
|
17
|
+
const TEST_DIR = getTestDir("typescript");
|
|
18
|
+
|
|
19
|
+
describe("TypeScript files utilities", () => {
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
cleanupTestDirectory(TEST_DIR);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe("writeTypeScriptFile", () => {
|
|
25
|
+
it("should add a header to the TypeScript file", () => {
|
|
26
|
+
setupTestDirectory(TEST_DIR);
|
|
27
|
+
|
|
28
|
+
const content = "export const foo = 'bar';";
|
|
29
|
+
const filePath = path.join(TEST_DIR, "test.ts");
|
|
30
|
+
writeTypeScriptFile(filePath, content);
|
|
31
|
+
|
|
32
|
+
const fullContent = readFile(filePath);
|
|
33
|
+
expect(fullContent).toContain("generated by apify-schema-tools.");
|
|
34
|
+
|
|
35
|
+
const parsedContent = readGeneratedTypeScriptFile(filePath);
|
|
36
|
+
expect(parsedContent).toBe(content);
|
|
37
|
+
expect(parsedContent).not.toContain("generated by apify-schema-tools.");
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe("jsonSchemaToTypeScriptInterface", () => {
|
|
42
|
+
it("should convert JSON schema to TypeScript schema", () => {
|
|
43
|
+
const schema: ObjectSchema = {
|
|
44
|
+
description: "Test schema",
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
name: { type: "string" },
|
|
48
|
+
colors: {
|
|
49
|
+
type: "array",
|
|
50
|
+
items: {
|
|
51
|
+
type: "object",
|
|
52
|
+
properties: {
|
|
53
|
+
name: {
|
|
54
|
+
type: "string",
|
|
55
|
+
enum: ["red", "green", "blue"],
|
|
56
|
+
},
|
|
57
|
+
value: {
|
|
58
|
+
type: ["integer", "string"],
|
|
59
|
+
description: "The hex color value",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
required: ["name"],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
features: {
|
|
66
|
+
type: "array",
|
|
67
|
+
items: {
|
|
68
|
+
type: "string",
|
|
69
|
+
enum: ["dotted", "striped", "solid"],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
isNice: {
|
|
73
|
+
type: "boolean",
|
|
74
|
+
description: "Whether the shape is nice",
|
|
75
|
+
nullable: true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
required: ["name", "features", "isNice"],
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const tsInterface = jsonSchemaToTypeScriptInterface(schema);
|
|
82
|
+
|
|
83
|
+
expect(tsInterface).toEqual({
|
|
84
|
+
doc: "Test schema",
|
|
85
|
+
isRequired: true,
|
|
86
|
+
isArray: false,
|
|
87
|
+
properties: {
|
|
88
|
+
name: {
|
|
89
|
+
doc: undefined,
|
|
90
|
+
isRequired: true,
|
|
91
|
+
isArray: false,
|
|
92
|
+
type: "string",
|
|
93
|
+
},
|
|
94
|
+
colors: {
|
|
95
|
+
doc: undefined,
|
|
96
|
+
isRequired: false,
|
|
97
|
+
isArray: true,
|
|
98
|
+
properties: {
|
|
99
|
+
name: {
|
|
100
|
+
doc: undefined,
|
|
101
|
+
isRequired: true,
|
|
102
|
+
isArray: false,
|
|
103
|
+
enum: ["red", "green", "blue"],
|
|
104
|
+
},
|
|
105
|
+
value: {
|
|
106
|
+
doc: "The hex color value",
|
|
107
|
+
isRequired: false,
|
|
108
|
+
isArray: false,
|
|
109
|
+
type: ["number", "string"],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
features: {
|
|
114
|
+
doc: undefined,
|
|
115
|
+
isRequired: true,
|
|
116
|
+
isArray: true,
|
|
117
|
+
enum: ["dotted", "striped", "solid"],
|
|
118
|
+
},
|
|
119
|
+
isNice: {
|
|
120
|
+
doc: "Whether the shape is nice",
|
|
121
|
+
isRequired: true,
|
|
122
|
+
isArray: false,
|
|
123
|
+
type: ["boolean", "null"],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("serializeTypeScriptInterface", () => {
|
|
131
|
+
it("should serialize TypeScript interface to string", () => {
|
|
132
|
+
const tsSchema = {
|
|
133
|
+
doc: "Test schema",
|
|
134
|
+
isRequired: true,
|
|
135
|
+
isArray: false,
|
|
136
|
+
properties: {
|
|
137
|
+
name: {
|
|
138
|
+
doc: undefined,
|
|
139
|
+
isRequired: true,
|
|
140
|
+
isArray: false,
|
|
141
|
+
type: "string",
|
|
142
|
+
},
|
|
143
|
+
colors: {
|
|
144
|
+
doc: undefined,
|
|
145
|
+
isRequired: false,
|
|
146
|
+
isArray: true,
|
|
147
|
+
properties: {
|
|
148
|
+
name: {
|
|
149
|
+
doc: undefined,
|
|
150
|
+
isRequired: true,
|
|
151
|
+
isArray: false,
|
|
152
|
+
enum: ["red", "green", "blue"],
|
|
153
|
+
},
|
|
154
|
+
value: {
|
|
155
|
+
doc: "The hex color value",
|
|
156
|
+
isRequired: false,
|
|
157
|
+
isArray: false,
|
|
158
|
+
type: ["number", "string"],
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
features: {
|
|
163
|
+
doc: undefined,
|
|
164
|
+
isRequired: true,
|
|
165
|
+
isArray: true,
|
|
166
|
+
enum: ["dotted", "striped", "solid"],
|
|
167
|
+
},
|
|
168
|
+
isNice: {
|
|
169
|
+
doc: "Whether the shape is nice",
|
|
170
|
+
isRequired: true,
|
|
171
|
+
isArray: false,
|
|
172
|
+
type: ["boolean", "null"],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const serialized = serializeTypeScriptInterface("Shape", tsSchema);
|
|
178
|
+
expect(serialized).toBe(`\
|
|
179
|
+
/**
|
|
180
|
+
* Test schema
|
|
181
|
+
*/
|
|
182
|
+
export interface Shape {
|
|
183
|
+
name: string;
|
|
184
|
+
colors?: {
|
|
185
|
+
name: "red" | "green" | "blue";
|
|
186
|
+
/**
|
|
187
|
+
* The hex color value
|
|
188
|
+
*/
|
|
189
|
+
value?: number | string;
|
|
190
|
+
}[];
|
|
191
|
+
features: ("dotted" | "striped" | "solid")[];
|
|
192
|
+
/**
|
|
193
|
+
* Whether the shape is nice
|
|
194
|
+
*/
|
|
195
|
+
isNice: boolean | null;
|
|
196
|
+
}`);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe("parseTypeScriptInterface", () => {
|
|
201
|
+
it("should parse TypeScript interface from string", () => {
|
|
202
|
+
const tsInterface = `\
|
|
203
|
+
/**
|
|
204
|
+
* Test schema
|
|
205
|
+
*/
|
|
206
|
+
export interface Shape {
|
|
207
|
+
name: string;
|
|
208
|
+
colors?: {
|
|
209
|
+
name: "red" | "green" | "blue";
|
|
210
|
+
/**
|
|
211
|
+
* The hex color value
|
|
212
|
+
*/
|
|
213
|
+
value?: number | string;
|
|
214
|
+
}[];
|
|
215
|
+
features: ("dotted" | "striped" | "solid")[];
|
|
216
|
+
/**
|
|
217
|
+
* Whether the shape is nice
|
|
218
|
+
*/
|
|
219
|
+
isNice: boolean | null;
|
|
220
|
+
}`;
|
|
221
|
+
const parsed = parseTypeScriptInterface(tsInterface);
|
|
222
|
+
expect(parsed).toEqual({
|
|
223
|
+
doc: "Test schema",
|
|
224
|
+
isRequired: true,
|
|
225
|
+
isArray: false,
|
|
226
|
+
properties: {
|
|
227
|
+
name: {
|
|
228
|
+
doc: undefined,
|
|
229
|
+
isRequired: true,
|
|
230
|
+
isArray: false,
|
|
231
|
+
type: "string",
|
|
232
|
+
},
|
|
233
|
+
colors: {
|
|
234
|
+
doc: undefined,
|
|
235
|
+
isRequired: false,
|
|
236
|
+
isArray: true,
|
|
237
|
+
properties: {
|
|
238
|
+
name: {
|
|
239
|
+
doc: undefined,
|
|
240
|
+
isRequired: true,
|
|
241
|
+
isArray: false,
|
|
242
|
+
enum: ["red", "green", "blue"],
|
|
243
|
+
},
|
|
244
|
+
value: {
|
|
245
|
+
doc: "The hex color value",
|
|
246
|
+
isRequired: false,
|
|
247
|
+
isArray: false,
|
|
248
|
+
type: ["number", "string"],
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
features: {
|
|
253
|
+
doc: undefined,
|
|
254
|
+
isRequired: true,
|
|
255
|
+
isArray: true,
|
|
256
|
+
enum: ["dotted", "striped", "solid"],
|
|
257
|
+
},
|
|
258
|
+
isNice: {
|
|
259
|
+
doc: "Whether the shape is nice",
|
|
260
|
+
isRequired: true,
|
|
261
|
+
isArray: false,
|
|
262
|
+
type: ["boolean", "null"],
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe("compareTypescriptInterfaces", () => {
|
|
270
|
+
const baseInterface = {
|
|
271
|
+
doc: "Base interface",
|
|
272
|
+
isRequired: true,
|
|
273
|
+
isArray: false,
|
|
274
|
+
properties: {
|
|
275
|
+
name: {
|
|
276
|
+
doc: "User name",
|
|
277
|
+
isRequired: true,
|
|
278
|
+
isArray: false,
|
|
279
|
+
type: "string",
|
|
280
|
+
},
|
|
281
|
+
age: {
|
|
282
|
+
doc: undefined,
|
|
283
|
+
isRequired: false,
|
|
284
|
+
isArray: false,
|
|
285
|
+
type: "number",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
it("should return true for identical interfaces", () => {
|
|
291
|
+
const interfaceA = {
|
|
292
|
+
doc: "Test interface",
|
|
293
|
+
isRequired: true,
|
|
294
|
+
isArray: false,
|
|
295
|
+
properties: {
|
|
296
|
+
name: {
|
|
297
|
+
doc: "User name",
|
|
298
|
+
isRequired: true,
|
|
299
|
+
isArray: false,
|
|
300
|
+
type: "string",
|
|
301
|
+
},
|
|
302
|
+
age: {
|
|
303
|
+
doc: undefined,
|
|
304
|
+
isRequired: false,
|
|
305
|
+
isArray: false,
|
|
306
|
+
type: "number",
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
const interfaceB = {
|
|
311
|
+
doc: "Test interface",
|
|
312
|
+
isRequired: true,
|
|
313
|
+
isArray: false,
|
|
314
|
+
properties: {
|
|
315
|
+
name: {
|
|
316
|
+
doc: "User name",
|
|
317
|
+
isRequired: true,
|
|
318
|
+
isArray: false,
|
|
319
|
+
type: "string",
|
|
320
|
+
},
|
|
321
|
+
age: {
|
|
322
|
+
doc: undefined,
|
|
323
|
+
isRequired: false,
|
|
324
|
+
isArray: false,
|
|
325
|
+
type: "number",
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(true);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it("should return false for interfaces with different number of properties", () => {
|
|
334
|
+
const interfaceA = baseInterface;
|
|
335
|
+
const interfaceB = {
|
|
336
|
+
doc: "Test interface",
|
|
337
|
+
isRequired: true,
|
|
338
|
+
isArray: false,
|
|
339
|
+
properties: {
|
|
340
|
+
name: {
|
|
341
|
+
doc: "User name",
|
|
342
|
+
isRequired: true,
|
|
343
|
+
isArray: false,
|
|
344
|
+
type: "string",
|
|
345
|
+
},
|
|
346
|
+
age: {
|
|
347
|
+
doc: undefined,
|
|
348
|
+
isRequired: false,
|
|
349
|
+
isArray: false,
|
|
350
|
+
type: "number",
|
|
351
|
+
},
|
|
352
|
+
email: {
|
|
353
|
+
doc: undefined,
|
|
354
|
+
isRequired: true,
|
|
355
|
+
isArray: false,
|
|
356
|
+
type: "string",
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it("should return false for interfaces with different property names", () => {
|
|
365
|
+
const interfaceA = baseInterface;
|
|
366
|
+
const interfaceB = {
|
|
367
|
+
doc: "Test interface",
|
|
368
|
+
isRequired: true,
|
|
369
|
+
isArray: false,
|
|
370
|
+
properties: {
|
|
371
|
+
fullName: {
|
|
372
|
+
doc: "User name",
|
|
373
|
+
isRequired: true,
|
|
374
|
+
isArray: false,
|
|
375
|
+
type: "string",
|
|
376
|
+
},
|
|
377
|
+
age: {
|
|
378
|
+
doc: undefined,
|
|
379
|
+
isRequired: false,
|
|
380
|
+
isArray: false,
|
|
381
|
+
type: "number",
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it("should return false for properties with different types", () => {
|
|
390
|
+
const interfaceA = baseInterface;
|
|
391
|
+
const interfaceB = {
|
|
392
|
+
doc: "Test interface",
|
|
393
|
+
isRequired: true,
|
|
394
|
+
isArray: false,
|
|
395
|
+
properties: {
|
|
396
|
+
name: {
|
|
397
|
+
doc: "User name",
|
|
398
|
+
isRequired: true,
|
|
399
|
+
isArray: false,
|
|
400
|
+
type: "string",
|
|
401
|
+
},
|
|
402
|
+
age: {
|
|
403
|
+
doc: undefined,
|
|
404
|
+
isRequired: false,
|
|
405
|
+
isArray: false,
|
|
406
|
+
type: "string", // Different type
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("should return false for properties with different isRequired values", () => {
|
|
415
|
+
const interfaceA = baseInterface;
|
|
416
|
+
const interfaceB = {
|
|
417
|
+
doc: "Test interface",
|
|
418
|
+
isRequired: true,
|
|
419
|
+
isArray: false,
|
|
420
|
+
properties: {
|
|
421
|
+
name: {
|
|
422
|
+
doc: "User name",
|
|
423
|
+
isRequired: false, // Different isRequired
|
|
424
|
+
isArray: false,
|
|
425
|
+
type: "string",
|
|
426
|
+
},
|
|
427
|
+
age: {
|
|
428
|
+
doc: undefined,
|
|
429
|
+
isRequired: false,
|
|
430
|
+
isArray: false,
|
|
431
|
+
type: "number",
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it("should return false for properties with different isArray values", () => {
|
|
440
|
+
const interfaceA = baseInterface;
|
|
441
|
+
const interfaceB = {
|
|
442
|
+
doc: "Test interface",
|
|
443
|
+
isRequired: true,
|
|
444
|
+
isArray: false,
|
|
445
|
+
properties: {
|
|
446
|
+
name: {
|
|
447
|
+
doc: "User name",
|
|
448
|
+
isRequired: true,
|
|
449
|
+
isArray: true, // Different isArray
|
|
450
|
+
type: "string",
|
|
451
|
+
},
|
|
452
|
+
age: {
|
|
453
|
+
doc: undefined,
|
|
454
|
+
isRequired: false,
|
|
455
|
+
isArray: false,
|
|
456
|
+
type: "number",
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it("should return false for properties with different documentation when ignoreDocs is false", () => {
|
|
465
|
+
const interfaceA = baseInterface;
|
|
466
|
+
const interfaceB = {
|
|
467
|
+
doc: "Test interface",
|
|
468
|
+
isRequired: true,
|
|
469
|
+
isArray: false,
|
|
470
|
+
properties: {
|
|
471
|
+
name: {
|
|
472
|
+
doc: "Different documentation", // Different doc
|
|
473
|
+
isRequired: true,
|
|
474
|
+
isArray: false,
|
|
475
|
+
type: "string",
|
|
476
|
+
},
|
|
477
|
+
age: {
|
|
478
|
+
doc: undefined,
|
|
479
|
+
isRequired: false,
|
|
480
|
+
isArray: false,
|
|
481
|
+
type: "number",
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB, false)).toBe(false);
|
|
487
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false); // Default is false
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
it("should return true for properties with different documentation when ignoreDocs is true", () => {
|
|
491
|
+
const interfaceA = baseInterface;
|
|
492
|
+
const interfaceB = {
|
|
493
|
+
doc: "Test interface",
|
|
494
|
+
isRequired: true,
|
|
495
|
+
isArray: false,
|
|
496
|
+
properties: {
|
|
497
|
+
name: {
|
|
498
|
+
doc: "Different documentation", // Different doc
|
|
499
|
+
isRequired: true,
|
|
500
|
+
isArray: false,
|
|
501
|
+
type: "string",
|
|
502
|
+
},
|
|
503
|
+
age: {
|
|
504
|
+
doc: "Different age doc", // Different doc
|
|
505
|
+
isRequired: false,
|
|
506
|
+
isArray: false,
|
|
507
|
+
type: "number",
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB, true)).toBe(true);
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
it("should handle enum properties correctly", () => {
|
|
516
|
+
const interfaceA = {
|
|
517
|
+
doc: undefined,
|
|
518
|
+
isRequired: true,
|
|
519
|
+
isArray: false,
|
|
520
|
+
properties: {
|
|
521
|
+
status: {
|
|
522
|
+
doc: undefined,
|
|
523
|
+
isRequired: true,
|
|
524
|
+
isArray: false,
|
|
525
|
+
enum: ["active", "inactive", "pending"],
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
const interfaceB = {
|
|
530
|
+
doc: undefined,
|
|
531
|
+
isRequired: true,
|
|
532
|
+
isArray: false,
|
|
533
|
+
properties: {
|
|
534
|
+
status: {
|
|
535
|
+
doc: undefined,
|
|
536
|
+
isRequired: true,
|
|
537
|
+
isArray: false,
|
|
538
|
+
enum: ["active", "inactive", "pending"],
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(true);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it("should return false for enum properties with different values", () => {
|
|
547
|
+
const interfaceA = {
|
|
548
|
+
doc: undefined,
|
|
549
|
+
isRequired: true,
|
|
550
|
+
isArray: false,
|
|
551
|
+
properties: {
|
|
552
|
+
status: {
|
|
553
|
+
doc: undefined,
|
|
554
|
+
isRequired: true,
|
|
555
|
+
isArray: false,
|
|
556
|
+
enum: ["active", "inactive", "pending"],
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
};
|
|
560
|
+
const interfaceB = {
|
|
561
|
+
doc: undefined,
|
|
562
|
+
isRequired: true,
|
|
563
|
+
isArray: false,
|
|
564
|
+
properties: {
|
|
565
|
+
status: {
|
|
566
|
+
doc: undefined,
|
|
567
|
+
isRequired: true,
|
|
568
|
+
isArray: false,
|
|
569
|
+
enum: ["active", "inactive", "cancelled"], // Different enum value
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
it("should handle nested interface properties correctly", () => {
|
|
578
|
+
const interfaceA = {
|
|
579
|
+
doc: undefined,
|
|
580
|
+
isRequired: true,
|
|
581
|
+
isArray: false,
|
|
582
|
+
properties: {
|
|
583
|
+
user: {
|
|
584
|
+
doc: undefined,
|
|
585
|
+
isRequired: true,
|
|
586
|
+
isArray: false,
|
|
587
|
+
properties: {
|
|
588
|
+
name: {
|
|
589
|
+
doc: undefined,
|
|
590
|
+
isRequired: true,
|
|
591
|
+
isArray: false,
|
|
592
|
+
type: "string",
|
|
593
|
+
},
|
|
594
|
+
age: {
|
|
595
|
+
doc: undefined,
|
|
596
|
+
isRequired: false,
|
|
597
|
+
isArray: false,
|
|
598
|
+
type: "number",
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
},
|
|
603
|
+
};
|
|
604
|
+
const interfaceB = {
|
|
605
|
+
doc: undefined,
|
|
606
|
+
isRequired: true,
|
|
607
|
+
isArray: false,
|
|
608
|
+
properties: {
|
|
609
|
+
user: {
|
|
610
|
+
doc: undefined,
|
|
611
|
+
isRequired: true,
|
|
612
|
+
isArray: false,
|
|
613
|
+
properties: {
|
|
614
|
+
name: {
|
|
615
|
+
doc: undefined,
|
|
616
|
+
isRequired: true,
|
|
617
|
+
isArray: false,
|
|
618
|
+
type: "string",
|
|
619
|
+
},
|
|
620
|
+
age: {
|
|
621
|
+
doc: undefined,
|
|
622
|
+
isRequired: false,
|
|
623
|
+
isArray: false,
|
|
624
|
+
type: "number",
|
|
625
|
+
},
|
|
626
|
+
},
|
|
627
|
+
},
|
|
628
|
+
},
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(true);
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
it("should return false for nested interfaces with different structures", () => {
|
|
635
|
+
const interfaceA = {
|
|
636
|
+
doc: undefined,
|
|
637
|
+
isRequired: true,
|
|
638
|
+
isArray: false,
|
|
639
|
+
properties: {
|
|
640
|
+
user: {
|
|
641
|
+
doc: undefined,
|
|
642
|
+
isRequired: true,
|
|
643
|
+
isArray: false,
|
|
644
|
+
properties: {
|
|
645
|
+
name: {
|
|
646
|
+
doc: undefined,
|
|
647
|
+
isRequired: true,
|
|
648
|
+
isArray: false,
|
|
649
|
+
type: "string",
|
|
650
|
+
},
|
|
651
|
+
age: {
|
|
652
|
+
doc: undefined,
|
|
653
|
+
isRequired: false,
|
|
654
|
+
isArray: false,
|
|
655
|
+
type: "number",
|
|
656
|
+
},
|
|
657
|
+
},
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
};
|
|
661
|
+
const interfaceB = {
|
|
662
|
+
doc: undefined,
|
|
663
|
+
isRequired: true,
|
|
664
|
+
isArray: false,
|
|
665
|
+
properties: {
|
|
666
|
+
user: {
|
|
667
|
+
doc: undefined,
|
|
668
|
+
isRequired: true,
|
|
669
|
+
isArray: false,
|
|
670
|
+
properties: {
|
|
671
|
+
name: {
|
|
672
|
+
doc: undefined,
|
|
673
|
+
isRequired: true,
|
|
674
|
+
isArray: false,
|
|
675
|
+
type: "string",
|
|
676
|
+
},
|
|
677
|
+
// Missing age property
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
},
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
it("should handle union types correctly", () => {
|
|
687
|
+
const interfaceA = {
|
|
688
|
+
doc: undefined,
|
|
689
|
+
isRequired: true,
|
|
690
|
+
isArray: false,
|
|
691
|
+
properties: {
|
|
692
|
+
value: {
|
|
693
|
+
doc: undefined,
|
|
694
|
+
isRequired: true,
|
|
695
|
+
isArray: false,
|
|
696
|
+
type: ["string", "number"],
|
|
697
|
+
},
|
|
698
|
+
},
|
|
699
|
+
};
|
|
700
|
+
const interfaceB = {
|
|
701
|
+
doc: undefined,
|
|
702
|
+
isRequired: true,
|
|
703
|
+
isArray: false,
|
|
704
|
+
properties: {
|
|
705
|
+
value: {
|
|
706
|
+
doc: undefined,
|
|
707
|
+
isRequired: true,
|
|
708
|
+
isArray: false,
|
|
709
|
+
type: ["string", "number"],
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(true);
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
it("should return false for union types with different order", () => {
|
|
718
|
+
const interfaceA = {
|
|
719
|
+
doc: undefined,
|
|
720
|
+
isRequired: true,
|
|
721
|
+
isArray: false,
|
|
722
|
+
properties: {
|
|
723
|
+
value: {
|
|
724
|
+
doc: undefined,
|
|
725
|
+
isRequired: true,
|
|
726
|
+
isArray: false,
|
|
727
|
+
type: ["string", "number"],
|
|
728
|
+
},
|
|
729
|
+
},
|
|
730
|
+
};
|
|
731
|
+
const interfaceB = {
|
|
732
|
+
doc: undefined,
|
|
733
|
+
isRequired: true,
|
|
734
|
+
isArray: false,
|
|
735
|
+
properties: {
|
|
736
|
+
value: {
|
|
737
|
+
doc: undefined,
|
|
738
|
+
isRequired: true,
|
|
739
|
+
isArray: false,
|
|
740
|
+
type: ["number", "string"], // Different order
|
|
741
|
+
},
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
it("should return false when comparing interface property to basic type property", () => {
|
|
749
|
+
const interfaceA = {
|
|
750
|
+
doc: undefined,
|
|
751
|
+
isRequired: true,
|
|
752
|
+
isArray: false,
|
|
753
|
+
properties: {
|
|
754
|
+
data: {
|
|
755
|
+
doc: undefined,
|
|
756
|
+
isRequired: true,
|
|
757
|
+
isArray: false,
|
|
758
|
+
properties: {
|
|
759
|
+
name: {
|
|
760
|
+
doc: undefined,
|
|
761
|
+
isRequired: true,
|
|
762
|
+
isArray: false,
|
|
763
|
+
type: "string",
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
},
|
|
767
|
+
},
|
|
768
|
+
};
|
|
769
|
+
const interfaceB = {
|
|
770
|
+
doc: undefined,
|
|
771
|
+
isRequired: true,
|
|
772
|
+
isArray: false,
|
|
773
|
+
properties: {
|
|
774
|
+
data: {
|
|
775
|
+
doc: undefined,
|
|
776
|
+
isRequired: true,
|
|
777
|
+
isArray: false,
|
|
778
|
+
type: "string", // Basic type instead of interface
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
it("should return false when comparing enum property to basic type property", () => {
|
|
787
|
+
const interfaceA = {
|
|
788
|
+
doc: undefined,
|
|
789
|
+
isRequired: true,
|
|
790
|
+
isArray: false,
|
|
791
|
+
properties: {
|
|
792
|
+
status: {
|
|
793
|
+
doc: undefined,
|
|
794
|
+
isRequired: true,
|
|
795
|
+
isArray: false,
|
|
796
|
+
enum: ["active", "inactive"],
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
};
|
|
800
|
+
const interfaceB = {
|
|
801
|
+
doc: undefined,
|
|
802
|
+
isRequired: true,
|
|
803
|
+
isArray: false,
|
|
804
|
+
properties: {
|
|
805
|
+
status: {
|
|
806
|
+
doc: undefined,
|
|
807
|
+
isRequired: true,
|
|
808
|
+
isArray: false,
|
|
809
|
+
type: "string", // Basic type instead of enum
|
|
810
|
+
},
|
|
811
|
+
},
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
expect(compareTypescriptInterfaces(interfaceA, interfaceB)).toBe(false);
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
});
|