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,33 @@
|
|
|
1
|
+
export interface ParameterMeta {
|
|
2
|
+
name: string;
|
|
3
|
+
type: string;
|
|
4
|
+
}
|
|
5
|
+
export interface DependencyMeta {
|
|
6
|
+
/** Module specifier, e.g. './userRepository' */
|
|
7
|
+
modulePath: string;
|
|
8
|
+
/** Named imports used, e.g. ['findById', 'save'] */
|
|
9
|
+
importedNames: string[];
|
|
10
|
+
/** Whether it's a default import */
|
|
11
|
+
isDefault: boolean;
|
|
12
|
+
/** The local alias/name used in code */
|
|
13
|
+
localName: string;
|
|
14
|
+
}
|
|
15
|
+
export interface FunctionMeta {
|
|
16
|
+
name: string;
|
|
17
|
+
className?: string;
|
|
18
|
+
parameters: ParameterMeta[];
|
|
19
|
+
returnType: string;
|
|
20
|
+
/** Function uses async/await or returns a Promise */
|
|
21
|
+
isAsync: boolean;
|
|
22
|
+
/** Function body contains throw statements */
|
|
23
|
+
throwsErrors: boolean;
|
|
24
|
+
/** External module dependencies used inside the function body */
|
|
25
|
+
dependencies: DependencyMeta[];
|
|
26
|
+
/** Class constructor parameters (for DI mocking) */
|
|
27
|
+
constructorParams?: ParameterMeta[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Analyse a TypeScript source file and extract exported functions,
|
|
31
|
+
* class methods, their dependencies, async flags, and error patterns.
|
|
32
|
+
*/
|
|
33
|
+
export declare function analyzeFile(filePath: string): FunctionMeta[];
|
package/dist/analyzer.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyzeFile = analyzeFile;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
// ─── Main analyse function ───────────────────────────────────────────────────
|
|
6
|
+
/**
|
|
7
|
+
* Analyse a TypeScript source file and extract exported functions,
|
|
8
|
+
* class methods, their dependencies, async flags, and error patterns.
|
|
9
|
+
*/
|
|
10
|
+
function analyzeFile(filePath) {
|
|
11
|
+
const project = new ts_morph_1.Project({ compilerOptions: { allowJs: true } });
|
|
12
|
+
const sourceFile = project.addSourceFileAtPath(filePath);
|
|
13
|
+
const results = [];
|
|
14
|
+
// Collect all import declarations for dependency cross-referencing
|
|
15
|
+
const fileImports = collectImports(sourceFile);
|
|
16
|
+
// ── Exported function declarations ──────────────────────────────────
|
|
17
|
+
const functions = sourceFile.getFunctions();
|
|
18
|
+
for (const fn of functions) {
|
|
19
|
+
if (!fn.isExported())
|
|
20
|
+
continue;
|
|
21
|
+
const name = fn.getName();
|
|
22
|
+
if (!name)
|
|
23
|
+
continue;
|
|
24
|
+
const parameters = fn.getParameters().map((p) => ({
|
|
25
|
+
name: p.getName(),
|
|
26
|
+
type: p.getType().getText(p) || "unknown",
|
|
27
|
+
}));
|
|
28
|
+
const returnType = fn.getReturnType().getText(fn) || "void";
|
|
29
|
+
const isAsync = fn.isAsync() || returnType.toLowerCase().startsWith("promise");
|
|
30
|
+
const throwsErrors = bodyContainsThrow(fn);
|
|
31
|
+
const dependencies = findUsedDependencies(fn, fileImports);
|
|
32
|
+
results.push({
|
|
33
|
+
name,
|
|
34
|
+
parameters,
|
|
35
|
+
returnType,
|
|
36
|
+
isAsync,
|
|
37
|
+
throwsErrors,
|
|
38
|
+
dependencies,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// ── Exported class declarations → public methods ────────────────────
|
|
42
|
+
const classes = sourceFile.getClasses();
|
|
43
|
+
for (const cls of classes) {
|
|
44
|
+
if (!cls.isExported())
|
|
45
|
+
continue;
|
|
46
|
+
const className = cls.getName() ?? "AnonymousClass";
|
|
47
|
+
// Extract constructor params for DI
|
|
48
|
+
const constructorParams = extractConstructorParams(cls);
|
|
49
|
+
const methods = cls.getMethods();
|
|
50
|
+
for (const method of methods) {
|
|
51
|
+
// Skip private / protected
|
|
52
|
+
if (method.hasModifier(ts_morph_1.SyntaxKind.PrivateKeyword) ||
|
|
53
|
+
method.hasModifier(ts_morph_1.SyntaxKind.ProtectedKeyword)) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const name = method.getName();
|
|
57
|
+
const parameters = method.getParameters().map((p) => ({
|
|
58
|
+
name: p.getName(),
|
|
59
|
+
type: p.getType().getText(p) || "unknown",
|
|
60
|
+
}));
|
|
61
|
+
const returnType = method.getReturnType().getText(method) || "void";
|
|
62
|
+
const isAsync = method.isAsync() || returnType.toLowerCase().startsWith("promise");
|
|
63
|
+
const throwsErrors = bodyContainsThrow(method);
|
|
64
|
+
const dependencies = findUsedDependencies(method, fileImports);
|
|
65
|
+
results.push({
|
|
66
|
+
name,
|
|
67
|
+
className,
|
|
68
|
+
parameters,
|
|
69
|
+
returnType,
|
|
70
|
+
isAsync,
|
|
71
|
+
throwsErrors,
|
|
72
|
+
dependencies,
|
|
73
|
+
constructorParams,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return results;
|
|
78
|
+
}
|
|
79
|
+
function collectImports(sourceFile) {
|
|
80
|
+
const imports = [];
|
|
81
|
+
for (const decl of sourceFile.getImportDeclarations()) {
|
|
82
|
+
const modulePath = decl.getModuleSpecifierValue();
|
|
83
|
+
// Skip node_modules / built-in imports — only track relative imports
|
|
84
|
+
if (!modulePath.startsWith(".") && !modulePath.startsWith("/")) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
// Default import
|
|
88
|
+
const defaultImport = decl.getDefaultImport();
|
|
89
|
+
if (defaultImport) {
|
|
90
|
+
imports.push({
|
|
91
|
+
modulePath,
|
|
92
|
+
localName: defaultImport.getText(),
|
|
93
|
+
importedName: "default",
|
|
94
|
+
isDefault: true,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Named imports
|
|
98
|
+
for (const named of decl.getNamedImports()) {
|
|
99
|
+
imports.push({
|
|
100
|
+
modulePath,
|
|
101
|
+
localName: named.getAliasNode()?.getText() ?? named.getName(),
|
|
102
|
+
importedName: named.getName(),
|
|
103
|
+
isDefault: false,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return imports;
|
|
108
|
+
}
|
|
109
|
+
// ─── Dependency cross-referencing ────────────────────────────────────────────
|
|
110
|
+
function findUsedDependencies(fnNode, fileImports) {
|
|
111
|
+
const bodyText = fnNode.getText();
|
|
112
|
+
const depMap = new Map();
|
|
113
|
+
for (const imp of fileImports) {
|
|
114
|
+
// Check if the imported name is used in the function body
|
|
115
|
+
// Use word boundary matching to avoid partial matches
|
|
116
|
+
const regex = new RegExp(`\\b${escapeRegex(imp.localName)}\\b`);
|
|
117
|
+
if (regex.test(bodyText)) {
|
|
118
|
+
const existing = depMap.get(imp.modulePath);
|
|
119
|
+
if (existing) {
|
|
120
|
+
if (!existing.importedNames.includes(imp.importedName)) {
|
|
121
|
+
existing.importedNames.push(imp.importedName);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
depMap.set(imp.modulePath, {
|
|
126
|
+
modulePath: imp.modulePath,
|
|
127
|
+
importedNames: [imp.importedName],
|
|
128
|
+
isDefault: imp.isDefault,
|
|
129
|
+
localName: imp.localName,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return Array.from(depMap.values());
|
|
135
|
+
}
|
|
136
|
+
function escapeRegex(str) {
|
|
137
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
138
|
+
}
|
|
139
|
+
// ─── Throw detection ─────────────────────────────────────────────────────────
|
|
140
|
+
function bodyContainsThrow(node) {
|
|
141
|
+
return node.getDescendantsOfKind(ts_morph_1.SyntaxKind.ThrowStatement).length > 0;
|
|
142
|
+
}
|
|
143
|
+
// ─── Constructor param extraction ────────────────────────────────────────────
|
|
144
|
+
function extractConstructorParams(cls) {
|
|
145
|
+
const ctors = cls.getConstructors();
|
|
146
|
+
if (ctors.length === 0)
|
|
147
|
+
return [];
|
|
148
|
+
const ctor = ctors[0];
|
|
149
|
+
return ctor.getParameters().map((p) => ({
|
|
150
|
+
name: p.getName(),
|
|
151
|
+
type: p.getType().getText(p) || "unknown",
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootstrap the testgen workspace inside the current project.
|
|
3
|
+
*
|
|
4
|
+
* Creates:
|
|
5
|
+
* testgen/
|
|
6
|
+
* ├── tests/
|
|
7
|
+
* ├── mocks/
|
|
8
|
+
* ├── utils/
|
|
9
|
+
* │ └── setup.ts
|
|
10
|
+
* ├── jest.config.ts
|
|
11
|
+
* ├── tsconfig.test.json
|
|
12
|
+
* └── testgen.config.json
|
|
13
|
+
*
|
|
14
|
+
* Also patches the host package.json to add a "test" script.
|
|
15
|
+
*/
|
|
16
|
+
export declare function bootstrap(): void;
|
|
@@ -0,0 +1,227 @@
|
|
|
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.bootstrap = bootstrap;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
const utils_1 = require("./utils");
|
|
41
|
+
const configManager_1 = require("./configManager");
|
|
42
|
+
/**
|
|
43
|
+
* Bootstrap the testgen workspace inside the current project.
|
|
44
|
+
*
|
|
45
|
+
* Creates:
|
|
46
|
+
* testgen/
|
|
47
|
+
* ├── tests/
|
|
48
|
+
* ├── mocks/
|
|
49
|
+
* ├── utils/
|
|
50
|
+
* │ └── setup.ts
|
|
51
|
+
* ├── jest.config.ts
|
|
52
|
+
* ├── tsconfig.test.json
|
|
53
|
+
* └── testgen.config.json
|
|
54
|
+
*
|
|
55
|
+
* Also patches the host package.json to add a "test" script.
|
|
56
|
+
*/
|
|
57
|
+
function bootstrap() {
|
|
58
|
+
const projectRoot = (0, utils_1.getProjectRoot)();
|
|
59
|
+
const testgenDir = path.join(projectRoot, "testgen");
|
|
60
|
+
if (fs.existsSync(testgenDir)) {
|
|
61
|
+
(0, utils_1.log)("testgen/ directory already exists — skipping scaffold.", "warn");
|
|
62
|
+
(0, utils_1.log)("Delete the testgen/ folder first if you want a fresh init.", "info");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
(0, utils_1.log)("Bootstrapping testgen workspace…", "info");
|
|
66
|
+
// ── Create directories ────────────────────────────────────────────
|
|
67
|
+
(0, utils_1.ensureDir)(path.join(testgenDir, "tests"));
|
|
68
|
+
(0, utils_1.ensureDir)(path.join(testgenDir, "mocks"));
|
|
69
|
+
(0, utils_1.ensureDir)(path.join(testgenDir, "utils"));
|
|
70
|
+
// ── utils/setup.ts ────────────────────────────────────────────────
|
|
71
|
+
const setupContent = `/**
|
|
72
|
+
* Global test environment setup.
|
|
73
|
+
* Add any environment variables or global configuration here.
|
|
74
|
+
*
|
|
75
|
+
* This file is available for manual import in test files if needed:
|
|
76
|
+
* import '../utils/setup';
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
// Set test environment
|
|
80
|
+
process.env.NODE_ENV = 'test';
|
|
81
|
+
`;
|
|
82
|
+
fs.writeFileSync(path.join(testgenDir, "utils", "setup.ts"), setupContent, "utf-8");
|
|
83
|
+
// ── jest.config.ts ────────────────────────────────────────────────
|
|
84
|
+
const jestConfig = `import type { Config } from "jest";
|
|
85
|
+
|
|
86
|
+
const config: Config = {
|
|
87
|
+
preset: "ts-jest",
|
|
88
|
+
testEnvironment: "node",
|
|
89
|
+
roots: ["<rootDir>/tests"],
|
|
90
|
+
testMatch: ["**/*.test.ts"],
|
|
91
|
+
transform: {
|
|
92
|
+
"^.+\\\\.ts$": "ts-jest",
|
|
93
|
+
},
|
|
94
|
+
moduleFileExtensions: ["ts", "js", "json"],
|
|
95
|
+
verbose: true,
|
|
96
|
+
clearMocks: true,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default config;
|
|
100
|
+
`;
|
|
101
|
+
fs.writeFileSync(path.join(testgenDir, "jest.config.ts"), jestConfig, "utf-8");
|
|
102
|
+
// ── tsconfig.json (inside testgen/) ─────────────────────────────────
|
|
103
|
+
const tsConfigTest = {
|
|
104
|
+
compilerOptions: {
|
|
105
|
+
target: "ES2020",
|
|
106
|
+
module: "commonjs",
|
|
107
|
+
strict: true,
|
|
108
|
+
esModuleInterop: true,
|
|
109
|
+
skipLibCheck: true,
|
|
110
|
+
outDir: "./dist-test",
|
|
111
|
+
rootDir: "..",
|
|
112
|
+
declaration: false,
|
|
113
|
+
sourceMap: true,
|
|
114
|
+
types: ["jest", "node"],
|
|
115
|
+
},
|
|
116
|
+
include: ["tests/**/*.ts", "utils/**/*.ts", "../src/**/*.ts"],
|
|
117
|
+
exclude: ["node_modules"],
|
|
118
|
+
};
|
|
119
|
+
fs.writeFileSync(path.join(testgenDir, "tsconfig.json"), JSON.stringify(tsConfigTest, null, 2), "utf-8");
|
|
120
|
+
// ── testgen.config.json ───────────────────────────────────────────
|
|
121
|
+
const defaultConfig = (0, configManager_1.getDefaultConfig)();
|
|
122
|
+
fs.writeFileSync(path.join(testgenDir, "testgen.config.json"), JSON.stringify(defaultConfig, null, 2), "utf-8");
|
|
123
|
+
// ── Patch host package.json ───────────────────────────────────────
|
|
124
|
+
patchPackageJson(projectRoot);
|
|
125
|
+
// ── Install required dev dependencies ────────────────────────────
|
|
126
|
+
installTestDependencies(projectRoot);
|
|
127
|
+
// ── Patch host tsconfig.json ─────────────────────────────────────
|
|
128
|
+
patchTsConfig(projectRoot);
|
|
129
|
+
(0, utils_1.log)("Workspace created successfully!", "success");
|
|
130
|
+
(0, utils_1.log)("", "info");
|
|
131
|
+
(0, utils_1.log)(" testgen/tests/ — generated test files", "info");
|
|
132
|
+
(0, utils_1.log)(" testgen/mocks/ — mock data (per source file)", "info");
|
|
133
|
+
(0, utils_1.log)(" testgen/utils/setup.ts — global test setup", "info");
|
|
134
|
+
(0, utils_1.log)(" testgen/jest.config.ts — Jest configuration", "info");
|
|
135
|
+
(0, utils_1.log)(" testgen/testgen.config.json — testgen settings", "info");
|
|
136
|
+
(0, utils_1.log)("", "info");
|
|
137
|
+
(0, utils_1.log)("Run `npx testgen watch` to start watching for changes.", "info");
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Install required test dev-dependencies so generated files have
|
|
141
|
+
* proper type definitions (describe, test, expect, jest, etc.).
|
|
142
|
+
*/
|
|
143
|
+
function installTestDependencies(projectRoot) {
|
|
144
|
+
const deps = ["jest", "ts-jest", "ts-node", "@types/jest", "@types/node"];
|
|
145
|
+
(0, utils_1.log)("Installing test dependencies…", "info");
|
|
146
|
+
try {
|
|
147
|
+
(0, child_process_1.execSync)(`npm install --save-dev ${deps.join(" ")}`, {
|
|
148
|
+
cwd: projectRoot,
|
|
149
|
+
stdio: "pipe",
|
|
150
|
+
});
|
|
151
|
+
(0, utils_1.log)(`Installed: ${deps.join(", ")}`, "success");
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
(0, utils_1.log)(`Could not auto-install dependencies. Run manually:\n npm install --save-dev ${deps.join(" ")}`, "warn");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Add the "test" script to the host project's package.json.
|
|
159
|
+
*/
|
|
160
|
+
function patchPackageJson(projectRoot) {
|
|
161
|
+
const pkgPath = path.join(projectRoot, "package.json");
|
|
162
|
+
try {
|
|
163
|
+
const raw = fs.readFileSync(pkgPath, "utf-8");
|
|
164
|
+
const pkg = JSON.parse(raw);
|
|
165
|
+
if (!pkg.scripts) {
|
|
166
|
+
pkg.scripts = {};
|
|
167
|
+
}
|
|
168
|
+
if (pkg.scripts.test && pkg.scripts.test !== "jest --config ./testgen/jest.config.ts") {
|
|
169
|
+
(0, utils_1.log)(`Existing "test" script found: "${pkg.scripts.test}" — overwriting.`, "warn");
|
|
170
|
+
}
|
|
171
|
+
pkg.scripts.test = "jest --config ./testgen/jest.config.ts";
|
|
172
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
173
|
+
(0, utils_1.log)('Added "test" script to package.json.', "success");
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
(0, utils_1.log)("Could not update package.json — please add the test script manually.", "error");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Patch the host project's tsconfig.json to exclude testgen/ from compilation.
|
|
181
|
+
* This prevents "rootDir" errors when the main tsconfig has rootDir set to src/.
|
|
182
|
+
*/
|
|
183
|
+
function patchTsConfig(projectRoot) {
|
|
184
|
+
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
|
|
185
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
186
|
+
(0, utils_1.log)("No tsconfig.json found — skipping tsconfig patch.", "info");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
const raw = fs.readFileSync(tsconfigPath, "utf-8");
|
|
191
|
+
// Try standard parse first; only strip comments/trailing commas on failure
|
|
192
|
+
let tsconfig;
|
|
193
|
+
try {
|
|
194
|
+
tsconfig = JSON.parse(raw);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Strip comments carefully — only outside quoted strings
|
|
198
|
+
const cleaned = raw
|
|
199
|
+
.replace(/("(?:[^"\\]|\\.)*")|\/\/.*$/gm, (m, str) => str ?? "") // preserve strings, strip // comments
|
|
200
|
+
.replace(/("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g, (m, str) => str ?? "") // preserve strings, strip /* */
|
|
201
|
+
.replace(/,(\s*[}\]])/g, "$1");
|
|
202
|
+
tsconfig = JSON.parse(cleaned);
|
|
203
|
+
}
|
|
204
|
+
if (!tsconfig.exclude) {
|
|
205
|
+
tsconfig.exclude = [];
|
|
206
|
+
}
|
|
207
|
+
const required = ["testgen", "node_modules", "dist"];
|
|
208
|
+
let changed = false;
|
|
209
|
+
for (const entry of required) {
|
|
210
|
+
if (!tsconfig.exclude.includes(entry)) {
|
|
211
|
+
tsconfig.exclude.push(entry);
|
|
212
|
+
changed = true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (changed) {
|
|
216
|
+
fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 4) + "\n", "utf-8");
|
|
217
|
+
(0, utils_1.log)("Patched tsconfig.json — added testgen to exclude list.", "success");
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
(0, utils_1.log)("tsconfig.json already excludes testgen — no changes needed.", "info");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
(0, utils_1.log)("Could not patch tsconfig.json — please add \"testgen\" to the exclude array manually.", "warn");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const commander_1 = require("commander");
|
|
39
|
+
const bootstrap_1 = require("./bootstrap");
|
|
40
|
+
const watcher_1 = require("./watcher");
|
|
41
|
+
const configManager_1 = require("./configManager");
|
|
42
|
+
const utils_1 = require("./utils");
|
|
43
|
+
const program = new commander_1.Command();
|
|
44
|
+
program
|
|
45
|
+
.name("testgen")
|
|
46
|
+
.description("Developer CLI tool that bootstraps testing environments and auto-generates unit test skeletons for TypeScript functions.")
|
|
47
|
+
.version("1.0.0");
|
|
48
|
+
program
|
|
49
|
+
.command("init")
|
|
50
|
+
.description("Initialize the testgen workspace in the current project")
|
|
51
|
+
.action(() => {
|
|
52
|
+
(0, bootstrap_1.bootstrap)();
|
|
53
|
+
});
|
|
54
|
+
program
|
|
55
|
+
.command("watch")
|
|
56
|
+
.description("Watch source files and auto-generate test skeletons")
|
|
57
|
+
.action(() => {
|
|
58
|
+
(0, watcher_1.startWatcher)();
|
|
59
|
+
});
|
|
60
|
+
program
|
|
61
|
+
.command("generate <file>")
|
|
62
|
+
.description("Generate test and mock files for a single source file")
|
|
63
|
+
.action(async (file) => {
|
|
64
|
+
const projectRoot = (0, utils_1.getProjectRoot)();
|
|
65
|
+
const config = (0, configManager_1.loadConfig)(projectRoot);
|
|
66
|
+
const absPath = path.resolve(file);
|
|
67
|
+
await (0, watcher_1.processFile)(absPath, projectRoot, config);
|
|
68
|
+
});
|
|
69
|
+
program.parse(process.argv);
|
|
70
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,2CAA6B;AAC7B,yCAAoC;AACpC,2CAAwC;AACxC,uCAAsD;AACtD,mDAA6C;AAC7C,mCAAyC;AAEzC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CACR,0HAA0H,CAC7H;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,OAAO;KACF,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CAAC,GAAG,EAAE;IACT,IAAA,qBAAS,GAAE,CAAC;AAChB,CAAC,CAAC,CAAC;AAEP,OAAO;KACF,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,GAAG,EAAE;IACT,IAAA,sBAAY,GAAE,CAAC;AACnB,CAAC,CAAC,CAAC;AAEP,OAAO;KACF,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;IAC3B,MAAM,WAAW,GAAG,IAAA,sBAAc,GAAE,CAAC;IACrC,MAAM,MAAM,GAAG,IAAA,0BAAU,EAAC,WAAW,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,IAAA,qBAAW,EAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEP,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface TestGenConfig {
|
|
2
|
+
watchPatterns: string[];
|
|
3
|
+
ignorePatterns: string[];
|
|
4
|
+
testDir: string;
|
|
5
|
+
mockDir: string;
|
|
6
|
+
srcDir: string;
|
|
7
|
+
scenarioRules: {
|
|
8
|
+
number: string[];
|
|
9
|
+
string: string[];
|
|
10
|
+
boolean: string[];
|
|
11
|
+
default: string[];
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function loadConfig(projectRoot: string): TestGenConfig;
|
|
15
|
+
export declare function getDefaultConfig(): TestGenConfig;
|
|
@@ -0,0 +1,94 @@
|
|
|
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.loadConfig = loadConfig;
|
|
37
|
+
exports.getDefaultConfig = getDefaultConfig;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const DEFAULT_CONFIG = {
|
|
41
|
+
watchPatterns: ["src/**/*.ts"],
|
|
42
|
+
ignorePatterns: ["node_modules", "testgen", "dist", "**/*.test.ts", "**/*.spec.ts"],
|
|
43
|
+
testDir: "testgen/tests",
|
|
44
|
+
mockDir: "testgen/mocks",
|
|
45
|
+
srcDir: "src",
|
|
46
|
+
scenarioRules: {
|
|
47
|
+
number: [
|
|
48
|
+
"handles typical value",
|
|
49
|
+
"handles negative value",
|
|
50
|
+
"handles zero",
|
|
51
|
+
"handles boundary value",
|
|
52
|
+
],
|
|
53
|
+
string: [
|
|
54
|
+
"handles valid input",
|
|
55
|
+
"handles empty string",
|
|
56
|
+
"handles special characters",
|
|
57
|
+
"handles whitespace-only input",
|
|
58
|
+
],
|
|
59
|
+
boolean: ["handles truthy condition", "handles falsy condition"],
|
|
60
|
+
default: ["handles default case"],
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
function loadConfig(projectRoot) {
|
|
64
|
+
const configPath = path.join(projectRoot, "testgen", "testgen.config.json");
|
|
65
|
+
if (fs.existsSync(configPath)) {
|
|
66
|
+
try {
|
|
67
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
68
|
+
const userConfig = JSON.parse(raw);
|
|
69
|
+
return mergeConfig(DEFAULT_CONFIG, userConfig);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
console.warn("⚠ Could not parse testgen.config.json — using defaults.");
|
|
73
|
+
return { ...DEFAULT_CONFIG };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { ...DEFAULT_CONFIG };
|
|
77
|
+
}
|
|
78
|
+
function mergeConfig(base, override) {
|
|
79
|
+
return {
|
|
80
|
+
watchPatterns: override.watchPatterns ?? base.watchPatterns,
|
|
81
|
+
ignorePatterns: override.ignorePatterns ?? base.ignorePatterns,
|
|
82
|
+
testDir: override.testDir ?? base.testDir,
|
|
83
|
+
mockDir: override.mockDir ?? base.mockDir,
|
|
84
|
+
srcDir: override.srcDir ?? base.srcDir,
|
|
85
|
+
scenarioRules: {
|
|
86
|
+
...base.scenarioRules,
|
|
87
|
+
...(override.scenarioRules ?? {}),
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function getDefaultConfig() {
|
|
92
|
+
return { ...DEFAULT_CONFIG };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=configManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configManager.js","sourceRoot":"","sources":["../src/configManager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,gCAeC;AAmBD,4CAEC;AA7ED,uCAAyB;AACzB,2CAA6B;AAgB7B,MAAM,cAAc,GAAkB;IAClC,aAAa,EAAE,CAAC,aAAa,CAAC;IAC9B,cAAc,EAAE,CAAC,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,CAAC;IACnF,OAAO,EAAE,eAAe;IACxB,OAAO,EAAE,eAAe;IACxB,MAAM,EAAE,KAAK;IACb,aAAa,EAAE;QACX,MAAM,EAAE;YACJ,uBAAuB;YACvB,wBAAwB;YACxB,cAAc;YACd,wBAAwB;SAC3B;QACD,MAAM,EAAE;YACJ,qBAAqB;YACrB,sBAAsB;YACtB,4BAA4B;YAC5B,+BAA+B;SAClC;QACD,OAAO,EAAE,CAAC,0BAA0B,EAAE,yBAAyB,CAAC;QAChE,OAAO,EAAE,CAAC,sBAAsB,CAAC;KACpC;CACJ,CAAC;AAEF,SAAgB,UAAU,CAAC,WAAmB;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAE5E,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA2B,CAAC;YAC7D,OAAO,WAAW,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;YACzE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;QACjC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,WAAW,CAChB,IAAmB,EACnB,QAAgC;IAEhC,OAAO;QACH,aAAa,EAAE,QAAQ,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa;QAC3D,cAAc,EAAE,QAAQ,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc;QAC9D,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;QACzC,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;QACzC,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM;QACtC,aAAa,EAAE;YACX,GAAG,IAAI,CAAC,aAAa;YACrB,GAAG,CAAC,QAAQ,CAAC,aAAa,IAAI,EAAE,CAAC;SACpC;KACJ,CAAC;AACN,CAAC;AAED,SAAgB,gBAAgB;IAC5B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;AACjC,CAAC"}
|