@sdk-it/core 0.31.0 → 0.31.2
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/package.json +3 -2
- package/dist/lib/deriver.test.d.ts +0 -1
- package/dist/lib/deriver.test.d.ts.map +0 -1
- package/dist/lib/deriver.test.js +0 -382
- package/dist/lib/deriver.test.js.map +0 -7
- package/dist/lib/file-system.test.d.ts +0 -2
- package/dist/lib/file-system.test.d.ts.map +0 -1
- package/dist/lib/file-system.test.js +0 -357
- package/dist/lib/file-system.test.js.map +0 -7
- package/dist/lib/program.test.d.ts +0 -2
- package/dist/lib/program.test.d.ts.map +0 -1
- package/dist/lib/program.test.js +0 -289
- package/dist/lib/program.test.js.map +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdk-it/core",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"dist",
|
|
26
|
-
"!**/*.tsbuildinfo"
|
|
26
|
+
"!**/*.tsbuildinfo",
|
|
27
|
+
"!**/*.test.*"
|
|
27
28
|
],
|
|
28
29
|
"dependencies": {
|
|
29
30
|
"debug": "^4.4.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=deriver.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deriver.test.d.ts","sourceRoot":"","sources":["../../src/lib/deriver.test.ts"],"names":[],"mappings":""}
|
package/dist/lib/deriver.test.js
DELETED
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "node:test";
|
|
2
|
-
describe("serializeType: Basic Primitive and Special Types", () => {
|
|
3
|
-
it.todo("serializes `any` type to an empty type list", () => {
|
|
4
|
-
});
|
|
5
|
-
it.todo("serializes `unknown` type to an empty type list", () => {
|
|
6
|
-
});
|
|
7
|
-
it.todo("serializes `string` type", () => {
|
|
8
|
-
});
|
|
9
|
-
it.todo("serializes `number` type", () => {
|
|
10
|
-
});
|
|
11
|
-
it.todo("serializes `boolean` type", () => {
|
|
12
|
-
});
|
|
13
|
-
it.todo("serializes `null` type as optional", () => {
|
|
14
|
-
});
|
|
15
|
-
it.todo(
|
|
16
|
-
"serializes `void` type (likely falls back to Any/Unknown or unhandled)",
|
|
17
|
-
() => {
|
|
18
|
-
}
|
|
19
|
-
);
|
|
20
|
-
it.todo(
|
|
21
|
-
"serializes `never` type (likely falls back to Any/Unknown or unhandled)",
|
|
22
|
-
() => {
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
it.todo(
|
|
26
|
-
"serializes `undefined` type implicitly via union/intersection optional flag",
|
|
27
|
-
() => {
|
|
28
|
-
}
|
|
29
|
-
);
|
|
30
|
-
});
|
|
31
|
-
describe("serializeType: Literal Types", () => {
|
|
32
|
-
it.todo("serializes string literal types with their value", () => {
|
|
33
|
-
});
|
|
34
|
-
it.todo("serializes numeric literal types with their value", () => {
|
|
35
|
-
});
|
|
36
|
-
it.todo("serializes boolean literal `true` type", () => {
|
|
37
|
-
});
|
|
38
|
-
it.todo("serializes boolean literal `false` type", () => {
|
|
39
|
-
});
|
|
40
|
-
it.todo("serializes template literal types as base `string`", () => {
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
describe("serializeType: Enum Types", () => {
|
|
44
|
-
it.todo(
|
|
45
|
-
"serializes an Enum type (e.g., `enum Color {}`) potentially via unhandled path",
|
|
46
|
-
() => {
|
|
47
|
-
}
|
|
48
|
-
);
|
|
49
|
-
it.todo(
|
|
50
|
-
"serializes an EnumLiteral type (e.g., `Color.Red`) potentially via unhandled path or base type",
|
|
51
|
-
() => {
|
|
52
|
-
}
|
|
53
|
-
);
|
|
54
|
-
});
|
|
55
|
-
describe("serializeType: Union Types (`|`)", () => {
|
|
56
|
-
it.todo(
|
|
57
|
-
"serializes a union of primitive types (e.g., string | number)",
|
|
58
|
-
() => {
|
|
59
|
-
}
|
|
60
|
-
);
|
|
61
|
-
it.todo(
|
|
62
|
-
"serializes a union type including `null` (e.g., string | null)",
|
|
63
|
-
() => {
|
|
64
|
-
}
|
|
65
|
-
);
|
|
66
|
-
it.todo(
|
|
67
|
-
"serializes a union type including `undefined`, setting optional flag and filtering `undefined`",
|
|
68
|
-
() => {
|
|
69
|
-
}
|
|
70
|
-
);
|
|
71
|
-
it.todo(
|
|
72
|
-
"serializes a union type including both `null` and `undefined`",
|
|
73
|
-
() => {
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
it.todo('serializes a union of literal types (e.g., "a" | "b" | 1)', () => {
|
|
77
|
-
});
|
|
78
|
-
it.todo(
|
|
79
|
-
"serializes a union including complex types (e.g., string | MyInterface)",
|
|
80
|
-
() => {
|
|
81
|
-
}
|
|
82
|
-
);
|
|
83
|
-
it.todo("serializes a union containing only `undefined`", () => {
|
|
84
|
-
});
|
|
85
|
-
it.todo("serializes a union containing only `null`", () => {
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
describe("serializeType: Intersection Types (`&`)", () => {
|
|
89
|
-
it.todo(
|
|
90
|
-
"serializes an intersection of object/interface types (e.g., A & B)",
|
|
91
|
-
() => {
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
it.todo(
|
|
95
|
-
"serializes an intersection type including `undefined`, setting optional flag and filtering `undefined`",
|
|
96
|
-
() => {
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
it.todo("serializes an intersection containing only `undefined`", () => {
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
describe("serializeType: Array and Tuple Types", () => {
|
|
103
|
-
it.todo("serializes a simple array type (e.g., string[])", () => {
|
|
104
|
-
});
|
|
105
|
-
it.todo("serializes readonly array types (e.g., readonly number[])", () => {
|
|
106
|
-
});
|
|
107
|
-
it.todo(
|
|
108
|
-
"serializes an array type with object elements (e.g., MyInterface[])",
|
|
109
|
-
() => {
|
|
110
|
-
}
|
|
111
|
-
);
|
|
112
|
-
it.todo(
|
|
113
|
-
"serializes an array type with union elements (e.g., (string | number)[])",
|
|
114
|
-
() => {
|
|
115
|
-
}
|
|
116
|
-
);
|
|
117
|
-
it.todo("serializes an array type where element type has no symbol", () => {
|
|
118
|
-
});
|
|
119
|
-
it.todo(
|
|
120
|
-
"serializes an array type where element symbol has no value declaration but has declarations",
|
|
121
|
-
() => {
|
|
122
|
-
}
|
|
123
|
-
);
|
|
124
|
-
it.todo(
|
|
125
|
-
"serializes an array type with a mapped type element (e.g., MappedType[])",
|
|
126
|
-
() => {
|
|
127
|
-
}
|
|
128
|
-
);
|
|
129
|
-
it.todo(
|
|
130
|
-
"handles array-like types with missing type arguments gracefully (e.g., Array)",
|
|
131
|
-
() => {
|
|
132
|
-
}
|
|
133
|
-
);
|
|
134
|
-
it.todo(
|
|
135
|
-
"serializes tuple types (e.g., [string, number]) potentially as array of union",
|
|
136
|
-
() => {
|
|
137
|
-
}
|
|
138
|
-
);
|
|
139
|
-
});
|
|
140
|
-
describe("serializeType: Record/Index Types", () => {
|
|
141
|
-
it.todo(
|
|
142
|
-
"serializes a string index signature type (Record<string, number>)",
|
|
143
|
-
() => {
|
|
144
|
-
}
|
|
145
|
-
);
|
|
146
|
-
it.todo(
|
|
147
|
-
"serializes a string index signature type with complex value (Record<string, MyInterface>)",
|
|
148
|
-
() => {
|
|
149
|
-
}
|
|
150
|
-
);
|
|
151
|
-
it.todo(
|
|
152
|
-
"serializes a type with only a number index signature ([key: number]: boolean)",
|
|
153
|
-
() => {
|
|
154
|
-
}
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
describe("serializeType: Object Types (Interfaces, Classes, Inline, Mapped)", () => {
|
|
158
|
-
it.todo("serializes an inline object type literal (passed as type)", () => {
|
|
159
|
-
});
|
|
160
|
-
it.todo(
|
|
161
|
-
"serializes a mapped type directly (e.g., type M = { [K in keyof T]: T[K] })",
|
|
162
|
-
() => {
|
|
163
|
-
}
|
|
164
|
-
);
|
|
165
|
-
it.todo(
|
|
166
|
-
"serializes an object type using literal property assignments from declarations",
|
|
167
|
-
() => {
|
|
168
|
-
}
|
|
169
|
-
);
|
|
170
|
-
it.todo(
|
|
171
|
-
"serializes an object type with mixed declared types (PropertySignature) and literal assignments (PropertyAssignment)",
|
|
172
|
-
() => {
|
|
173
|
-
}
|
|
174
|
-
);
|
|
175
|
-
it.todo(
|
|
176
|
-
"serializes an empty object type `{}` potentially falling back to name or generic",
|
|
177
|
-
() => {
|
|
178
|
-
}
|
|
179
|
-
);
|
|
180
|
-
it.todo(
|
|
181
|
-
"handles object types matching default overrides (e.g., DateConstructor -> string)",
|
|
182
|
-
() => {
|
|
183
|
-
}
|
|
184
|
-
);
|
|
185
|
-
it.todo(
|
|
186
|
-
"handles known object types NOT in defaults (e.g., RegExp) by attempting standard object serialization",
|
|
187
|
-
() => {
|
|
188
|
-
}
|
|
189
|
-
);
|
|
190
|
-
it.todo(
|
|
191
|
-
"serializes an interface type by deferring to serializeNode for reference/collection",
|
|
192
|
-
() => {
|
|
193
|
-
}
|
|
194
|
-
);
|
|
195
|
-
it.todo(
|
|
196
|
-
"serializes a class type by deferring to serializeNode for reference/collection",
|
|
197
|
-
() => {
|
|
198
|
-
}
|
|
199
|
-
);
|
|
200
|
-
it.todo(
|
|
201
|
-
"serializes an interface type using its name when its declaration cannot be found",
|
|
202
|
-
() => {
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
it.todo(
|
|
206
|
-
"serializes a class type using its name when its declaration cannot be found",
|
|
207
|
-
() => {
|
|
208
|
-
}
|
|
209
|
-
);
|
|
210
|
-
});
|
|
211
|
-
describe("serializeType: Unhandled Types", () => {
|
|
212
|
-
it.todo(
|
|
213
|
-
"handles an unhandled type flag by using checker.typeToString and warns",
|
|
214
|
-
() => {
|
|
215
|
-
}
|
|
216
|
-
);
|
|
217
|
-
});
|
|
218
|
-
describe("serializeNode: Object Literal Expressions (`{ ... }`)", () => {
|
|
219
|
-
it.todo(
|
|
220
|
-
"serializes an object literal node with various primitive property types",
|
|
221
|
-
() => {
|
|
222
|
-
}
|
|
223
|
-
);
|
|
224
|
-
it.todo(
|
|
225
|
-
"serializes an object literal node with nested object/array literals",
|
|
226
|
-
() => {
|
|
227
|
-
}
|
|
228
|
-
);
|
|
229
|
-
it.todo("serializes an empty object literal node `{}`", () => {
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
describe("serializeNode: Property Access/Signature/Declaration", () => {
|
|
233
|
-
it.todo(
|
|
234
|
-
"serializes a PropertyAccessExpression node (e.g., `obj.prop`) by resolving its type",
|
|
235
|
-
() => {
|
|
236
|
-
}
|
|
237
|
-
);
|
|
238
|
-
it.todo(
|
|
239
|
-
"serializes a PropertySignature node (e.g., `prop: string;`) by resolving its type",
|
|
240
|
-
() => {
|
|
241
|
-
}
|
|
242
|
-
);
|
|
243
|
-
it.todo(
|
|
244
|
-
"serializes a PropertyDeclaration node (e.g., `prop: number;`) by resolving its type",
|
|
245
|
-
() => {
|
|
246
|
-
}
|
|
247
|
-
);
|
|
248
|
-
it.todo(
|
|
249
|
-
"handles property nodes where symbol cannot be found for the property name and warns",
|
|
250
|
-
() => {
|
|
251
|
-
}
|
|
252
|
-
);
|
|
253
|
-
});
|
|
254
|
-
describe("serializeNode: Interface Declarations (`interface ...`) and Collector Interaction", () => {
|
|
255
|
-
it.todo(
|
|
256
|
-
"serializes a new interface declaration, adding its structure to the collector",
|
|
257
|
-
() => {
|
|
258
|
-
}
|
|
259
|
-
);
|
|
260
|
-
it.todo(
|
|
261
|
-
"returns only a reference for an already serialized interface declaration (present in collector)",
|
|
262
|
-
() => {
|
|
263
|
-
}
|
|
264
|
-
);
|
|
265
|
-
it.todo(
|
|
266
|
-
"handles interface declarations matching default overrides without adding to collector",
|
|
267
|
-
() => {
|
|
268
|
-
}
|
|
269
|
-
);
|
|
270
|
-
it.todo("throws an error for an interface declaration without a name", () => {
|
|
271
|
-
});
|
|
272
|
-
it.todo(
|
|
273
|
-
"handles interfaces with no members correctly (adds empty object to collector)",
|
|
274
|
-
() => {
|
|
275
|
-
}
|
|
276
|
-
);
|
|
277
|
-
it.todo(
|
|
278
|
-
"handles interfaces extending other interfaces (serialization includes only own properties)",
|
|
279
|
-
() => {
|
|
280
|
-
}
|
|
281
|
-
);
|
|
282
|
-
});
|
|
283
|
-
describe("serializeNode: Class Declarations (`class ...`) and Collector Interaction", () => {
|
|
284
|
-
it.todo(
|
|
285
|
-
"serializes a new class declaration, adding its property structure to the collector",
|
|
286
|
-
() => {
|
|
287
|
-
}
|
|
288
|
-
);
|
|
289
|
-
it.todo(
|
|
290
|
-
"returns only a reference for an already serialized class declaration (present in collector)",
|
|
291
|
-
() => {
|
|
292
|
-
}
|
|
293
|
-
);
|
|
294
|
-
it.todo(
|
|
295
|
-
"handles class declarations matching default overrides without adding to collector",
|
|
296
|
-
() => {
|
|
297
|
-
}
|
|
298
|
-
);
|
|
299
|
-
it.todo(
|
|
300
|
-
"throws an error for a class declaration without a name (e.g., anonymous default export)",
|
|
301
|
-
() => {
|
|
302
|
-
}
|
|
303
|
-
);
|
|
304
|
-
it.todo(
|
|
305
|
-
"handles classes with no property declarations (only methods/constructor) correctly (adds empty object to collector)",
|
|
306
|
-
() => {
|
|
307
|
-
}
|
|
308
|
-
);
|
|
309
|
-
it.todo(
|
|
310
|
-
"handles classes implementing interfaces (serialization includes only own properties)",
|
|
311
|
-
() => {
|
|
312
|
-
}
|
|
313
|
-
);
|
|
314
|
-
it.todo(
|
|
315
|
-
"handles classes extending other classes (serialization includes only own properties)",
|
|
316
|
-
() => {
|
|
317
|
-
}
|
|
318
|
-
);
|
|
319
|
-
});
|
|
320
|
-
describe("serializeNode: Other Node Types", () => {
|
|
321
|
-
it.todo(
|
|
322
|
-
"serializes a VariableDeclaration node with an explicit type annotation",
|
|
323
|
-
() => {
|
|
324
|
-
}
|
|
325
|
-
);
|
|
326
|
-
it.todo(
|
|
327
|
-
"handles VariableDeclaration node without a type annotation and warns",
|
|
328
|
-
() => {
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
it.todo(
|
|
332
|
-
"handles VariableDeclaration node where symbol cannot be found for the variable name and warns",
|
|
333
|
-
() => {
|
|
334
|
-
}
|
|
335
|
-
);
|
|
336
|
-
it.todo(
|
|
337
|
-
"serializes an Identifier node by resolving its type at that location",
|
|
338
|
-
() => {
|
|
339
|
-
}
|
|
340
|
-
);
|
|
341
|
-
it.todo(
|
|
342
|
-
"handles Identifier node where symbol cannot be found and warns",
|
|
343
|
-
() => {
|
|
344
|
-
}
|
|
345
|
-
);
|
|
346
|
-
it.todo(
|
|
347
|
-
"serializes an AwaitExpression node by resolving the awaited type",
|
|
348
|
-
() => {
|
|
349
|
-
}
|
|
350
|
-
);
|
|
351
|
-
it.todo(
|
|
352
|
-
"serializes a CallExpression node by resolving its return type",
|
|
353
|
-
() => {
|
|
354
|
-
}
|
|
355
|
-
);
|
|
356
|
-
it.todo(
|
|
357
|
-
"serializes an AsExpression node by resolving the asserted type",
|
|
358
|
-
() => {
|
|
359
|
-
}
|
|
360
|
-
);
|
|
361
|
-
it.todo(
|
|
362
|
-
"serializes a TypeLiteralNode (`{ ... }` used as a type) by resolving its properties",
|
|
363
|
-
() => {
|
|
364
|
-
}
|
|
365
|
-
);
|
|
366
|
-
it.todo("serializes NullKeyword node", () => {
|
|
367
|
-
});
|
|
368
|
-
it.todo("serializes BooleanKeyword node", () => {
|
|
369
|
-
});
|
|
370
|
-
it.todo("serializes TrueKeyword node as boolean literal", () => {
|
|
371
|
-
});
|
|
372
|
-
it.todo("serializes FalseKeyword node as boolean literal", () => {
|
|
373
|
-
});
|
|
374
|
-
it.todo(
|
|
375
|
-
"serializes an ArrayLiteralExpression node by resolving its inferred type",
|
|
376
|
-
() => {
|
|
377
|
-
}
|
|
378
|
-
);
|
|
379
|
-
it.todo("handles an unhandled node kind by returning `any` and warns", () => {
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
//# sourceMappingURL=deriver.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/lib/deriver.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { describe, it } from 'node:test';\n\n// --- serializeType Functionality ---\n\ndescribe('serializeType: Basic Primitive and Special Types', () => {\n it.todo('serializes `any` type to an empty type list', () => {\n // Input: ts.Type with TypeFlags.Any\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [] }\n });\n it.todo('serializes `unknown` type to an empty type list', () => {\n // Input: ts.Type with TypeFlags.Unknown\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [] }\n });\n it.todo('serializes `string` type', () => {\n // Input: ts.Type with TypeFlags.String\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] }\n });\n it.todo('serializes `number` type', () => {\n // Input: ts.Type with TypeFlags.Number\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['number'] }\n });\n it.todo('serializes `boolean` type', () => {\n // Input: ts.Type with TypeFlags.Boolean\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n });\n it.todo('serializes `null` type as optional', () => {\n // Input: ts.Type with TypeFlags.Null\n // Output: { [deriveSymbol]: true, optional: true, [$types]: ['null'] }\n });\n it.todo(\n 'serializes `void` type (likely falls back to Any/Unknown or unhandled)',\n () => {\n // Input: ts.Type with TypeFlags.Void (or VoidLike)\n // Determine expected output based on how TS checker presents this type and how the unhandled path works. Likely results in `[$types]: []` or `[$types]: ['void']`.\n },\n );\n it.todo(\n 'serializes `never` type (likely falls back to Any/Unknown or unhandled)',\n () => {\n // Input: ts.Type with TypeFlags.Never\n // Determine expected output. Likely results in `[$types]: []` or `[$types]: ['never']`.\n },\n );\n it.todo(\n 'serializes `undefined` type implicitly via union/intersection optional flag',\n () => {\n // Note: Undefined itself isn't directly serialized as a standalone type by this logic.\n // Its presence in unions/intersections correctly sets the `optional` flag. Tests are under Union/Intersection sections.\n },\n );\n});\n\ndescribe('serializeType: Literal Types', () => {\n it.todo('serializes string literal types with their value', () => {\n // Input: ts.StringLiteralType (e.g., type of \"constant\")\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: 'constant', [$types]: ['string'] }\n });\n it.todo('serializes numeric literal types with their value', () => {\n // Input: ts.NumberLiteralType (e.g., type of 123)\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: 123, [$types]: ['number'] }\n });\n it.todo('serializes boolean literal `true` type', () => {\n // Input: ts.BooleanLiteralType (true) checked via TypeFlags.BooleanLiteral\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n // Note: Current code identifies it's boolean but doesn't store the literal `true` value.\n });\n it.todo('serializes boolean literal `false` type', () => {\n // Input: ts.BooleanLiteralType (false) checked via TypeFlags.BooleanLiteral\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n // Note: Current code identifies it's boolean but doesn't store the literal `false` value.\n });\n it.todo('serializes template literal types as base `string`', () => {\n // Input: ts.Type with TypeFlags.TemplateLiteral (e.g. type of `ID-${number}`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] }\n });\n // Note: BigIntLiteral is not explicitly handled, would fall under unhandled.\n});\n\ndescribe('serializeType: Enum Types', () => {\n it.todo(\n 'serializes an Enum type (e.g., `enum Color {}`) potentially via unhandled path',\n () => {\n // Input: ts.Type with TypeFlags.Enum (representing the enum itself, e.g., `Color`)\n // Expect it to fall into the unhandled path, likely using checker.typeToString.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['Color'] } or similar based on typeToString. Check console warning.\n },\n );\n it.todo(\n 'serializes an EnumLiteral type (e.g., `Color.Red`) potentially via unhandled path or base type',\n () => {\n // Input: ts.Type with TypeFlags.EnumLiteral (representing the enum member, e.g., `Color.Red`)\n // Check if TS resolves this to its base type (string/number) or if it falls to unhandled.\n // If number enum: Potentially { [deriveSymbol]: true, optional: false, [$types]: ['number'] }\n // If string enum: Potentially { [deriveSymbol]: true, optional: false, [$types]: ['string'] } or a literal string.\n // If unhandled: { [deriveSymbol]: true, optional: false, [$types]: ['Color.Red'] } or similar. Check console warning.\n },\n );\n});\n\ndescribe('serializeType: Union Types (`|`)', () => {\n it.todo(\n 'serializes a union of primitive types (e.g., string | number)',\n () => {\n // Input: ts.UnionType with string and number types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedNumber] }\n },\n );\n it.todo(\n 'serializes a union type including `null` (e.g., string | null)',\n () => {\n // Input: ts.UnionType with string and null types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedNull] }\n // Note: `optional` remains false because `null` is treated as a distinct type here.\n },\n );\n it.todo(\n 'serializes a union type including `undefined`, setting optional flag and filtering `undefined`',\n () => {\n // Input: ts.UnionType with string and undefined types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [serializedString] } // undefined is filtered out, optional set to true\n },\n );\n it.todo(\n 'serializes a union type including both `null` and `undefined`',\n () => {\n // Input: ts.UnionType with string, null, and undefined types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [serializedString, serializedNull] } // undefined filtered, optional true\n },\n );\n it.todo('serializes a union of literal types (e.g., \"a\" | \"b\" | 1)', () => {\n // Input: ts.UnionType with \"a\", \"b\", 1 types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedLiteralA, serializedLiteralB, serializedLiteral1] }\n });\n it.todo(\n 'serializes a union including complex types (e.g., string | MyInterface)',\n () => {\n // Input: ts.UnionType with string and an interface type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedInterfaceRef] }\n },\n );\n it.todo('serializes a union containing only `undefined`', () => {\n // Input: ts.UnionType with only undefined type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [] }\n });\n it.todo('serializes a union containing only `null`', () => {\n // Input: ts.UnionType with only null type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedNull] }\n });\n});\n\ndescribe('serializeType: Intersection Types (`&`)', () => {\n it.todo(\n 'serializes an intersection of object/interface types (e.g., A & B)',\n () => {\n // Input: ts.IntersectionType with two interface types A and B\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: false, [$types]: [serializedInterfaceA, serializedInterfaceB] }\n },\n );\n it.todo(\n 'serializes an intersection type including `undefined`, setting optional flag and filtering `undefined`',\n () => {\n // Input: ts.IntersectionType with an interface type A and undefined\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: true, [$types]: [serializedInterfaceA] }\n },\n );\n it.todo('serializes an intersection containing only `undefined`', () => {\n // Input: ts.IntersectionType with only undefined type\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: true, [$types]: [] }\n });\n // Note: Intersections of primitives often resolve to `never`. The serialization of `never` itself is tested separately.\n});\n\ndescribe('serializeType: Array and Tuple Types', () => {\n it.todo('serializes a simple array type (e.g., string[])', () => {\n // Input: ts.TypeReference to Array<string>\n // Mock checker.isArrayLikeType -> true, checker.getTypeArguments -> [stringType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedString] }\n });\n it.todo('serializes readonly array types (e.g., readonly number[])', () => {\n // Input: ts.TypeReference to ReadonlyArray<number>\n // Mock checker.isArrayLikeType -> true, checker.getTypeArguments -> [numberType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedNumber] }\n });\n it.todo(\n 'serializes an array type with object elements (e.g., MyInterface[])',\n () => {\n // Input: ts.TypeReference to Array<MyInterface>\n // Mock checker.getTypeArguments -> [interfaceType], interfaceType.symbol.valueDeclaration -> InterfaceDeclaration Node\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedInterfaceRef] } // Relies on serializeNode call\n },\n );\n it.todo(\n 'serializes an array type with union elements (e.g., (string | number)[])',\n () => {\n // Input: ts.TypeReference to Array<string | number>\n // Mock checker.getTypeArguments -> [unionType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedUnionStringNumber] }\n },\n );\n it.todo('serializes an array type where element type has no symbol', () => {\n // Input: ts.TypeReference to Array<{inline: boolean}>\n // Mock checker.getTypeArguments -> [inlineObjectType], inlineObjectType.getSymbol() -> undefined\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedInlineObject] } // Relies on serializeType(inlineObjectType)\n });\n it.todo(\n 'serializes an array type where element symbol has no value declaration but has declarations',\n () => {\n // Input: ts.TypeReference to Array<SomeType>\n // Mock checker.getTypeArguments -> [someType], someType.symbol.valueDeclaration -> undefined, someType.symbol.declarations -> [TypeAliasDeclaration Node?]\n // Expect serializeNode to be called with declarations[0]. Verify output based on that node type.\n },\n );\n it.todo(\n 'serializes an array type with a mapped type element (e.g., MappedType[])',\n () => {\n // Input: ts.TypeReference to Array<MappedType>\n // Mock checker.getTypeArguments -> [mappedType], mappedType symbol has declarations[0] as MappedTypeNode\n // Mock checker.getPropertiesOfType for mappedType\n // Output: { kind: 'array', optional: false, [deriveSymbol]: true, [$types]: [resolvedMappedObject] }\n },\n );\n it.todo(\n 'handles array-like types with missing type arguments gracefully (e.g., Array)',\n () => {\n // Input: ts.TypeReference to Array (no <T>)\n // Mock checker.getTypeArguments -> undefined or []\n // Output: { [deriveSymbol]: true, optional: false, kind: 'array', [$types]: ['any'] } // Check console warning\n },\n );\n it.todo(\n 'serializes tuple types (e.g., [string, number]) potentially as array of union',\n () => {\n // Input: ts.TupleTypeReference for [string, number]\n // Mock checker.isArrayLikeType -> true. Check what checker.getTypeArguments returns (likely the tuple element types).\n // Current code likely serializes as Array<string | number>.\n // Expected Output (based on current code): { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedUnionStringNumber] } or similar union.\n // Note: A more precise tuple serialization would require specific handling of ts.TupleTypeReference.\n },\n );\n});\n\ndescribe('serializeType: Record/Index Types', () => {\n it.todo(\n 'serializes a string index signature type (Record<string, number>)',\n () => {\n // Input: ts.Type where type.getStringIndexType() returns numberType\n // Output: { [deriveSymbol]: true, kind: 'record', optional: false, [$types]: [serializedNumber] }\n },\n );\n it.todo(\n 'serializes a string index signature type with complex value (Record<string, MyInterface>)',\n () => {\n // Input: ts.Type where type.getStringIndexType() returns interfaceType\n // Output: { [deriveSymbol]: true, kind: 'record', optional: false, [$types]: [serializedInterfaceRef] }\n },\n );\n it.todo(\n 'serializes a type with only a number index signature ([key: number]: boolean)',\n () => {\n // Input: ts.Type where type.getStringIndexType() is undefined, but type.getNumberIndexType() exists.\n // Expect this to *not* take the `getStringIndexType` path.\n // It should fall into the `TypeFlags.Object` path.\n // Mock checker.getPropertiesOfType (might be empty or special symbol).\n // Mock type.symbol.declarations to include the IndexSignature node.\n // Expected Output: Likely falls back to generic object or potentially unhandled `{ [deriveSymbol]: true, optional: false, [$types]: ['<some object representation>'] }`. Needs verification against actual TS behavior.\n },\n );\n});\n\ndescribe('serializeType: Object Types (Interfaces, Classes, Inline, Mapped)', () => {\n it.todo('serializes an inline object type literal (passed as type)', () => {\n // Input: ts.Type representing `{ a: string; b?: number }` (TypeFlags.Object)\n // Mock checker.getPropertiesOfType -> [symbolA, symbolB]\n // Mock checker.getTypeOfSymbol for 'a' (string) and 'b' (number | undefined)\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ a: serializedString, b: serializedUnionNumberUndefined }] }\n });\n it.todo(\n 'serializes a mapped type directly (e.g., type M = { [K in keyof T]: T[K] })',\n () => {\n // Input: ts.Type representing a mapped type (TypeFlags.Object, potentially others)\n // Mock checker.getPropertiesOfType to return the mapped properties.\n // Mock checker.getTypeOfSymbol for each mapped property.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ /* serialized mapped properties */ }] }\n },\n );\n it.todo(\n 'serializes an object type using literal property assignments from declarations',\n () => {\n // Input: ts.Type representing an object like `const x = { val: 123 }`\n // Mock checker.getPropertiesOfType -> [symbolVal]\n // Mock symbolVal.getDeclarations() -> [PropertyAssignment node with literal 123]\n // Mock checker.getTypeAtLocation for the literal initializer -> numberLiteralType(123)\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ val: serializedLiteral123 }] }\n },\n );\n it.todo(\n 'serializes an object type with mixed declared types (PropertySignature) and literal assignments (PropertyAssignment)',\n () => {\n // Input: ts.Type representing `{ prop: string; literal: \"hello\" }` where `prop` comes from signature and `literal` from assignment.\n // Ensure both `isPropertyAssignment` and `isPropertySignature` paths within the loop are tested.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ prop: serializedString, literal: serializedLiteralHello }] }\n },\n );\n it.todo(\n 'serializes an empty object type `{}` potentially falling back to name or generic',\n () => {\n // Input: ts.Type representing `{}` (TypeFlags.Object)\n // Mock checker.getPropertiesOfType -> []\n // Mock type.symbol.valueDeclaration / declarations -> undefined\n // Mock type.symbol.getName() -> 'Object' or similar\n // Expected Output: Depends on fallback logic. Potentially `{ [deriveSymbol]: true, optional: false, [$types]: ['Object'] }` or a generic object representation if name is unhelpful.\n },\n );\n it.todo(\n 'handles object types matching default overrides (e.g., DateConstructor -> string)',\n () => {\n // Input: ts.Type whose symbol name is 'DateConstructor' (present in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] } // Value from `defaults` map\n },\n );\n it.todo(\n 'handles known object types NOT in defaults (e.g., RegExp) by attempting standard object serialization',\n () => {\n // Input: ts.Type for RegExp (not in `defaults`)\n // Mock checker.getPropertiesOfType (likely empty or methods)\n // Mock symbol.valueDeclaration / declarations (likely points to lib.d.ts)\n // Expect standard object serialization attempt, possibly resulting in an empty object or reference if declaration is found.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ /* properties or empty */ }] } or a reference via serializeNode.\n },\n );\n it.todo(\n 'serializes an interface type by deferring to serializeNode for reference/collection',\n () => {\n // Input: ts.InterfaceType (an interface type verified by type.isClassOrInterface() and symbol flags)\n // Mock type.symbol.valueDeclaration or declarations[0] -> InterfaceDeclaration node\n // Verify serializeNode is called with the declaration node.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n },\n );\n it.todo(\n 'serializes a class type by deferring to serializeNode for reference/collection',\n () => {\n // Input: ts.Type representing a class (isClass returns true)\n // Mock type.symbol.valueDeclaration -> ClassDeclaration node\n // Verify serializeNode is called with the declaration node.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n },\n );\n it.todo(\n 'serializes an interface type using its name when its declaration cannot be found',\n () => {\n // Input: ts.InterfaceType where type.symbol has no valueDeclaration or declarations[0]\n // Mock type.symbol.getName() -> 'MyInterface'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['MyInterface'] }\n },\n );\n it.todo(\n 'serializes a class type using its name when its declaration cannot be found',\n () => {\n // Input: ts.Type for a class where type.symbol has no valueDeclaration\n // Mock type.symbol.getName() -> 'MyClass'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['MyClass'] }\n },\n );\n});\n\ndescribe('serializeType: Unhandled Types', () => {\n it.todo(\n 'handles an unhandled type flag by using checker.typeToString and warns',\n () => {\n // Input: A ts.Type with flags not explicitly handled (e.g., potentially Enum, Index, IndexedAccess if not resolved)\n // Mock checker.typeToString -> '<specific unhandled representation>'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['<specific unhandled representation>'] } // Check console warning\n },\n );\n // Note: Complex types like ConditionalType, IndexedAccessType are expected to be resolved by the checker *before* this function sees them.\n // We serialize the *result* of the resolution, not the conditional/indexed access type itself.\n});\n\n// --- serializeNode Functionality ---\n\ndescribe('serializeNode: Object Literal Expressions (`{ ... }`)', () => {\n it.todo(\n 'serializes an object literal node with various primitive property types',\n () => {\n // Input: ts.ObjectLiteralExpression node `{ a: 1, b: \"s\", c: true, d: null, e: undefined }`\n // Mock checker.getTypeAtLocation for the node itself\n // Mock checker.getTypeOfSymbol for properties 'a', 'b', 'c', 'd', 'e'\n // Mock checker.getTypeAtLocation for literal initializers (1, \"s\", true, null, undefined)\n // Output: { a: serializedLiteral1, b: serializedLiteralS, c: serializedLiteralTrue, d: serializedNull, e: serializedUndefined } // Note: undefined serialization depends on serializeType\n },\n );\n it.todo(\n 'serializes an object literal node with nested object/array literals',\n () => {\n // Input: ts.ObjectLiteralExpression node `{ data: { values: [1, 2] } }`\n // Ensure recursive serialization via serializeType/serializeNode works.\n // Output: { data: { values: serializedArrayLiteral12 } }\n },\n );\n it.todo('serializes an empty object literal node `{}`', () => {\n // Input: ts.ObjectLiteralExpression node `{}`\n // Mock checker.getTypeAtLocation -> empty object type\n // Output: {}\n });\n});\n\ndescribe('serializeNode: Property Access/Signature/Declaration', () => {\n it.todo(\n 'serializes a PropertyAccessExpression node (e.g., `obj.prop`) by resolving its type',\n () => {\n // Input: ts.PropertyAccessExpression node `obj.prop`\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> typeProp\n // Verify serializeType is called with typeProp.\n // Output: Result of serializeType(typeProp)\n },\n );\n it.todo(\n 'serializes a PropertySignature node (e.g., `prop: string;`) by resolving its type',\n () => {\n // Input: ts.PropertySignature node `prop: string;` (within an InterfaceDeclaration or TypeLiteral)\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> stringType\n // Verify serializeType is called with stringType.\n // Output: Result of serializeType(stringType)\n },\n );\n it.todo(\n 'serializes a PropertyDeclaration node (e.g., `prop: number;`) by resolving its type',\n () => {\n // Input: ts.PropertyDeclaration node `prop: number;` (within a ClassDeclaration)\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> numberType\n // Verify serializeType is called with numberType.\n // Output: Result of serializeType(numberType)\n },\n );\n it.todo(\n 'handles property nodes where symbol cannot be found for the property name and warns',\n () => {\n // Input: A PropertySignature/Declaration/Access node where checker.getSymbolAtLocation(node.name) returns undefined\n // Output: null // Check console warning\n },\n );\n});\n\ndescribe('serializeNode: Interface Declarations (`interface ...`) and Collector Interaction', () => {\n it.todo(\n 'serializes a new interface declaration, adding its structure to the collector',\n () => {\n // Input: ts.InterfaceDeclaration node `interface MyInterface { id: number; name?: string; }`\n // Ensure collector['MyInterface'] is initially empty/undefined.\n // Mock members `id` and `name` and their serialization via serializeNode(PropertySignature).\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n // Verify collector['MyInterface'] now contains { id: serializedNumber, name: serializedUnionStringUndefined }\n },\n );\n it.todo(\n 'returns only a reference for an already serialized interface declaration (present in collector)',\n () => {\n // Input: ts.InterfaceDeclaration node `interface MyInterface { ... }`\n // Pre-populate collector['MyInterface'] with a placeholder or previous result.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n // Verify collector['MyInterface'] was not overwritten if already fully populated.\n },\n );\n it.todo(\n 'handles interface declarations matching default overrides without adding to collector',\n () => {\n // Input: ts.InterfaceDeclaration node `interface Readable { ... }` (name is in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Value from `defaults` map\n // Verify collector['Readable'] remains undefined or unchanged.\n },\n );\n it.todo('throws an error for an interface declaration without a name', () => {\n // Input: An InterfaceDeclaration node where node.name is undefined.\n // Expect the function to throw 'Interface has no name'.\n });\n it.todo(\n 'handles interfaces with no members correctly (adds empty object to collector)',\n () => {\n // Input: ts.InterfaceDeclaration node `interface Empty {}`\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/Empty`] }\n // Verify collector['Empty'] is `{}`.\n },\n );\n it.todo(\n 'handles interfaces extending other interfaces (serialization includes only own properties)',\n () => {\n // Input: `interface B extends A { propB: string; }` (where A is `interface A { propA: number }`)\n // Serialize B.\n // Output: Reference `#/components/schemas/B`\n // Verify collector['B'] contains only `{ propB: serializedString }`. (Inherited props are resolved by tools consuming the schema, not duplicated here).\n // Note: Actual inheritance representation might need adjustment based on target schema format (e.g., OpenAPI `allOf`). This test verifies the *collector* content based on current code.\n },\n );\n});\n\ndescribe('serializeNode: Class Declarations (`class ...`) and Collector Interaction', () => {\n it.todo(\n 'serializes a new class declaration, adding its property structure to the collector',\n () => {\n // Input: ts.ClassDeclaration node `class MyClass { id: number; private secret: string; constructor() {} }`\n // Ensure collector['MyClass'] is initially empty/undefined.\n // Mock members `id` and `secret` and their serialization via serializeNode(PropertyDeclaration). Ignore constructor/methods.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n // Verify collector['MyClass'] now contains { id: serializedNumber, secret: serializedString } (Includes private members)\n },\n );\n it.todo(\n 'returns only a reference for an already serialized class declaration (present in collector)',\n () => {\n // Input: ts.ClassDeclaration node `class MyClass { ... }`\n // Pre-populate collector['MyClass'] with a placeholder or previous result.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n // Verify collector['MyClass'] was not overwritten if already fully populated.\n },\n );\n it.todo(\n 'handles class declarations matching default overrides without adding to collector',\n () => {\n // Input: ts.ClassDeclaration node `class Uint8Array { ... }` (name is in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Value from `defaults` map\n // Verify collector['Uint8Array'] remains undefined or unchanged.\n },\n );\n it.todo(\n 'throws an error for a class declaration without a name (e.g., anonymous default export)',\n () => {\n // Input: A ClassDeclaration node where node.name is undefined.\n // Expect the function to throw 'Class has no name'.\n },\n );\n it.todo(\n 'handles classes with no property declarations (only methods/constructor) correctly (adds empty object to collector)',\n () => {\n // Input: ts.ClassDeclaration node `class Service { constructor() {} process() {} }`\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/Service`], $ref: `#/components/schemas/Service` }\n // Verify collector['Service'] is `{}`.\n },\n );\n it.todo(\n 'handles classes implementing interfaces (serialization includes only own properties)',\n () => {\n // Input: `class B implements A { propB: string; }` (where A is `interface A { propA: number }`)\n // Serialize B.\n // Output: Reference `#/components/schemas/B`\n // Verify collector['B'] contains only `{ propB: serializedString }`.\n },\n );\n it.todo(\n 'handles classes extending other classes (serialization includes only own properties)',\n () => {\n // Input: `class D extends C { propD: string; }` (where C is `class C { propC: number }`)\n // Serialize D.\n // Output: Reference `#/components/schemas/D`\n // Verify collector['D'] contains only `{ propD: serializedString }`.\n },\n );\n});\n\ndescribe('serializeNode: Other Node Types', () => {\n it.todo(\n 'serializes a VariableDeclaration node with an explicit type annotation',\n () => {\n // Input: ts.VariableDeclaration node `const user: IUser;`\n // Mock node.type to be a TypeReference node pointing to IUser\n // Mock checker.getTypeFromTypeNode -> interfaceType IUser\n // Verify serializeType is called with interfaceType IUser.\n // Output: Result of serializeType(interfaceType IUser) -> likely interface reference\n },\n );\n it.todo(\n 'handles VariableDeclaration node without a type annotation and warns',\n () => {\n // Input: ts.VariableDeclaration node `const count = 5;` (node.type is undefined)\n // Output: 'any' // Check console warning\n },\n );\n it.todo(\n 'handles VariableDeclaration node where symbol cannot be found for the variable name and warns',\n () => {\n // Input: ts.VariableDeclaration node where checker.getSymbolAtLocation(node.name) returns undefined\n // Output: null // Check console warning\n },\n );\n it.todo(\n 'serializes an Identifier node by resolving its type at that location',\n () => {\n // Input: ts.Identifier node `myVar` (where myVar is declared as string)\n // Mock checker.getSymbolAtLocation for the identifier -> symbolMyVar\n // Mock checker.getTypeAtLocation for the identifier node -> stringType\n // Verify serializeType is called with stringType.\n // Output: Result of serializeType(stringType)\n },\n );\n it.todo(\n 'handles Identifier node where symbol cannot be found and warns',\n () => {\n // Input: ts.Identifier node where checker.getSymbolAtLocation returns undefined\n // Output: null // Check console warning\n },\n );\n it.todo(\n 'serializes an AwaitExpression node by resolving the awaited type',\n () => {\n // Input: ts.AwaitExpression node `await getUser()` where getUser returns Promise<User>\n // Mock checker.getTypeAtLocation(node) -> User type (checker resolves the Promise)\n // Verify serializeType is called with the User type.\n // Output: Result of serializeType(User type)\n },\n );\n it.todo(\n 'serializes a CallExpression node by resolving its return type',\n () => {\n // Input: ts.CallExpression node `calculateTotal()` where calculateTotal returns number\n // Mock checker.getTypeAtLocation(node) -> numberType\n // Verify serializeType is called with numberType.\n // Output: Result of serializeType(numberType)\n },\n );\n it.todo(\n 'serializes an AsExpression node by resolving the asserted type',\n () => {\n // Input: ts.AsExpression node `data as Product`\n // Mock checker.getTypeAtLocation(node) -> Product type (the asserted type)\n // Verify serializeType is called with the Product type.\n // Output: Result of serializeType(Product type)\n },\n );\n it.todo(\n 'serializes a TypeLiteralNode (`{ ... }` used as a type) by resolving its properties',\n () => {\n // Input: ts.TypeLiteralNode node `{ id: number; value: string }`\n // Mock checker.getTypeAtLocation(node) -> objectType\n // Mock checker.getPropertiesOfType(objectType) -> [symbolId, symbolValue]\n // Mock checker.getTypeOfSymbol for each property.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [{ id: serializedNumber, value: serializedString }] }\n },\n );\n it.todo('serializes NullKeyword node', () => {\n // Input: Node with kind ts.SyntaxKind.NullKeyword\n // Output: { [deriveSymbol]: true, optional: true, [$types]: ['null'] }\n });\n it.todo('serializes BooleanKeyword node', () => {\n // Input: Node with kind ts.SyntaxKind.BooleanKeyword\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n });\n it.todo('serializes TrueKeyword node as boolean literal', () => {\n // Input: Node with kind ts.SyntaxKind.TrueKeyword\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: true, [$types]: ['boolean'] }\n });\n it.todo('serializes FalseKeyword node as boolean literal', () => {\n // Input: Node with kind ts.SyntaxKind.FalseKeyword\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: false, [$types]: ['boolean'] }\n });\n it.todo(\n 'serializes an ArrayLiteralExpression node by resolving its inferred type',\n () => {\n // Input: ts.ArrayLiteralExpression node `[1, \"a\", null]`\n // Mock checker.getTypeAtLocation(node) -> inferred array type (e.g., (number | string | null)[])\n // Verify serializeType is called with the inferred type.\n // Output: Result of serializeType(inferred array type) -> likely array of union\n },\n );\n it.todo('handles an unhandled node kind by returning `any` and warns', () => {\n // Input: A node with a kind not explicitly handled (e.g., ts.SyntaxKind.IfStatement)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Check console warning\n });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-system.test.d.ts","sourceRoot":"","sources":["../../src/lib/file-system.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { after, before, describe, it } from "node:test";
|
|
6
|
-
import {
|
|
7
|
-
addLeadingSlash,
|
|
8
|
-
exist,
|
|
9
|
-
getExt,
|
|
10
|
-
getFile,
|
|
11
|
-
getFolderExports,
|
|
12
|
-
isNullOrUndefined,
|
|
13
|
-
readFolder,
|
|
14
|
-
removeTrialingSlashes,
|
|
15
|
-
writeFiles
|
|
16
|
-
} from "./file-system.ts";
|
|
17
|
-
describe("File System Utilities - Error-First Testing", () => {
|
|
18
|
-
let testDir;
|
|
19
|
-
let nonExistentPath;
|
|
20
|
-
before(async () => {
|
|
21
|
-
testDir = join(tmpdir(), `fs-test-${Date.now()}`);
|
|
22
|
-
await mkdir(testDir, { recursive: true });
|
|
23
|
-
nonExistentPath = join(testDir, "non-existent-directory", "deep", "path");
|
|
24
|
-
});
|
|
25
|
-
after(async () => {
|
|
26
|
-
const { rm } = await import("node:fs/promises");
|
|
27
|
-
await rm(testDir, { recursive: true, force: true });
|
|
28
|
-
});
|
|
29
|
-
describe("getFile - Attack Phase: Invalid Inputs & File System Errors", () => {
|
|
30
|
-
it("should return null for non-existent file", async () => {
|
|
31
|
-
const result = await getFile(join(testDir, "does-not-exist.txt"));
|
|
32
|
-
assert.strictEqual(result, null);
|
|
33
|
-
});
|
|
34
|
-
it("should return null for empty string path", async () => {
|
|
35
|
-
const result = await getFile("");
|
|
36
|
-
assert.strictEqual(result, null);
|
|
37
|
-
});
|
|
38
|
-
it("should throw error when trying to read a directory path instead of file", async () => {
|
|
39
|
-
const dirPath = join(testDir, "test-dir-for-getfile");
|
|
40
|
-
await mkdir(dirPath);
|
|
41
|
-
await assert.rejects(() => getFile(dirPath), {
|
|
42
|
-
code: "EISDIR"
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
it("should handle permission denied scenarios gracefully", async () => {
|
|
46
|
-
const result = await getFile("/root/protected-file.txt");
|
|
47
|
-
assert.strictEqual(result, null);
|
|
48
|
-
});
|
|
49
|
-
it("should handle malformed paths", async () => {
|
|
50
|
-
const malformedPaths = [
|
|
51
|
-
"\0invalid",
|
|
52
|
-
"file\nwith\nnewlines",
|
|
53
|
-
"file with tabs"
|
|
54
|
-
];
|
|
55
|
-
for (const path of malformedPaths) {
|
|
56
|
-
const result = await getFile(path);
|
|
57
|
-
assert.strictEqual(result, null, `Failed for path: ${path}`);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
describe("exist - Attack Phase: Edge Cases & Invalid Paths", () => {
|
|
62
|
-
it("should return false for non-existent paths", async () => {
|
|
63
|
-
assert.strictEqual(await exist(nonExistentPath), false);
|
|
64
|
-
});
|
|
65
|
-
it("should return false for empty string", async () => {
|
|
66
|
-
assert.strictEqual(await exist(""), false);
|
|
67
|
-
});
|
|
68
|
-
it("should handle null bytes in path gracefully", async () => {
|
|
69
|
-
assert.strictEqual(await exist("path\0with\0nulls"), false);
|
|
70
|
-
});
|
|
71
|
-
it("should handle extremely long paths", async () => {
|
|
72
|
-
const longPath = "a".repeat(1e4);
|
|
73
|
-
assert.strictEqual(await exist(longPath), false);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
describe("readFolder - Attack Phase: Directory Corruption & Invalid States", () => {
|
|
77
|
-
it("should return empty array for non-existent directory", async () => {
|
|
78
|
-
const result = await readFolder(nonExistentPath);
|
|
79
|
-
assert.deepStrictEqual(result, []);
|
|
80
|
-
});
|
|
81
|
-
it("should throw error for file path instead of directory", async () => {
|
|
82
|
-
const filePath = join(testDir, "test-file-for-readfolder.txt");
|
|
83
|
-
await writeFile(filePath, "content");
|
|
84
|
-
await assert.rejects(() => readFolder(filePath), {
|
|
85
|
-
code: "ENOTDIR"
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
it("should handle permission denied on directory", async () => {
|
|
89
|
-
const result = await readFolder("/root");
|
|
90
|
-
assert.deepStrictEqual(result, []);
|
|
91
|
-
});
|
|
92
|
-
it("should handle recursive reading with circular symlinks gracefully", async () => {
|
|
93
|
-
const result = await readFolder(testDir, true);
|
|
94
|
-
assert.ok(Array.isArray(result));
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
describe("writeFiles - Attack Phase: Write Failures & State Corruption", () => {
|
|
98
|
-
it("should handle null content gracefully", async () => {
|
|
99
|
-
const content = {
|
|
100
|
-
"test.txt": null,
|
|
101
|
-
"valid.txt": "content"
|
|
102
|
-
};
|
|
103
|
-
await writeFiles(testDir, content);
|
|
104
|
-
assert.strictEqual(await exist(join(testDir, "test.txt")), false);
|
|
105
|
-
assert.strictEqual(await exist(join(testDir, "valid.txt")), true);
|
|
106
|
-
});
|
|
107
|
-
it("should fail gracefully when writing to read-only directory", async () => {
|
|
108
|
-
const readOnlyPath = "/read-only-system-path";
|
|
109
|
-
const content = {
|
|
110
|
-
"test.txt": "content"
|
|
111
|
-
};
|
|
112
|
-
try {
|
|
113
|
-
await writeFiles(readOnlyPath, content);
|
|
114
|
-
assert.fail("Should have thrown an error for read-only directory");
|
|
115
|
-
} catch (error) {
|
|
116
|
-
assert.ok(error instanceof Error);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
it("should handle ignoreIfExists flag correctly when file exists", async () => {
|
|
120
|
-
const filePath = join(testDir, "existing.txt");
|
|
121
|
-
await writeFile(filePath, "original");
|
|
122
|
-
const content = {
|
|
123
|
-
"existing.txt": {
|
|
124
|
-
content: "should not overwrite",
|
|
125
|
-
ignoreIfExists: true
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
await writeFiles(testDir, content);
|
|
129
|
-
const result = await getFile(filePath);
|
|
130
|
-
assert.strictEqual(result, "original");
|
|
131
|
-
});
|
|
132
|
-
it("should create deeply nested directories", async () => {
|
|
133
|
-
const content = {
|
|
134
|
-
"deep/nested/structure/file.txt": "content"
|
|
135
|
-
};
|
|
136
|
-
await writeFiles(testDir, content);
|
|
137
|
-
const result = await getFile(
|
|
138
|
-
join(testDir, "deep/nested/structure/file.txt")
|
|
139
|
-
);
|
|
140
|
-
assert.strictEqual(result, "content");
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
describe("getFolderExports - Attack Phase: Invalid Folder States", () => {
|
|
144
|
-
const mockReadFolder = async (folder) => {
|
|
145
|
-
if (folder === nonExistentPath) {
|
|
146
|
-
return [];
|
|
147
|
-
}
|
|
148
|
-
return [
|
|
149
|
-
{
|
|
150
|
-
filePath: join(folder, "valid.ts"),
|
|
151
|
-
fileName: "valid.ts",
|
|
152
|
-
isFolder: false
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
filePath: join(folder, "index.ts"),
|
|
156
|
-
fileName: "index.ts",
|
|
157
|
-
isFolder: false
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
filePath: join(folder, "subfolder"),
|
|
161
|
-
fileName: "subfolder",
|
|
162
|
-
isFolder: true
|
|
163
|
-
}
|
|
164
|
-
];
|
|
165
|
-
};
|
|
166
|
-
it("should handle non-existent folder gracefully", async () => {
|
|
167
|
-
const result = await getFolderExports(nonExistentPath, mockReadFolder);
|
|
168
|
-
assert.strictEqual(result, "");
|
|
169
|
-
});
|
|
170
|
-
it("should ignore files with unsupported extensions", async () => {
|
|
171
|
-
const mockReadFolderWithJs = async () => [
|
|
172
|
-
{ filePath: "test.js", fileName: "test.js", isFolder: false },
|
|
173
|
-
{ filePath: "test.ts", fileName: "test.ts", isFolder: false }
|
|
174
|
-
];
|
|
175
|
-
const result = await getFolderExports(
|
|
176
|
-
testDir,
|
|
177
|
-
mockReadFolderWithJs,
|
|
178
|
-
true,
|
|
179
|
-
["ts"]
|
|
180
|
-
);
|
|
181
|
-
assert.ok(!result.includes("test.js"));
|
|
182
|
-
assert.ok(result.includes("test.ts"));
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
describe("getExt - Attack Phase: Malformed File Names", () => {
|
|
186
|
-
it("should handle undefined filename", () => {
|
|
187
|
-
assert.strictEqual(getExt(void 0), "");
|
|
188
|
-
});
|
|
189
|
-
it("should handle empty string filename", () => {
|
|
190
|
-
assert.strictEqual(getExt(""), "");
|
|
191
|
-
});
|
|
192
|
-
it("should handle filename with no extension", () => {
|
|
193
|
-
assert.strictEqual(getExt("filename"), "");
|
|
194
|
-
});
|
|
195
|
-
it("should handle filename with multiple dots", () => {
|
|
196
|
-
assert.strictEqual(getExt("file.name.with.multiple.dots.ts"), "ts");
|
|
197
|
-
});
|
|
198
|
-
it("should handle filename starting with dot", () => {
|
|
199
|
-
assert.strictEqual(getExt(".hidden"), "hidden");
|
|
200
|
-
});
|
|
201
|
-
it("should handle filename with only dots", () => {
|
|
202
|
-
assert.strictEqual(getExt("..."), "txt");
|
|
203
|
-
});
|
|
204
|
-
it("should handle filename with path separators", () => {
|
|
205
|
-
assert.strictEqual(getExt("path/to/file.txt"), "txt");
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
describe("Path Utilities - Attack Phase: Malformed Paths", () => {
|
|
209
|
-
describe("addLeadingSlash", () => {
|
|
210
|
-
it("should handle empty string", () => {
|
|
211
|
-
assert.strictEqual(addLeadingSlash(""), "/");
|
|
212
|
-
});
|
|
213
|
-
it("should handle path with multiple leading slashes", () => {
|
|
214
|
-
assert.strictEqual(addLeadingSlash("///path"), "/path");
|
|
215
|
-
});
|
|
216
|
-
it("should handle path with backslashes", () => {
|
|
217
|
-
const result = addLeadingSlash("path\\to\\file");
|
|
218
|
-
assert.ok(result.startsWith("/"));
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
describe("removeTrialingSlashes", () => {
|
|
222
|
-
it("should handle empty string", () => {
|
|
223
|
-
assert.strictEqual(removeTrialingSlashes(""), "");
|
|
224
|
-
});
|
|
225
|
-
it("should handle string with only slashes", () => {
|
|
226
|
-
assert.strictEqual(removeTrialingSlashes("///"), "");
|
|
227
|
-
});
|
|
228
|
-
it("should preserve single slash when keepLastOne is true", () => {
|
|
229
|
-
assert.strictEqual(removeTrialingSlashes("path///", true), "path/");
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
describe("Type Guards - Attack Phase: Type Coercion Vulnerabilities", () => {
|
|
234
|
-
describe("isNullOrUndefined", () => {
|
|
235
|
-
it("should correctly identify falsy values that are not null/undefined", () => {
|
|
236
|
-
assert.strictEqual(isNullOrUndefined(0), false);
|
|
237
|
-
assert.strictEqual(isNullOrUndefined(""), false);
|
|
238
|
-
assert.strictEqual(isNullOrUndefined(false), false);
|
|
239
|
-
assert.strictEqual(isNullOrUndefined(NaN), false);
|
|
240
|
-
});
|
|
241
|
-
it("should correctly identify null and undefined", () => {
|
|
242
|
-
assert.strictEqual(isNullOrUndefined(null), true);
|
|
243
|
-
assert.strictEqual(isNullOrUndefined(void 0), true);
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
describe("type safety verification", () => {
|
|
247
|
-
it("should handle type coercion edge cases", () => {
|
|
248
|
-
const value = null;
|
|
249
|
-
if (isNullOrUndefined(value)) {
|
|
250
|
-
assert.ok(value === null || value === void 0);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
describe("State Transition Testing - File System Operations", () => {
|
|
256
|
-
it("should maintain file system consistency during complex operations", async () => {
|
|
257
|
-
const complexContent = {
|
|
258
|
-
"folder1/file1.txt": "content1",
|
|
259
|
-
"folder1/file2.txt": null,
|
|
260
|
-
// Should not be created
|
|
261
|
-
"folder2/subfolder/file3.txt": {
|
|
262
|
-
content: "content3",
|
|
263
|
-
ignoreIfExists: false
|
|
264
|
-
},
|
|
265
|
-
"folder2/existing.txt": {
|
|
266
|
-
content: "new content",
|
|
267
|
-
ignoreIfExists: true
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
await mkdir(join(testDir, "folder2"), { recursive: true });
|
|
271
|
-
await writeFile(join(testDir, "folder2/existing.txt"), "original");
|
|
272
|
-
await writeFiles(testDir, complexContent);
|
|
273
|
-
assert.strictEqual(
|
|
274
|
-
await getFile(join(testDir, "folder1/file1.txt")),
|
|
275
|
-
"content1"
|
|
276
|
-
);
|
|
277
|
-
assert.strictEqual(
|
|
278
|
-
await exist(join(testDir, "folder1/file2.txt")),
|
|
279
|
-
false
|
|
280
|
-
);
|
|
281
|
-
assert.strictEqual(
|
|
282
|
-
await getFile(join(testDir, "folder2/subfolder/file3.txt")),
|
|
283
|
-
"content3"
|
|
284
|
-
);
|
|
285
|
-
assert.strictEqual(
|
|
286
|
-
await getFile(join(testDir, "folder2/existing.txt")),
|
|
287
|
-
"original"
|
|
288
|
-
);
|
|
289
|
-
});
|
|
290
|
-
it("should maintain directory structure consistency during recursive operations", async () => {
|
|
291
|
-
const nestedDir = join(testDir, "nested/deep/structure");
|
|
292
|
-
await mkdir(nestedDir, { recursive: true });
|
|
293
|
-
await writeFile(join(nestedDir, "file.txt"), "content");
|
|
294
|
-
await writeFile(join(testDir, "nested/file2.txt"), "content2");
|
|
295
|
-
const files = await readFolder(join(testDir, "nested"), true);
|
|
296
|
-
assert.ok(files.includes("deep/structure/file.txt"));
|
|
297
|
-
assert.ok(files.includes("file2.txt"));
|
|
298
|
-
assert.strictEqual(files.filter((f) => f.startsWith("deep/")).length, 1);
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
describe("Happy Path - Basic Functionality Confirmation", () => {
|
|
302
|
-
it("should successfully read existing file", async () => {
|
|
303
|
-
const filePath = join(testDir, "test-read.txt");
|
|
304
|
-
const content = "test content";
|
|
305
|
-
await writeFile(filePath, content);
|
|
306
|
-
const result = await getFile(filePath);
|
|
307
|
-
assert.strictEqual(result, content);
|
|
308
|
-
});
|
|
309
|
-
it("should correctly identify existing files and directories", async () => {
|
|
310
|
-
const filePath = join(testDir, "test-exist-unique.txt");
|
|
311
|
-
const dirPath = join(testDir, "test-dir-unique");
|
|
312
|
-
await writeFile(filePath, "content");
|
|
313
|
-
await mkdir(dirPath);
|
|
314
|
-
assert.strictEqual(await exist(filePath), true);
|
|
315
|
-
assert.strictEqual(await exist(dirPath), true);
|
|
316
|
-
});
|
|
317
|
-
it("should read folder contents correctly", async () => {
|
|
318
|
-
const folderPath = join(testDir, "read-test");
|
|
319
|
-
await mkdir(folderPath);
|
|
320
|
-
await writeFile(join(folderPath, "file1.txt"), "content1");
|
|
321
|
-
await writeFile(join(folderPath, "file2.txt"), "content2");
|
|
322
|
-
const files = await readFolder(folderPath);
|
|
323
|
-
assert.deepStrictEqual(files.sort(), ["file1.txt", "file2.txt"]);
|
|
324
|
-
});
|
|
325
|
-
it("should write files correctly", async () => {
|
|
326
|
-
const content = {
|
|
327
|
-
"simple.txt": "simple content",
|
|
328
|
-
"complex.txt": {
|
|
329
|
-
content: "complex content",
|
|
330
|
-
ignoreIfExists: false
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
await writeFiles(testDir, content);
|
|
334
|
-
assert.strictEqual(
|
|
335
|
-
await getFile(join(testDir, "simple.txt")),
|
|
336
|
-
"simple content"
|
|
337
|
-
);
|
|
338
|
-
assert.strictEqual(
|
|
339
|
-
await getFile(join(testDir, "complex.txt")),
|
|
340
|
-
"complex content"
|
|
341
|
-
);
|
|
342
|
-
});
|
|
343
|
-
it("should extract file extensions correctly", () => {
|
|
344
|
-
assert.strictEqual(getExt("file.txt"), "txt");
|
|
345
|
-
assert.strictEqual(getExt("script.js"), "js");
|
|
346
|
-
assert.strictEqual(getExt("component.tsx"), "tsx");
|
|
347
|
-
});
|
|
348
|
-
it("should format paths correctly", () => {
|
|
349
|
-
assert.strictEqual(addLeadingSlash("path/to/file"), "/path/to/file");
|
|
350
|
-
assert.strictEqual(
|
|
351
|
-
removeTrialingSlashes("path/to/file///"),
|
|
352
|
-
"path/to/file"
|
|
353
|
-
);
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
});
|
|
357
|
-
//# sourceMappingURL=file-system.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/lib/file-system.test.ts"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert/strict';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { after, before, describe, it } from 'node:test';\n\nimport {\n type WriteContent,\n addLeadingSlash,\n exist,\n getExt,\n getFile,\n getFolderExports,\n isNullOrUndefined,\n readFolder,\n removeTrialingSlashes,\n writeFiles,\n} from './file-system.ts';\n\ndescribe('File System Utilities - Error-First Testing', () => {\n let testDir: string;\n let nonExistentPath: string;\n\n before(async () => {\n testDir = join(tmpdir(), `fs-test-${Date.now()}`);\n await mkdir(testDir, { recursive: true });\n nonExistentPath = join(testDir, 'non-existent-directory', 'deep', 'path');\n });\n\n after(async () => {\n const { rm } = await import('node:fs/promises');\n await rm(testDir, { recursive: true, force: true });\n });\n\n describe('getFile - Attack Phase: Invalid Inputs & File System Errors', () => {\n it('should return null for non-existent file', async () => {\n const result = await getFile(join(testDir, 'does-not-exist.txt'));\n assert.strictEqual(result, null);\n });\n\n it('should return null for empty string path', async () => {\n const result = await getFile('');\n assert.strictEqual(result, null);\n });\n\n it('should throw error when trying to read a directory path instead of file', async () => {\n const dirPath = join(testDir, 'test-dir-for-getfile');\n await mkdir(dirPath);\n\n await assert.rejects(() => getFile(dirPath), {\n code: 'EISDIR',\n });\n });\n\n it('should handle permission denied scenarios gracefully', async () => {\n // Test with invalid path that would cause permission errors\n const result = await getFile('/root/protected-file.txt');\n assert.strictEqual(result, null);\n });\n\n it('should handle malformed paths', async () => {\n const malformedPaths = [\n '\\0invalid',\n 'file\\nwith\\nnewlines',\n 'file\\twith\\ttabs',\n ];\n\n for (const path of malformedPaths) {\n const result = await getFile(path);\n assert.strictEqual(result, null, `Failed for path: ${path}`);\n }\n });\n });\n\n describe('exist - Attack Phase: Edge Cases & Invalid Paths', () => {\n it('should return false for non-existent paths', async () => {\n assert.strictEqual(await exist(nonExistentPath), false);\n });\n\n it('should return false for empty string', async () => {\n assert.strictEqual(await exist(''), false);\n });\n\n it('should handle null bytes in path gracefully', async () => {\n assert.strictEqual(await exist('path\\0with\\0nulls'), false);\n });\n\n it('should handle extremely long paths', async () => {\n const longPath = 'a'.repeat(10000);\n assert.strictEqual(await exist(longPath), false);\n });\n });\n\n describe('readFolder - Attack Phase: Directory Corruption & Invalid States', () => {\n it('should return empty array for non-existent directory', async () => {\n const result = await readFolder(nonExistentPath);\n assert.deepStrictEqual(result, []);\n });\n\n it('should throw error for file path instead of directory', async () => {\n const filePath = join(testDir, 'test-file-for-readfolder.txt');\n await writeFile(filePath, 'content');\n\n // readFolder should throw an error when given a file path\n await assert.rejects(() => readFolder(filePath), {\n code: 'ENOTDIR',\n });\n });\n\n it('should handle permission denied on directory', async () => {\n const result = await readFolder('/root');\n assert.deepStrictEqual(result, []);\n });\n\n it('should handle recursive reading with circular symlinks gracefully', async () => {\n // This tests the function's resilience to infinite loops\n const result = await readFolder(testDir, true);\n assert.ok(Array.isArray(result));\n });\n });\n\n describe('writeFiles - Attack Phase: Write Failures & State Corruption', () => {\n it('should handle null content gracefully', async () => {\n const content: WriteContent = {\n 'test.txt': null,\n 'valid.txt': 'content',\n };\n\n await writeFiles(testDir, content);\n\n // Verify null content file was not created\n assert.strictEqual(await exist(join(testDir, 'test.txt')), false);\n // Verify valid file was created\n assert.strictEqual(await exist(join(testDir, 'valid.txt')), true);\n });\n\n it('should fail gracefully when writing to read-only directory', async () => {\n const readOnlyPath = '/read-only-system-path';\n const content: WriteContent = {\n 'test.txt': 'content',\n };\n\n try {\n await writeFiles(readOnlyPath, content);\n assert.fail('Should have thrown an error for read-only directory');\n } catch (error) {\n assert.ok(error instanceof Error);\n }\n });\n\n it('should handle ignoreIfExists flag correctly when file exists', async () => {\n const filePath = join(testDir, 'existing.txt');\n await writeFile(filePath, 'original');\n\n const content: WriteContent = {\n 'existing.txt': {\n content: 'should not overwrite',\n ignoreIfExists: true,\n },\n };\n\n await writeFiles(testDir, content);\n const result = await getFile(filePath);\n assert.strictEqual(result, 'original');\n });\n\n it('should create deeply nested directories', async () => {\n const content: WriteContent = {\n 'deep/nested/structure/file.txt': 'content',\n };\n\n await writeFiles(testDir, content);\n const result = await getFile(\n join(testDir, 'deep/nested/structure/file.txt'),\n );\n assert.strictEqual(result, 'content');\n });\n });\n\n describe('getFolderExports - Attack Phase: Invalid Folder States', () => {\n const mockReadFolder = async (folder: string) => {\n if (folder === nonExistentPath) {\n return [];\n }\n return [\n {\n filePath: join(folder, 'valid.ts'),\n fileName: 'valid.ts',\n isFolder: false,\n },\n {\n filePath: join(folder, 'index.ts'),\n fileName: 'index.ts',\n isFolder: false,\n },\n {\n filePath: join(folder, 'subfolder'),\n fileName: 'subfolder',\n isFolder: true,\n },\n ];\n };\n\n it('should handle non-existent folder gracefully', async () => {\n const result = await getFolderExports(nonExistentPath, mockReadFolder);\n assert.strictEqual(result, '');\n });\n\n it('should ignore files with unsupported extensions', async () => {\n const mockReadFolderWithJs = async () => [\n { filePath: 'test.js', fileName: 'test.js', isFolder: false },\n { filePath: 'test.ts', fileName: 'test.ts', isFolder: false },\n ];\n\n const result = await getFolderExports(\n testDir,\n mockReadFolderWithJs,\n true,\n ['ts'],\n );\n assert.ok(!result.includes('test.js'));\n assert.ok(result.includes('test.ts'));\n });\n });\n\n describe('getExt - Attack Phase: Malformed File Names', () => {\n it('should handle undefined filename', () => {\n assert.strictEqual(getExt(undefined), '');\n });\n\n it('should handle empty string filename', () => {\n assert.strictEqual(getExt(''), '');\n });\n\n it('should handle filename with no extension', () => {\n assert.strictEqual(getExt('filename'), '');\n });\n\n it('should handle filename with multiple dots', () => {\n assert.strictEqual(getExt('file.name.with.multiple.dots.ts'), 'ts');\n });\n\n it('should handle filename starting with dot', () => {\n // Based on the actual implementation, '.hidden' should return 'hidden'\n assert.strictEqual(getExt('.hidden'), 'hidden');\n });\n\n it('should handle filename with only dots', () => {\n // Based on the actual implementation, '...' returns 'txt' as fallback\n assert.strictEqual(getExt('...'), 'txt');\n });\n\n it('should handle filename with path separators', () => {\n assert.strictEqual(getExt('path/to/file.txt'), 'txt');\n });\n });\n\n describe('Path Utilities - Attack Phase: Malformed Paths', () => {\n describe('addLeadingSlash', () => {\n it('should handle empty string', () => {\n assert.strictEqual(addLeadingSlash(''), '/');\n });\n\n it('should handle path with multiple leading slashes', () => {\n assert.strictEqual(addLeadingSlash('///path'), '/path');\n });\n\n it('should handle path with backslashes', () => {\n const result = addLeadingSlash('path\\\\to\\\\file');\n assert.ok(result.startsWith('/'));\n });\n });\n\n describe('removeTrialingSlashes', () => {\n it('should handle empty string', () => {\n assert.strictEqual(removeTrialingSlashes(''), '');\n });\n\n it('should handle string with only slashes', () => {\n assert.strictEqual(removeTrialingSlashes('///'), '');\n });\n\n it('should preserve single slash when keepLastOne is true', () => {\n assert.strictEqual(removeTrialingSlashes('path///', true), 'path/');\n });\n });\n });\n\n describe('Type Guards - Attack Phase: Type Coercion Vulnerabilities', () => {\n describe('isNullOrUndefined', () => {\n it('should correctly identify falsy values that are not null/undefined', () => {\n assert.strictEqual(isNullOrUndefined(0), false);\n assert.strictEqual(isNullOrUndefined(''), false);\n assert.strictEqual(isNullOrUndefined(false), false);\n assert.strictEqual(isNullOrUndefined(NaN), false);\n });\n\n it('should correctly identify null and undefined', () => {\n assert.strictEqual(isNullOrUndefined(null), true);\n assert.strictEqual(isNullOrUndefined(undefined), true);\n });\n });\n\n // Remove notNullOrUndefined tests since it doesn't exist in the source\n describe('type safety verification', () => {\n it('should handle type coercion edge cases', () => {\n // Test that isNullOrUndefined works as a proper type guard\n const value: unknown = null;\n if (isNullOrUndefined(value)) {\n // TypeScript should narrow the type here\n assert.ok(value === null || value === undefined);\n }\n });\n });\n });\n\n describe('State Transition Testing - File System Operations', () => {\n it('should maintain file system consistency during complex operations', async () => {\n const complexContent: WriteContent = {\n 'folder1/file1.txt': 'content1',\n 'folder1/file2.txt': null, // Should not be created\n 'folder2/subfolder/file3.txt': {\n content: 'content3',\n ignoreIfExists: false,\n },\n 'folder2/existing.txt': {\n content: 'new content',\n ignoreIfExists: true,\n },\n };\n\n // Pre-create existing file\n await mkdir(join(testDir, 'folder2'), { recursive: true });\n await writeFile(join(testDir, 'folder2/existing.txt'), 'original');\n\n await writeFiles(testDir, complexContent);\n\n // Verify final state\n assert.strictEqual(\n await getFile(join(testDir, 'folder1/file1.txt')),\n 'content1',\n );\n assert.strictEqual(\n await exist(join(testDir, 'folder1/file2.txt')),\n false,\n );\n assert.strictEqual(\n await getFile(join(testDir, 'folder2/subfolder/file3.txt')),\n 'content3',\n );\n assert.strictEqual(\n await getFile(join(testDir, 'folder2/existing.txt')),\n 'original',\n );\n });\n\n it('should maintain directory structure consistency during recursive operations', async () => {\n // Create nested structure\n const nestedDir = join(testDir, 'nested/deep/structure');\n await mkdir(nestedDir, { recursive: true });\n await writeFile(join(nestedDir, 'file.txt'), 'content');\n await writeFile(join(testDir, 'nested/file2.txt'), 'content2');\n\n const files = await readFolder(join(testDir, 'nested'), true);\n\n // Verify structure is maintained\n assert.ok(files.includes('deep/structure/file.txt'));\n assert.ok(files.includes('file2.txt'));\n assert.strictEqual(files.filter((f) => f.startsWith('deep/')).length, 1);\n });\n });\n\n describe('Happy Path - Basic Functionality Confirmation', () => {\n it('should successfully read existing file', async () => {\n const filePath = join(testDir, 'test-read.txt');\n const content = 'test content';\n await writeFile(filePath, content);\n\n const result = await getFile(filePath);\n assert.strictEqual(result, content);\n });\n\n it('should correctly identify existing files and directories', async () => {\n const filePath = join(testDir, 'test-exist-unique.txt');\n const dirPath = join(testDir, 'test-dir-unique');\n\n await writeFile(filePath, 'content');\n await mkdir(dirPath);\n\n assert.strictEqual(await exist(filePath), true);\n assert.strictEqual(await exist(dirPath), true);\n });\n\n it('should read folder contents correctly', async () => {\n const folderPath = join(testDir, 'read-test');\n await mkdir(folderPath);\n await writeFile(join(folderPath, 'file1.txt'), 'content1');\n await writeFile(join(folderPath, 'file2.txt'), 'content2');\n\n const files = await readFolder(folderPath);\n assert.deepStrictEqual(files.sort(), ['file1.txt', 'file2.txt']);\n });\n\n it('should write files correctly', async () => {\n const content: WriteContent = {\n 'simple.txt': 'simple content',\n 'complex.txt': {\n content: 'complex content',\n ignoreIfExists: false,\n },\n };\n\n await writeFiles(testDir, content);\n\n assert.strictEqual(\n await getFile(join(testDir, 'simple.txt')),\n 'simple content',\n );\n assert.strictEqual(\n await getFile(join(testDir, 'complex.txt')),\n 'complex content',\n );\n });\n\n it('should extract file extensions correctly', () => {\n assert.strictEqual(getExt('file.txt'), 'txt');\n assert.strictEqual(getExt('script.js'), 'js');\n assert.strictEqual(getExt('component.tsx'), 'tsx');\n });\n\n it('should format paths correctly', () => {\n assert.strictEqual(addLeadingSlash('path/to/file'), '/path/to/file');\n assert.strictEqual(\n removeTrialingSlashes('path/to/file///'),\n 'path/to/file',\n );\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"program.test.d.ts","sourceRoot":"","sources":["../../src/lib/program.test.ts"],"names":[],"mappings":""}
|
package/dist/lib/program.test.js
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from "node:assert";
|
|
2
|
-
import { describe, it } from "node:test";
|
|
3
|
-
import ts from "typescript";
|
|
4
|
-
import { isInterfaceType } from "./program.ts";
|
|
5
|
-
describe("isInterfaceType Helper Function - Error-First Testing", () => {
|
|
6
|
-
describe("Error Cases and Invalid Inputs", () => {
|
|
7
|
-
it("throws TypeError when type.symbol is undefined", () => {
|
|
8
|
-
const mockType = {
|
|
9
|
-
isClassOrInterface: () => true,
|
|
10
|
-
symbol: void 0
|
|
11
|
-
};
|
|
12
|
-
assert.throws(
|
|
13
|
-
() => {
|
|
14
|
-
isInterfaceType(mockType);
|
|
15
|
-
},
|
|
16
|
-
TypeError,
|
|
17
|
-
"Should throw TypeError when accessing flags on undefined symbol"
|
|
18
|
-
);
|
|
19
|
-
});
|
|
20
|
-
it("throws TypeError when type.symbol is null", () => {
|
|
21
|
-
const mockType = {
|
|
22
|
-
isClassOrInterface: () => true,
|
|
23
|
-
symbol: null
|
|
24
|
-
};
|
|
25
|
-
assert.throws(
|
|
26
|
-
() => {
|
|
27
|
-
isInterfaceType(mockType);
|
|
28
|
-
},
|
|
29
|
-
TypeError,
|
|
30
|
-
"Should throw TypeError when accessing flags on null symbol"
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
it("handles malformed type object missing isClassOrInterface method", () => {
|
|
34
|
-
const mockType = {
|
|
35
|
-
// Missing isClassOrInterface method
|
|
36
|
-
symbol: {
|
|
37
|
-
flags: ts.SymbolFlags.Interface
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
assert.throws(
|
|
41
|
-
() => {
|
|
42
|
-
isInterfaceType(mockType);
|
|
43
|
-
},
|
|
44
|
-
TypeError,
|
|
45
|
-
"Should throw when isClassOrInterface is not a function"
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
it("handles type with symbol missing flags property", () => {
|
|
49
|
-
const mockType = {
|
|
50
|
-
isClassOrInterface: () => true,
|
|
51
|
-
symbol: {}
|
|
52
|
-
// Missing flags property
|
|
53
|
-
};
|
|
54
|
-
const result = isInterfaceType(mockType);
|
|
55
|
-
assert.strictEqual(
|
|
56
|
-
result,
|
|
57
|
-
false,
|
|
58
|
-
"Should return false when flags property is missing"
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
it("handles type with symbol having non-numeric flags", () => {
|
|
62
|
-
const mockType = {
|
|
63
|
-
isClassOrInterface: () => true,
|
|
64
|
-
symbol: {
|
|
65
|
-
flags: "invalid"
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
const result = isInterfaceType(mockType);
|
|
69
|
-
assert.strictEqual(
|
|
70
|
-
result,
|
|
71
|
-
false,
|
|
72
|
-
"Should return false when flags is not a number"
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
describe("System Invariants", () => {
|
|
77
|
-
it("INVARIANT: Interface flag must be present for true result", () => {
|
|
78
|
-
const interfaceType = {
|
|
79
|
-
isClassOrInterface: () => true,
|
|
80
|
-
symbol: {
|
|
81
|
-
flags: ts.SymbolFlags.Interface
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
const result = isInterfaceType(interfaceType);
|
|
85
|
-
assert.strictEqual(
|
|
86
|
-
result,
|
|
87
|
-
true,
|
|
88
|
-
"INVARIANT VIOLATED: Interface flag present but function returned false"
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
it("INVARIANT: Non-interface flags must result in false", () => {
|
|
92
|
-
const nonInterfaceFlags = [
|
|
93
|
-
ts.SymbolFlags.Class,
|
|
94
|
-
ts.SymbolFlags.Function,
|
|
95
|
-
ts.SymbolFlags.Variable,
|
|
96
|
-
ts.SymbolFlags.Property,
|
|
97
|
-
ts.SymbolFlags.Enum,
|
|
98
|
-
ts.SymbolFlags.Module,
|
|
99
|
-
ts.SymbolFlags.Namespace
|
|
100
|
-
// Removed TypeAliasExcludes which seems to have the Interface bit
|
|
101
|
-
];
|
|
102
|
-
nonInterfaceFlags.forEach((flag) => {
|
|
103
|
-
const mockType = {
|
|
104
|
-
isClassOrInterface: () => true,
|
|
105
|
-
symbol: {
|
|
106
|
-
flags: flag
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
const result = isInterfaceType(mockType);
|
|
110
|
-
assert.strictEqual(
|
|
111
|
-
result,
|
|
112
|
-
false,
|
|
113
|
-
`INVARIANT VIOLATED: Non-interface flag ${ts.SymbolFlags[flag]} (${flag}) returned true`
|
|
114
|
-
);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
it("INVARIANT: isClassOrInterface() false must always result in false", () => {
|
|
118
|
-
const mockType = {
|
|
119
|
-
isClassOrInterface: () => false,
|
|
120
|
-
symbol: {
|
|
121
|
-
flags: ts.SymbolFlags.Interface
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
const result = isInterfaceType(mockType);
|
|
125
|
-
assert.strictEqual(
|
|
126
|
-
result,
|
|
127
|
-
false,
|
|
128
|
-
"INVARIANT VIOLATED: isClassOrInterface() false should always result in false"
|
|
129
|
-
);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
describe("Complex Flag Combinations", () => {
|
|
133
|
-
it("correctly handles combined flags including Interface", () => {
|
|
134
|
-
const combinedFlags = [
|
|
135
|
-
ts.SymbolFlags.Interface | ts.SymbolFlags.Type,
|
|
136
|
-
ts.SymbolFlags.Interface | ts.SymbolFlags.Alias,
|
|
137
|
-
ts.SymbolFlags.Interface | ts.SymbolFlags.Class,
|
|
138
|
-
// Edge case
|
|
139
|
-
ts.SymbolFlags.Interface | ts.SymbolFlags.Function
|
|
140
|
-
];
|
|
141
|
-
combinedFlags.forEach((flags, index) => {
|
|
142
|
-
const mockType = {
|
|
143
|
-
isClassOrInterface: () => true,
|
|
144
|
-
symbol: { flags }
|
|
145
|
-
};
|
|
146
|
-
const result = isInterfaceType(mockType);
|
|
147
|
-
assert.strictEqual(
|
|
148
|
-
result,
|
|
149
|
-
true,
|
|
150
|
-
`Combined flags case ${index + 1}: Interface flag present, should return true`
|
|
151
|
-
);
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
it("correctly handles combined flags excluding Interface", () => {
|
|
155
|
-
const combinedFlagsNoInterface = [
|
|
156
|
-
ts.SymbolFlags.Function | ts.SymbolFlags.Variable,
|
|
157
|
-
ts.SymbolFlags.Enum | ts.SymbolFlags.Module
|
|
158
|
-
// Removed Class | Type which seems to include the Interface bit
|
|
159
|
-
];
|
|
160
|
-
combinedFlagsNoInterface.forEach((flags, index) => {
|
|
161
|
-
if ((flags & ts.SymbolFlags.Interface) !== 0) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const mockType = {
|
|
165
|
-
isClassOrInterface: () => true,
|
|
166
|
-
symbol: { flags }
|
|
167
|
-
};
|
|
168
|
-
const result = isInterfaceType(mockType);
|
|
169
|
-
assert.strictEqual(
|
|
170
|
-
result,
|
|
171
|
-
false,
|
|
172
|
-
`Combined flags case ${index + 1}: No Interface flag, should return false`
|
|
173
|
-
);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
it("handles edge case with maximum flag value", () => {
|
|
177
|
-
const mockType = {
|
|
178
|
-
isClassOrInterface: () => true,
|
|
179
|
-
symbol: {
|
|
180
|
-
flags: Number.MAX_SAFE_INTEGER
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
const hasInterfaceFlag = (Number.MAX_SAFE_INTEGER & ts.SymbolFlags.Interface) !== 0;
|
|
184
|
-
const result = isInterfaceType(mockType);
|
|
185
|
-
assert.strictEqual(
|
|
186
|
-
result,
|
|
187
|
-
hasInterfaceFlag,
|
|
188
|
-
"Edge case with maximum flag value should follow bitwise logic"
|
|
189
|
-
);
|
|
190
|
-
});
|
|
191
|
-
it("handles zero flags correctly", () => {
|
|
192
|
-
const mockType = {
|
|
193
|
-
isClassOrInterface: () => true,
|
|
194
|
-
symbol: {
|
|
195
|
-
flags: 0
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
const result = isInterfaceType(mockType);
|
|
199
|
-
assert.strictEqual(result, false, "Zero flags should result in false");
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
describe("Boundary Conditions", () => {
|
|
203
|
-
it("tests exact Interface flag value", () => {
|
|
204
|
-
const mockType = {
|
|
205
|
-
isClassOrInterface: () => true,
|
|
206
|
-
symbol: {
|
|
207
|
-
flags: ts.SymbolFlags.Interface
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
const result = isInterfaceType(mockType);
|
|
211
|
-
assert.strictEqual(
|
|
212
|
-
result,
|
|
213
|
-
true,
|
|
214
|
-
"Exact Interface flag should return true"
|
|
215
|
-
);
|
|
216
|
-
});
|
|
217
|
-
it("tests Interface flag minus one", () => {
|
|
218
|
-
const mockType = {
|
|
219
|
-
isClassOrInterface: () => true,
|
|
220
|
-
symbol: {
|
|
221
|
-
flags: ts.SymbolFlags.Interface - 1
|
|
222
|
-
}
|
|
223
|
-
};
|
|
224
|
-
const result = isInterfaceType(mockType);
|
|
225
|
-
assert.strictEqual(
|
|
226
|
-
result,
|
|
227
|
-
false,
|
|
228
|
-
"Interface flag minus one should not match"
|
|
229
|
-
);
|
|
230
|
-
});
|
|
231
|
-
it("tests Interface flag plus one", () => {
|
|
232
|
-
const flagValue = ts.SymbolFlags.Interface + 1;
|
|
233
|
-
const mockType = {
|
|
234
|
-
isClassOrInterface: () => true,
|
|
235
|
-
symbol: {
|
|
236
|
-
flags: flagValue
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
const hasInterfaceFlag = (flagValue & ts.SymbolFlags.Interface) !== 0;
|
|
240
|
-
const result = isInterfaceType(mockType);
|
|
241
|
-
assert.strictEqual(
|
|
242
|
-
result,
|
|
243
|
-
hasInterfaceFlag,
|
|
244
|
-
"Interface flag plus one should follow bitwise logic"
|
|
245
|
-
);
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
describe("Happy Path Scenarios", () => {
|
|
249
|
-
it("correctly identifies interface types", () => {
|
|
250
|
-
const mockType = {
|
|
251
|
-
isClassOrInterface: () => true,
|
|
252
|
-
symbol: {
|
|
253
|
-
flags: ts.SymbolFlags.Interface
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
const result = isInterfaceType(mockType);
|
|
257
|
-
assert.strictEqual(
|
|
258
|
-
result,
|
|
259
|
-
true,
|
|
260
|
-
"Should correctly identify interface types"
|
|
261
|
-
);
|
|
262
|
-
});
|
|
263
|
-
it("correctly rejects class types", () => {
|
|
264
|
-
const mockType = {
|
|
265
|
-
isClassOrInterface: () => true,
|
|
266
|
-
symbol: {
|
|
267
|
-
flags: ts.SymbolFlags.Class
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
const result = isInterfaceType(mockType);
|
|
271
|
-
assert.strictEqual(result, false, "Should correctly reject class types");
|
|
272
|
-
});
|
|
273
|
-
it("correctly rejects primitive types", () => {
|
|
274
|
-
const mockType = {
|
|
275
|
-
isClassOrInterface: () => false,
|
|
276
|
-
symbol: {
|
|
277
|
-
flags: ts.SymbolFlags.None
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
const result = isInterfaceType(mockType);
|
|
281
|
-
assert.strictEqual(
|
|
282
|
-
result,
|
|
283
|
-
false,
|
|
284
|
-
"Should correctly reject primitive types"
|
|
285
|
-
);
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
|
-
//# sourceMappingURL=program.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/lib/program.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { strict as assert } from 'node:assert';\nimport { describe, it } from 'node:test';\nimport ts from 'typescript';\n\nimport { isInterfaceType } from './program.ts';\n\ndescribe('isInterfaceType Helper Function - Error-First Testing', () => {\n // Phase 1: Error-First Testing - Attack Before You Defend\n describe('Error Cases and Invalid Inputs', () => {\n it('throws TypeError when type.symbol is undefined', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: undefined,\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw TypeError when accessing flags on undefined symbol',\n );\n });\n\n it('throws TypeError when type.symbol is null', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: null,\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw TypeError when accessing flags on null symbol',\n );\n });\n\n it('handles malformed type object missing isClassOrInterface method', () => {\n const mockType = {\n // Missing isClassOrInterface method\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw when isClassOrInterface is not a function',\n );\n });\n\n it('handles type with symbol missing flags property', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {}, // Missing flags property\n } as unknown as ts.Type;\n\n // Should default to falsy flags (undefined & Interface === 0)\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should return false when flags property is missing',\n );\n });\n\n it('handles type with symbol having non-numeric flags', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: 'invalid' as unknown,\n },\n } as unknown as ts.Type;\n\n // Bitwise AND with string should result in 0 (falsy)\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should return false when flags is not a number',\n );\n });\n });\n\n // Phase 2: System Invariants Testing\n describe('System Invariants', () => {\n it('INVARIANT: Interface flag must be present for true result', () => {\n // Test that ONLY when Interface flag is present, result is true\n const interfaceType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(interfaceType);\n assert.strictEqual(\n result,\n true,\n 'INVARIANT VIOLATED: Interface flag present but function returned false',\n );\n });\n\n it('INVARIANT: Non-interface flags must result in false', () => {\n // Select a set of flags that are clearly not interface flags\n const nonInterfaceFlags = [\n ts.SymbolFlags.Class,\n ts.SymbolFlags.Function,\n ts.SymbolFlags.Variable,\n ts.SymbolFlags.Property,\n ts.SymbolFlags.Enum,\n ts.SymbolFlags.Module,\n ts.SymbolFlags.Namespace,\n // Removed TypeAliasExcludes which seems to have the Interface bit\n ];\n\n nonInterfaceFlags.forEach((flag) => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: flag,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n `INVARIANT VIOLATED: Non-interface flag ${ts.SymbolFlags[flag]} (${flag}) returned true`,\n );\n });\n });\n\n it('INVARIANT: isClassOrInterface() false must always result in false', () => {\n // Even with Interface flag, if isClassOrInterface is false, result must be false\n const mockType = {\n isClassOrInterface: () => false,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'INVARIANT VIOLATED: isClassOrInterface() false should always result in false',\n );\n });\n });\n\n // Phase 3: State Transitions and Complex Scenarios\n describe('Complex Flag Combinations', () => {\n it('correctly handles combined flags including Interface', () => {\n const combinedFlags = [\n ts.SymbolFlags.Interface | ts.SymbolFlags.Type,\n ts.SymbolFlags.Interface | ts.SymbolFlags.Alias,\n ts.SymbolFlags.Interface | ts.SymbolFlags.Class, // Edge case\n ts.SymbolFlags.Interface | ts.SymbolFlags.Function,\n ];\n\n combinedFlags.forEach((flags, index) => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: { flags },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n `Combined flags case ${index + 1}: Interface flag present, should return true`,\n );\n });\n });\n\n it('correctly handles combined flags excluding Interface', () => {\n const combinedFlagsNoInterface = [\n ts.SymbolFlags.Function | ts.SymbolFlags.Variable,\n ts.SymbolFlags.Enum | ts.SymbolFlags.Module,\n // Removed Class | Type which seems to include the Interface bit\n ];\n\n combinedFlagsNoInterface.forEach((flags, index) => {\n // Explicitly check that the flags don't include the Interface bit\n if ((flags & ts.SymbolFlags.Interface) !== 0) {\n // Skip this test case if it includes the Interface bit\n return;\n }\n\n const mockType = {\n isClassOrInterface: () => true,\n symbol: { flags },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n `Combined flags case ${index + 1}: No Interface flag, should return false`,\n );\n });\n });\n\n it('handles edge case with maximum flag value', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: Number.MAX_SAFE_INTEGER,\n },\n } as unknown as ts.Type;\n\n // If Interface flag bit is set in MAX_SAFE_INTEGER, result should be true\n const hasInterfaceFlag =\n (Number.MAX_SAFE_INTEGER & ts.SymbolFlags.Interface) !== 0;\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n hasInterfaceFlag,\n 'Edge case with maximum flag value should follow bitwise logic',\n );\n });\n\n it('handles zero flags correctly', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: 0,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(result, false, 'Zero flags should result in false');\n });\n });\n\n // Phase 4: Boundary Testing\n describe('Boundary Conditions', () => {\n it('tests exact Interface flag value', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n 'Exact Interface flag should return true',\n );\n });\n\n it('tests Interface flag minus one', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface - 1,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Interface flag minus one should not match',\n );\n });\n\n it('tests Interface flag plus one', () => {\n const flagValue = ts.SymbolFlags.Interface + 1;\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: flagValue,\n },\n } as unknown as ts.Type;\n\n // Depends on whether the +1 creates a different valid flag\n const hasInterfaceFlag = (flagValue & ts.SymbolFlags.Interface) !== 0;\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n hasInterfaceFlag,\n 'Interface flag plus one should follow bitwise logic',\n );\n });\n });\n\n // Phase 5: Happy Path Tests (Last)\n describe('Happy Path Scenarios', () => {\n it('correctly identifies interface types', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n 'Should correctly identify interface types',\n );\n });\n\n it('correctly rejects class types', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Class,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(result, false, 'Should correctly reject class types');\n });\n\n it('correctly rejects primitive types', () => {\n const mockType = {\n isClassOrInterface: () => false,\n symbol: {\n flags: ts.SymbolFlags.None,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should correctly reject primitive types',\n );\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|