testgen-ts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateMockFile = generateMockFile;
37
+ exports.getMocksForType = getMocksForType;
38
+ exports.getMocksForReturnType = getMocksForReturnType;
39
+ exports.buildMockArgSets = buildMockArgSets;
40
+ exports.getAllMockData = getAllMockData;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const formatter_1 = require("./formatter");
44
+ const utils_1 = require("./utils");
45
+ /**
46
+ * Generate a mock file that mirrors the source file path.
47
+ *
48
+ * Produces `testgen/mocks/<mirror>/file.mock.ts` containing exported
49
+ * constants with structured mock data for every analysed function.
50
+ */
51
+ async function generateMockFile(srcFilePath, scenarios, projectRoot, srcDir, mockDir) {
52
+ if (scenarios.length === 0)
53
+ return null;
54
+ const mockFilePath = (0, utils_1.mirrorPath)(srcFilePath, srcDir, path.join(projectRoot, mockDir), ".mock.ts");
55
+ const constantNames = new Map();
56
+ const lines = [];
57
+ // Header comment
58
+ const relSrc = path.relative(projectRoot, srcFilePath).replace(/\\/g, "/");
59
+ lines.push(`// Auto-generated mock data for ${relSrc}`);
60
+ lines.push(`// Do not edit — regenerated on each source change.`);
61
+ lines.push("");
62
+ for (const scenario of scenarios) {
63
+ const fnName = scenario.className
64
+ ? `${scenario.className}_${scenario.functionName}`
65
+ : scenario.functionName;
66
+ const constName = `${fnName}Mocks`;
67
+ constantNames.set(scenario.functionName, constName);
68
+ lines.push(`export const ${constName} = {`);
69
+ for (const c of scenario.cases) {
70
+ const key = camelCase(c.label);
71
+ if (c.paramNames.length === 0) {
72
+ lines.push(` ${key}: {},`);
73
+ }
74
+ else {
75
+ const props = c.paramNames
76
+ .map((name, i) => `${name}: ${c.argLiterals[i] ?? "undefined"}`)
77
+ .join(", ");
78
+ lines.push(` ${key}: { ${props} },`);
79
+ }
80
+ }
81
+ lines.push("};");
82
+ lines.push("");
83
+ }
84
+ const formatted = await (0, formatter_1.formatCode)(lines.join("\n"), projectRoot);
85
+ (0, utils_1.ensureDir)(path.dirname(mockFilePath));
86
+ fs.writeFileSync(mockFilePath, formatted, "utf-8");
87
+ (0, utils_1.log)(`Mock file → ${path.relative(projectRoot, mockFilePath)}`, "success");
88
+ return { filePath: mockFilePath, constantNames };
89
+ }
90
+ /**
91
+ * Convert a scenario label like "handles positive numbers" → "handlesPositiveNumbers"
92
+ */
93
+ function camelCase(label) {
94
+ return label
95
+ .replace(/[^a-zA-Z0-9 ]/g, "")
96
+ .split(/\s+/)
97
+ .map((word, i) => i === 0
98
+ ? word.toLowerCase()
99
+ : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
100
+ .join("");
101
+ }
102
+ // ─── Number Mocks ────────────────────────────────────────────────────────────
103
+ const NUMBER_MOCKS = [
104
+ { label: "typical value", literal: "100" },
105
+ { label: "negative value", literal: "-50" },
106
+ { label: "zero", literal: "0" },
107
+ { label: "boundary value", literal: "Number.MAX_SAFE_INTEGER" },
108
+ ];
109
+ // ─── String Mocks ────────────────────────────────────────────────────────────
110
+ const STRING_MOCKS = [
111
+ { label: "valid input", literal: "'John Doe'" },
112
+ { label: "empty string", literal: "''" },
113
+ { label: "special characters", literal: "'O\\'Brien & Sons <LLC>'" },
114
+ { label: "whitespace-only input", literal: "' '" },
115
+ ];
116
+ // ─── Boolean Mocks ───────────────────────────────────────────────────────────
117
+ const BOOLEAN_MOCKS = [
118
+ { label: "truthy condition", literal: "true" },
119
+ { label: "falsy condition", literal: "false" },
120
+ ];
121
+ // ─── Array Mocks ─────────────────────────────────────────────────────────────
122
+ const ARRAY_MOCKS = [
123
+ { label: "empty collection", literal: "[]" },
124
+ { label: "single item", literal: "['item-1']" },
125
+ { label: "multiple items", literal: "['alpha', 'beta', 'gamma']" },
126
+ ];
127
+ // ─── Object Mocks ────────────────────────────────────────────────────────────
128
+ const OBJECT_MOCKS = [
129
+ { label: "empty object", literal: "{}" },
130
+ { label: "populated object", literal: "{ id: 1, name: 'Test Item', active: true }" },
131
+ ];
132
+ // ─── Date Mocks ──────────────────────────────────────────────────────────────
133
+ const DATE_MOCKS = [
134
+ { label: "current timestamp", literal: "new Date()" },
135
+ { label: "fixed date", literal: "new Date('2025-06-15T10:30:00Z')" },
136
+ ];
137
+ // ─── Null / Undefined Mocks ──────────────────────────────────────────────────
138
+ const NULLABLE_MOCKS = [
139
+ { label: "null input", literal: "null" },
140
+ { label: "undefined input", literal: "undefined" },
141
+ ];
142
+ // ─── Default / Unknown Mocks ─────────────────────────────────────────────────
143
+ const DEFAULT_MOCKS = [
144
+ { label: "default case", literal: "{} as any" },
145
+ ];
146
+ /**
147
+ * Get mock values for a parameter type.
148
+ * For custom interfaces/types, attempts to resolve properties and
149
+ * build a structured mock object.
150
+ */
151
+ function getMocksForType(typeStr) {
152
+ const t = normalise(typeStr);
153
+ if (t === "number")
154
+ return NUMBER_MOCKS;
155
+ if (t === "string")
156
+ return STRING_MOCKS;
157
+ if (t === "boolean")
158
+ return BOOLEAN_MOCKS;
159
+ if (t === "date")
160
+ return DATE_MOCKS;
161
+ if (t.endsWith("[]") || t.startsWith("array"))
162
+ return ARRAY_MOCKS;
163
+ if (t === "object" || t === "record")
164
+ return OBJECT_MOCKS;
165
+ if (t.includes("null") || t.includes("undefined"))
166
+ return [...getMocksForBaseOfUnion(t), ...NULLABLE_MOCKS];
167
+ // Try to generate a structured mock for custom/interface types
168
+ const interfaceMock = resolveInterfaceMock(typeStr);
169
+ if (interfaceMock)
170
+ return interfaceMock;
171
+ return DEFAULT_MOCKS;
172
+ }
173
+ /**
174
+ * Attempt to build realistic mock values for a custom type/interface.
175
+ * Uses heuristics based on property names and types to generate
176
+ * values that look like what a real developer would write.
177
+ */
178
+ function resolveInterfaceMock(typeStr) {
179
+ // Extract the base type name (remove generics, imports prefix)
180
+ const baseName = typeStr
181
+ .replace(/^import\([^)]+\)\./, "") // strip import("...").
182
+ .replace(/<.+>$/, "") // strip generics
183
+ .trim();
184
+ // Skip if it looks like a primitive or built-in
185
+ if (/^(string|number|boolean|void|any|never|unknown|undefined|null|object|record|date)$/i.test(baseName)) {
186
+ return null;
187
+ }
188
+ // Build a realistic mock object based on the type name
189
+ const mockObj = buildSmartMockForTypeName(baseName);
190
+ return [
191
+ { label: `valid ${baseName.toLowerCase()}`, literal: mockObj },
192
+ { label: `minimal ${baseName.toLowerCase()}`, literal: buildMinimalMock(baseName) },
193
+ ];
194
+ }
195
+ /**
196
+ * Generate a realistic mock object literal based on common type name patterns.
197
+ */
198
+ function buildSmartMockForTypeName(typeName) {
199
+ const lower = typeName.toLowerCase();
200
+ // User / Account / Profile patterns
201
+ if (lower.includes("user") || lower.includes("account") || lower.includes("profile")) {
202
+ return "{ id: 1, name: 'John Doe', email: 'john@example.com', active: true }";
203
+ }
204
+ // Product / Item patterns
205
+ if (lower.includes("product") || lower.includes("item")) {
206
+ return "{ id: 1, name: 'Test Product', price: 29.99, inStock: true }";
207
+ }
208
+ // Order / Invoice patterns
209
+ if (lower.includes("order") || lower.includes("invoice")) {
210
+ return "{ id: 1, total: 99.99, status: 'pending', createdAt: new Date('2025-01-15') }";
211
+ }
212
+ // Config / Settings / Options patterns
213
+ if (lower.includes("config") || lower.includes("settings") || lower.includes("options")) {
214
+ return "{ enabled: true, timeout: 5000, retries: 3 }";
215
+ }
216
+ // Request / Response / Payload patterns
217
+ if (lower.includes("request") || lower.includes("payload")) {
218
+ return "{ body: {}, headers: { 'Content-Type': 'application/json' }, method: 'GET' }";
219
+ }
220
+ if (lower.includes("response")) {
221
+ return "{ status: 200, data: {}, message: 'OK' }";
222
+ }
223
+ // Event / Message / Notification patterns
224
+ if (lower.includes("event") || lower.includes("message") || lower.includes("notification")) {
225
+ return "{ type: 'test', payload: {}, timestamp: new Date() }";
226
+ }
227
+ // Error / Exception patterns
228
+ if (lower.includes("error") || lower.includes("exception")) {
229
+ return "{ code: 'ERR_TEST', message: 'Test error', stack: '' }";
230
+ }
231
+ // Default: generic object with id and name
232
+ return `{ id: 1, name: 'Test ${typeName}' } as any`;
233
+ }
234
+ function buildMinimalMock(typeName) {
235
+ return `{} as any /* minimal ${typeName} */`;
236
+ }
237
+ /**
238
+ * Get mocks specifically for the return type — used for boolean return assertion hints.
239
+ */
240
+ function getMocksForReturnType(typeStr) {
241
+ const t = normalise(typeStr);
242
+ if (t === "boolean")
243
+ return BOOLEAN_MOCKS;
244
+ return [];
245
+ }
246
+ /**
247
+ * Build all mock arg sets for a function.
248
+ *
249
+ * Strategy: for each parameter, pick the mock values for its type.
250
+ * We iterate through the mocks in a "zip-longest" fashion so each
251
+ * scenario gets a unique combination where possible.
252
+ */
253
+ function buildMockArgSets(params) {
254
+ if (params.length === 0) {
255
+ return [{ scenarioLabel: "handles default case", args: [] }];
256
+ }
257
+ const mocksPerParam = params.map((p) => getMocksForType(p.type));
258
+ const maxLen = Math.max(...mocksPerParam.map((m) => m.length));
259
+ const result = [];
260
+ for (let i = 0; i < maxLen; i++) {
261
+ const args = mocksPerParam.map((mocks) => {
262
+ const idx = Math.min(i, mocks.length - 1);
263
+ return mocks[idx];
264
+ });
265
+ // Build label from the first param's mock label (since it drives the scenario name)
266
+ const primaryLabel = args[0].label;
267
+ result.push({
268
+ scenarioLabel: `handles ${primaryLabel}`,
269
+ args,
270
+ });
271
+ }
272
+ return result;
273
+ }
274
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
275
+ function normalise(typeStr) {
276
+ let t = typeStr.trim().toLowerCase();
277
+ // Unwrap Promise<T>
278
+ const promiseMatch = t.match(/^promise<(.+)>$/);
279
+ if (promiseMatch)
280
+ t = promiseMatch[1].trim();
281
+ return t;
282
+ }
283
+ function getMocksForBaseOfUnion(typeStr) {
284
+ // e.g. "string | null" → get mocks for "string"
285
+ const parts = typeStr.split("|").map((s) => s.trim()).filter((s) => s !== "null" && s !== "undefined");
286
+ if (parts.length > 0)
287
+ return getMocksForType(parts[0]);
288
+ return DEFAULT_MOCKS;
289
+ }
290
+ /**
291
+ * Get all available mock data as a structured map — used to generate
292
+ * the testgen/mocks/mockData.ts reusable constants file.
293
+ */
294
+ function getAllMockData() {
295
+ return {
296
+ number: NUMBER_MOCKS,
297
+ string: STRING_MOCKS,
298
+ boolean: BOOLEAN_MOCKS,
299
+ array: ARRAY_MOCKS,
300
+ object: OBJECT_MOCKS,
301
+ date: DATE_MOCKS,
302
+ nullable: NULLABLE_MOCKS,
303
+ };
304
+ }
305
+ //# sourceMappingURL=mockGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mockGenerator.js","sourceRoot":"","sources":["../src/mockGenerator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { FunctionMeta, DependencyMeta } from "./analyzer";
2
+ import { TestGenConfig } from "./configManager";
3
+ /** The kind of test block to generate */
4
+ export type ScenarioKind = "standard" | "throws" | "rejects";
5
+ export interface ScenarioCase {
6
+ /** Human-readable test name */
7
+ label: string;
8
+ /** Mock literal values for each parameter, in order */
9
+ argLiterals: string[];
10
+ /** Parameter names, in order */
11
+ paramNames: string[];
12
+ /** What kind of test block to render */
13
+ kind: ScenarioKind;
14
+ }
15
+ export interface TestScenario {
16
+ functionName: string;
17
+ className?: string;
18
+ parameters: {
19
+ name: string;
20
+ type: string;
21
+ }[];
22
+ returnType: string;
23
+ cases: ScenarioCase[];
24
+ /** Whether the function is async */
25
+ isAsync: boolean;
26
+ /** Whether the function has throw statements */
27
+ throwsErrors: boolean;
28
+ /** Dependencies imported from other modules */
29
+ dependencies: DependencyMeta[];
30
+ /** Constructor parameters for class DI */
31
+ constructorParams?: {
32
+ name: string;
33
+ type: string;
34
+ }[];
35
+ }
36
+ /**
37
+ * Generate test scenarios (with mock values) for each extracted function.
38
+ */
39
+ export declare function generateScenarios(functions: FunctionMeta[], config: TestGenConfig): TestScenario[];
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateScenarios = generateScenarios;
4
+ const mockGenerator_1 = require("./mockGenerator");
5
+ /**
6
+ * Generate test scenarios (with mock values) for each extracted function.
7
+ */
8
+ function generateScenarios(functions, config) {
9
+ return functions.map((fn) => {
10
+ const cases = buildCases(fn, config);
11
+ return {
12
+ functionName: fn.name,
13
+ className: fn.className,
14
+ parameters: fn.parameters.map((p) => ({ name: p.name, type: p.type })),
15
+ returnType: fn.returnType,
16
+ cases,
17
+ isAsync: fn.isAsync,
18
+ throwsErrors: fn.throwsErrors,
19
+ dependencies: fn.dependencies,
20
+ constructorParams: fn.constructorParams?.map((p) => ({
21
+ name: p.name,
22
+ type: p.type,
23
+ })),
24
+ };
25
+ });
26
+ }
27
+ function buildCases(fn, config) {
28
+ const paramNames = fn.parameters.map((p) => p.name);
29
+ const cases = [];
30
+ const seen = new Set();
31
+ // ── Parameter‑driven mock arg sets ──────────────────────────────────
32
+ const mockSets = (0, mockGenerator_1.buildMockArgSets)(fn.parameters);
33
+ for (const ms of mockSets) {
34
+ if (!seen.has(ms.scenarioLabel)) {
35
+ seen.add(ms.scenarioLabel);
36
+ cases.push({
37
+ label: ms.scenarioLabel,
38
+ argLiterals: ms.args.map((a) => a.literal),
39
+ paramNames,
40
+ kind: "standard",
41
+ });
42
+ }
43
+ }
44
+ // ── Return‑type driven scenarios (boolean) ──────────────────────────
45
+ const returnMocks = (0, mockGenerator_1.getMocksForReturnType)(fn.returnType);
46
+ for (const rm of returnMocks) {
47
+ const label = `handles ${rm.label}`;
48
+ if (!seen.has(label)) {
49
+ seen.add(label);
50
+ const fallbackArgs = mockSets.length > 0 ? mockSets[0].args.map((a) => a.literal) : [];
51
+ cases.push({
52
+ label,
53
+ argLiterals: fallbackArgs,
54
+ paramNames,
55
+ kind: "standard",
56
+ });
57
+ }
58
+ }
59
+ // ── Error/throw scenarios ────────────────────────────────────────────
60
+ if (fn.throwsErrors) {
61
+ if (fn.isAsync) {
62
+ // Async function with throw → rejection scenario
63
+ const label = "rejects on invalid input";
64
+ if (!seen.has(label)) {
65
+ seen.add(label);
66
+ // Use boundary/edge-case args (last mock set) for error scenarios
67
+ const errorArgs = mockSets.length > 0
68
+ ? mockSets[mockSets.length - 1].args.map((a) => a.literal)
69
+ : [];
70
+ cases.push({
71
+ label,
72
+ argLiterals: errorArgs,
73
+ paramNames,
74
+ kind: "rejects",
75
+ });
76
+ }
77
+ }
78
+ else {
79
+ // Sync function with throw → toThrow scenario
80
+ const label = "throws on invalid input";
81
+ if (!seen.has(label)) {
82
+ seen.add(label);
83
+ const errorArgs = mockSets.length > 0
84
+ ? mockSets[mockSets.length - 1].args.map((a) => a.literal)
85
+ : [];
86
+ cases.push({
87
+ label,
88
+ argLiterals: errorArgs,
89
+ paramNames,
90
+ kind: "throws",
91
+ });
92
+ }
93
+ }
94
+ }
95
+ else if (fn.isAsync) {
96
+ // Async function without explicit throw → still add a rejection guard
97
+ const label = "handles rejection gracefully";
98
+ if (!seen.has(label)) {
99
+ seen.add(label);
100
+ const fallbackArgs = mockSets.length > 0
101
+ ? mockSets[0].args.map((a) => a.literal)
102
+ : [];
103
+ cases.push({
104
+ label,
105
+ argLiterals: fallbackArgs,
106
+ paramNames,
107
+ kind: "rejects",
108
+ });
109
+ }
110
+ }
111
+ // ── Dependency-interaction scenario ──────────────────────────────────
112
+ if (fn.dependencies.length > 0) {
113
+ const label = "verifies dependency interactions";
114
+ if (!seen.has(label)) {
115
+ seen.add(label);
116
+ const fallbackArgs = mockSets.length > 0
117
+ ? mockSets[0].args.map((a) => a.literal)
118
+ : [];
119
+ cases.push({
120
+ label,
121
+ argLiterals: fallbackArgs,
122
+ paramNames,
123
+ kind: "standard",
124
+ });
125
+ }
126
+ }
127
+ // ── Fallback ────────────────────────────────────────────────────────
128
+ if (cases.length === 0) {
129
+ cases.push({
130
+ label: "handles default case",
131
+ argLiterals: [],
132
+ paramNames: [],
133
+ kind: "standard",
134
+ });
135
+ }
136
+ return cases;
137
+ }
138
+ //# sourceMappingURL=scenarioEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenarioEngine.js","sourceRoot":"","sources":["../src/scenarioEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Walk upward from `startDir` to find the nearest directory containing a package.json.
3
+ */
4
+ export declare function getProjectRoot(startDir?: string): string;
5
+ /**
6
+ * Recursively create a directory if it does not exist.
7
+ */
8
+ export declare function ensureDir(dirPath: string): void;
9
+ /**
10
+ * Mirror a source file path into an output directory with a given suffix.
11
+ *
12
+ * Example:
13
+ * srcPath: /project/src/services/user.service.ts
14
+ * srcRoot: src
15
+ * destRoot: testgen/tests
16
+ * suffix: .test.ts
17
+ * → testgen/tests/services/user.service.test.ts
18
+ */
19
+ export declare function mirrorPath(srcPath: string, srcRoot: string, destRoot: string, suffix?: string): string;
20
+ /**
21
+ * Generate a short unique hash for a given string.
22
+ */
23
+ export declare function generateHash(input: string): string;
24
+ /**
25
+ * Log a styled message to the console.
26
+ */
27
+ export declare function log(message: string, level?: "info" | "success" | "warn" | "error"): void;
package/dist/utils.js ADDED
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getProjectRoot = getProjectRoot;
37
+ exports.ensureDir = ensureDir;
38
+ exports.mirrorPath = mirrorPath;
39
+ exports.generateHash = generateHash;
40
+ exports.log = log;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const crypto = __importStar(require("crypto-js"));
44
+ /**
45
+ * Walk upward from `startDir` to find the nearest directory containing a package.json.
46
+ */
47
+ function getProjectRoot(startDir = process.cwd()) {
48
+ let current = path.resolve(startDir);
49
+ while (true) {
50
+ if (fs.existsSync(path.join(current, "package.json"))) {
51
+ return current;
52
+ }
53
+ const parent = path.dirname(current);
54
+ if (parent === current) {
55
+ throw new Error("Could not find a package.json in any parent directory. Are you inside a Node.js project?");
56
+ }
57
+ current = parent;
58
+ }
59
+ }
60
+ /**
61
+ * Recursively create a directory if it does not exist.
62
+ */
63
+ function ensureDir(dirPath) {
64
+ fs.mkdirSync(dirPath, { recursive: true });
65
+ }
66
+ /**
67
+ * Mirror a source file path into an output directory with a given suffix.
68
+ *
69
+ * Example:
70
+ * srcPath: /project/src/services/user.service.ts
71
+ * srcRoot: src
72
+ * destRoot: testgen/tests
73
+ * suffix: .test.ts
74
+ * → testgen/tests/services/user.service.test.ts
75
+ */
76
+ function mirrorPath(srcPath, srcRoot, destRoot, suffix = ".test.ts") {
77
+ // Normalise to forward slashes for reliable splitting
78
+ const normalised = srcPath.replace(/\\/g, "/");
79
+ const srcRootNorm = srcRoot.replace(/\\/g, "/");
80
+ // Find the portion after the src root
81
+ const idx = normalised.indexOf(`${srcRootNorm}/`);
82
+ if (idx === -1) {
83
+ // Fallback — just use the basename
84
+ const base = path.basename(srcPath, ".ts");
85
+ return path.join(destRoot, `${base}${suffix}`);
86
+ }
87
+ const relativePart = normalised.substring(idx + srcRootNorm.length + 1);
88
+ const parsed = path.parse(relativePart);
89
+ const outFileName = `${parsed.name}${suffix}`;
90
+ return path.join(destRoot, parsed.dir, outFileName);
91
+ }
92
+ /**
93
+ * Generate a short unique hash for a given string.
94
+ */
95
+ function generateHash(input) {
96
+ return crypto.MD5(input).toString().substring(0, 8);
97
+ }
98
+ /**
99
+ * Log a styled message to the console.
100
+ */
101
+ function log(message, level = "info") {
102
+ const prefix = {
103
+ info: "\x1b[36mℹ\x1b[0m", // cyan
104
+ success: "\x1b[32m✔\x1b[0m", // green
105
+ warn: "\x1b[33m⚠\x1b[0m", // yellow
106
+ error: "\x1b[31m✖\x1b[0m", // red
107
+ };
108
+ console.log(`${prefix[level]} ${message}`);
109
+ }
110
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,wCAeC;AAKD,8BAEC;AAYD,gCAsBC;AAKD,oCAEC;AAKD,kBAWC;AAtFD,uCAAyB;AACzB,2CAA6B;AAC7B,kDAAoC;AAEpC;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAC3D,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAErC,OAAO,IAAI,EAAE,CAAC;QACV,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YACpD,OAAO,OAAO,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACX,0FAA0F,CAC7F,CAAC;QACN,CAAC;QACD,OAAO,GAAG,MAAM,CAAC;IACrB,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS,CAAC,OAAe;IACrC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,UAAU,CACtB,OAAe,EACf,OAAe,EACf,QAAgB,EAChB,SAAiB,UAAU;IAE3B,sDAAsD;IACtD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEhD,sCAAsC;IACtC,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,WAAW,GAAG,CAAC,CAAC;IAClD,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACb,mCAAmC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,GAAG,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC;IAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,KAAa;IACtC,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAgB,GAAG,CACf,OAAe,EACf,QAA+C,MAAM;IAErD,MAAM,MAAM,GAA2B;QACnC,IAAI,EAAE,kBAAkB,EAAM,OAAO;QACrC,OAAO,EAAE,kBAAkB,EAAG,QAAQ;QACtC,IAAI,EAAE,kBAAkB,EAAM,SAAS;QACvC,KAAK,EAAE,kBAAkB,EAAK,MAAM;KACvC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { TestGenConfig } from "./configManager";
2
+ /**
3
+ * Start the file watcher.
4
+ *
5
+ * Watches the src directory for .ts file changes and runs the
6
+ * analyze → scenario → mock → test pipeline on each changed file.
7
+ */
8
+ export declare function startWatcher(): void;
9
+ /**
10
+ * Process a single TypeScript file through the full pipeline:
11
+ * analyze → scenarios → mock file → test file
12
+ */
13
+ export declare function processFile(filePath: string, projectRoot: string, config: TestGenConfig): Promise<void>;