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.
- package/dist/analyzer.d.ts +33 -0
- package/dist/analyzer.js +154 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/bootstrap.d.ts +16 -0
- package/dist/bootstrap.js +227 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +70 -0
- package/dist/cli.js.map +1 -0
- package/dist/configManager.d.ts +15 -0
- package/dist/configManager.js +94 -0
- package/dist/configManager.js.map +1 -0
- package/dist/formatter.d.ts +5 -0
- package/dist/formatter.js +67 -0
- package/dist/formatter.js.map +1 -0
- package/dist/generator.d.ts +10 -0
- package/dist/generator.js +446 -0
- package/dist/generator.js.map +1 -0
- package/dist/mockGenerator.d.ts +61 -0
- package/dist/mockGenerator.js +305 -0
- package/dist/mockGenerator.js.map +1 -0
- package/dist/scenarioEngine.d.ts +39 -0
- package/dist/scenarioEngine.js +138 -0
- package/dist/scenarioEngine.js.map +1 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +110 -0
- package/dist/utils.js.map +1 -0
- package/dist/watcher.d.ts +13 -0
- package/dist/watcher.js +148 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +44 -0
|
@@ -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":";;AAqCA,8CAqBC;AAxDD,mDAAsF;AAgCtF;;GAEG;AACH,SAAgB,iBAAiB,CAC7B,SAAyB,EACzB,MAAqB;IAErB,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACxB,MAAM,KAAK,GAAG,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACrC,OAAO;YACH,YAAY,EAAE,EAAE,CAAC,IAAI;YACrB,SAAS,EAAE,EAAE,CAAC,SAAS;YACvB,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACtE,UAAU,EAAE,EAAE,CAAC,UAAU;YACzB,KAAK;YACL,OAAO,EAAE,EAAE,CAAC,OAAO;YACnB,YAAY,EAAE,EAAE,CAAC,YAAY;YAC7B,YAAY,EAAE,EAAE,CAAC,YAAY;YAC7B,iBAAiB,EAAE,EAAE,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjD,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;aACf,CAAC,CAAC;SACN,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,UAAU,CAAC,EAAgB,EAAE,MAAqB;IACvD,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,uEAAuE;IACvE,MAAM,QAAQ,GAAiB,IAAA,gCAAgB,EAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAE/D,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC;gBACP,KAAK,EAAE,EAAE,CAAC,aAAa;gBACvB,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBAC1C,UAAU;gBACV,IAAI,EAAE,UAAU;aACnB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,uEAAuE;IACvE,MAAM,WAAW,GAAG,IAAA,qCAAqB,EAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IACzD,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACvF,KAAK,CAAC,IAAI,CAAC;gBACP,KAAK;gBACL,WAAW,EAAE,YAAY;gBACzB,UAAU;gBACV,IAAI,EAAE,UAAU;aACnB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,IAAI,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;YACb,iDAAiD;YACjD,MAAM,KAAK,GAAG,0BAA0B,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAChB,kEAAkE;gBAClE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC;oBACjC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;oBAC1D,CAAC,CAAC,EAAE,CAAC;gBACT,KAAK,CAAC,IAAI,CAAC;oBACP,KAAK;oBACL,WAAW,EAAE,SAAS;oBACtB,UAAU;oBACV,IAAI,EAAE,SAAS;iBAClB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,8CAA8C;YAC9C,MAAM,KAAK,GAAG,yBAAyB,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAChB,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC;oBACjC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;oBAC1D,CAAC,CAAC,EAAE,CAAC;gBACT,KAAK,CAAC,IAAI,CAAC;oBACP,KAAK;oBACL,WAAW,EAAE,SAAS;oBACtB,UAAU;oBACV,IAAI,EAAE,QAAQ;iBACjB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;IACL,CAAC;SAAM,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;QACpB,sEAAsE;QACtE,MAAM,KAAK,GAAG,8BAA8B,CAAC;QAC7C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBACxC,CAAC,CAAC,EAAE,CAAC;YACT,KAAK,CAAC,IAAI,CAAC;gBACP,KAAK;gBACL,WAAW,EAAE,YAAY;gBACzB,UAAU;gBACV,IAAI,EAAE,SAAS;aAClB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,kCAAkC,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBACxC,CAAC,CAAC,EAAE,CAAC;YACT,KAAK,CAAC,IAAI,CAAC;gBACP,KAAK;gBACL,WAAW,EAAE,YAAY;gBACzB,UAAU;gBACV,IAAI,EAAE,UAAU;aACnB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,uEAAuE;IACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC;YACP,KAAK,EAAE,sBAAsB;YAC7B,WAAW,EAAE,EAAE;YACf,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,UAAU;SACnB,CAAC,CAAC;IACP,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -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>;
|