@gnapi/cotester 1.2.7 → 1.2.9
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 +6 -0
- package/dist/analyzer.js +61 -0
- package/dist/analyzer.js.map +1 -1
- package/dist/astCache.js +1 -1
- package/dist/astCache.js.map +1 -1
- package/dist/auditLogger.d.ts +2 -0
- package/dist/auditLogger.js +38 -0
- package/dist/auditLogger.js.map +1 -1
- package/dist/branchAnalyzer.d.ts +1 -1
- package/dist/branchAnalyzer.js +91 -18
- package/dist/branchAnalyzer.js.map +1 -1
- package/dist/checker.d.ts +2 -0
- package/dist/checker.js +46 -3
- package/dist/checker.js.map +1 -1
- package/dist/cli.js +14 -1
- package/dist/cli.js.map +1 -1
- package/dist/configManager.d.ts +6 -0
- package/dist/configManager.js +44 -0
- package/dist/configManager.js.map +1 -1
- package/dist/frameworkAdapter.d.ts +11 -0
- package/dist/frameworkAdapter.js +17 -0
- package/dist/frameworkAdapter.js.map +1 -1
- package/dist/generator.js +58 -43
- package/dist/generator.js.map +1 -1
- package/dist/ignoreManager.js +10 -1
- package/dist/ignoreManager.js.map +1 -1
- package/dist/interfaceShapeResolver.js +77 -41
- package/dist/interfaceShapeResolver.js.map +1 -1
- package/dist/mockDataEngine.js +4 -1
- package/dist/mockDataEngine.js.map +1 -1
- package/dist/mockGenerator.js +8 -3
- package/dist/mockGenerator.js.map +1 -1
- package/dist/ormMockGenerator.js +77 -8
- package/dist/ormMockGenerator.js.map +1 -1
- package/dist/reporter.js +52 -24
- package/dist/reporter.js.map +1 -1
- package/dist/scenarioEngine.js +6 -0
- package/dist/scenarioEngine.js.map +1 -1
- package/dist/sharedMockRegistry.js +21 -4
- package/dist/sharedMockRegistry.js.map +1 -1
- package/dist/validator.js +23 -2
- package/dist/validator.js.map +1 -1
- package/dist/watcher.js +30 -1
- package/dist/watcher.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,uCAAyB;AACzB,2CAA6B;AAC7B,yCAAoC;AACpC,2CAAwC;AACxC,uCAAsD;AACtD,mDAA6C;AAC7C,mCAA0D;AAC1D,uCAAgD;AAChD,yCAAuC;AACvC,qDAAgD;AAChD,yCAAwC;AACxC,2CAA0C;AAE1C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CACR,0HAA0H,CAC7H;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,OAAO;KACF,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,GAAG,EAAE;IACT,IAAA,qBAAS,GAAE,CAAC;AAChB,CAAC,CAAC,CAAC;AAEP,OAAO;KACF,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,kIAAkI,CAAC;KAC/I,MAAM,CAAC,CAAC,MAAe,EAAE,EAAE;IACxB,IAAA,sBAAY,EAAC,MAAM,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEP,OAAO;KACF,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CACH,WAAW,EACX,mEAAmE,CACtE;KACA,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,IAA0B,EAAE,EAAE;IACvD,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,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAA,WAAG,EAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,IAAA,qBAAW,EAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;AAC1E,CAAC,CAAC,CAAC;AAEP,OAAO;KACF,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CACR,oGAAoG;IACpG,6EAA6E,CAChF;KACA,MAAM,CACH,qBAAqB,EACrB,uFAAuF,EACvF,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/configManager.d.ts
CHANGED
|
@@ -50,4 +50,10 @@ export interface TestGenConfig {
|
|
|
50
50
|
* are skipped silently.
|
|
51
51
|
*/
|
|
52
52
|
export declare function loadConfig(projectRoot: string): TestGenConfig;
|
|
53
|
+
/** Return a copy of the built-in default configuration. */
|
|
53
54
|
export declare function getDefaultConfig(): TestGenConfig;
|
|
55
|
+
/**
|
|
56
|
+
* Validate a resolved config object, printing warnings for invalid fields.
|
|
57
|
+
* Returns true if the config is safe to use, false if a fatal error was found.
|
|
58
|
+
*/
|
|
59
|
+
export declare function validateConfig(config: TestGenConfig, projectRoot: string): boolean;
|
package/dist/configManager.js
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.loadConfig = loadConfig;
|
|
37
37
|
exports.getDefaultConfig = getDefaultConfig;
|
|
38
|
+
exports.validateConfig = validateConfig;
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const path = __importStar(require("path"));
|
|
40
41
|
const module_1 = require("module");
|
|
@@ -212,7 +213,50 @@ function mergeConfig(base, override) {
|
|
|
212
213
|
},
|
|
213
214
|
};
|
|
214
215
|
}
|
|
216
|
+
/** Return a copy of the built-in default configuration. */
|
|
215
217
|
function getDefaultConfig() {
|
|
216
218
|
return { ...DEFAULT_CONFIG };
|
|
217
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Validate a resolved config object, printing warnings for invalid fields.
|
|
222
|
+
* Returns true if the config is safe to use, false if a fatal error was found.
|
|
223
|
+
*/
|
|
224
|
+
function validateConfig(config, projectRoot) {
|
|
225
|
+
let valid = true;
|
|
226
|
+
// --- minCoverage ---
|
|
227
|
+
if (typeof config.minCoverage !== "number" ||
|
|
228
|
+
!Number.isFinite(config.minCoverage) ||
|
|
229
|
+
config.minCoverage < 0 ||
|
|
230
|
+
config.minCoverage > 100) {
|
|
231
|
+
console.error(`✖ cotester: minCoverage must be a number between 0 and 100 (got ${config.minCoverage}). ` +
|
|
232
|
+
`Update cotester/cotester.config.json.`);
|
|
233
|
+
valid = false;
|
|
234
|
+
}
|
|
235
|
+
// --- framework ---
|
|
236
|
+
if (config.framework !== "jest" && config.framework !== "vitest") {
|
|
237
|
+
console.error(`✖ cotester: framework must be "jest" or "vitest" (got "${config.framework}"). ` +
|
|
238
|
+
`Update cotester/cotester.config.json.`);
|
|
239
|
+
valid = false;
|
|
240
|
+
}
|
|
241
|
+
// --- testDir must not equal srcDir ---
|
|
242
|
+
if (config.testDir && config.srcDir && config.testDir === config.srcDir) {
|
|
243
|
+
console.error(`✖ cotester: testDir and srcDir must not be the same path ("${config.srcDir}"). ` +
|
|
244
|
+
`This would overwrite source files with generated tests!`);
|
|
245
|
+
valid = false;
|
|
246
|
+
}
|
|
247
|
+
// --- srcDir existence warning (CF-1) ---
|
|
248
|
+
const srcAbs = path.resolve(projectRoot, config.srcDir);
|
|
249
|
+
if (!fs.existsSync(srcAbs)) {
|
|
250
|
+
console.warn(`⚠ cotester: srcDir "${config.srcDir}" does not exist at ${srcAbs}. ` +
|
|
251
|
+
`Check cotester/cotester.config.json or create the directory.`);
|
|
252
|
+
// Non-fatal — directory may be created later
|
|
253
|
+
}
|
|
254
|
+
// --- testDir existence warning (CF-1) ---
|
|
255
|
+
const testAbs = path.resolve(projectRoot, config.testDir);
|
|
256
|
+
if (!fs.existsSync(testAbs)) {
|
|
257
|
+
console.warn(`⚠ cotester: testDir "${config.testDir}" does not exist at ${testAbs}. ` +
|
|
258
|
+
`It will be created on first run.`);
|
|
259
|
+
}
|
|
260
|
+
return valid;
|
|
261
|
+
}
|
|
218
262
|
//# sourceMappingURL=configManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configManager.js","sourceRoot":"","sources":["../src/configManager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmGA,gCAmCC;
|
|
1
|
+
{"version":3,"file":"configManager.js","sourceRoot":"","sources":["../src/configManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,13 @@ export interface TestFrameworkAdapter {
|
|
|
29
29
|
mockReturnValue(name: string, val: string): string;
|
|
30
30
|
/** `jest.fn().mockReturnValue(val)` / `vi.fn().mockReturnValue(val)` — for inline chained stubs */
|
|
31
31
|
mockFnReturnValue(val: string): string;
|
|
32
|
+
/** `jest.spyOn(target, method)` / `vi.spyOn(target, method)` — for partial mocking (D-3) */
|
|
33
|
+
spyOn(target: string, method: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Produce `jest.mock(...)`/`vi.mock(...)` with a default export factory wrapper.
|
|
36
|
+
* Used when the import uses `import Foo from '...'` (FA-1).
|
|
37
|
+
*/
|
|
38
|
+
mockModuleWithDefault(importPath: string, defaultName: string, namedNames: string[]): string;
|
|
32
39
|
}
|
|
33
40
|
export declare class JestAdapter implements TestFrameworkAdapter {
|
|
34
41
|
frameworkImport(): string;
|
|
@@ -42,6 +49,8 @@ export declare class JestAdapter implements TestFrameworkAdapter {
|
|
|
42
49
|
mockResolvedValue(name: string, val: string): string;
|
|
43
50
|
mockReturnValue(name: string, val: string): string;
|
|
44
51
|
mockFnReturnValue(val: string): string;
|
|
52
|
+
spyOn(target: string, method: string): string;
|
|
53
|
+
mockModuleWithDefault(importPath: string, _defaultName: string, namedNames: string[]): string;
|
|
45
54
|
}
|
|
46
55
|
export declare class VitestAdapter implements TestFrameworkAdapter {
|
|
47
56
|
frameworkImport(): string;
|
|
@@ -55,5 +64,7 @@ export declare class VitestAdapter implements TestFrameworkAdapter {
|
|
|
55
64
|
mockResolvedValue(name: string, val: string): string;
|
|
56
65
|
mockReturnValue(name: string, val: string): string;
|
|
57
66
|
mockFnReturnValue(val: string): string;
|
|
67
|
+
spyOn(target: string, method: string): string;
|
|
68
|
+
mockModuleWithDefault(importPath: string, _defaultName: string, namedNames: string[]): string;
|
|
58
69
|
}
|
|
59
70
|
export declare function createAdapter(framework?: "jest" | "vitest"): TestFrameworkAdapter;
|
package/dist/frameworkAdapter.js
CHANGED
|
@@ -42,6 +42,14 @@ class JestAdapter {
|
|
|
42
42
|
mockFnReturnValue(val) {
|
|
43
43
|
return `jest.fn().mockReturnValue(${val})`;
|
|
44
44
|
}
|
|
45
|
+
spyOn(target, method) {
|
|
46
|
+
return `jest.spyOn(${target}, '${method}')`;
|
|
47
|
+
}
|
|
48
|
+
mockModuleWithDefault(importPath, _defaultName, namedNames) {
|
|
49
|
+
const named = namedNames.map((n) => ` ${n}: jest.fn(),`).join("\n");
|
|
50
|
+
const namedPart = named ? `\n${named}\n` : "";
|
|
51
|
+
return `jest.mock('${importPath}', () => ({\n __esModule: true,\n default: jest.fn(),${namedPart}}));`;
|
|
52
|
+
}
|
|
45
53
|
}
|
|
46
54
|
exports.JestAdapter = JestAdapter;
|
|
47
55
|
// ── Vitest adapter ────────────────────────────────────────────────────────────
|
|
@@ -80,6 +88,15 @@ class VitestAdapter {
|
|
|
80
88
|
mockFnReturnValue(val) {
|
|
81
89
|
return `vi.fn().mockReturnValue(${val})`;
|
|
82
90
|
}
|
|
91
|
+
spyOn(target, method) {
|
|
92
|
+
return `vi.spyOn(${target}, '${method}')`;
|
|
93
|
+
}
|
|
94
|
+
// FA-1: Vitest default export factory — wraps the mock in a default-exporting module shape
|
|
95
|
+
mockModuleWithDefault(importPath, _defaultName, namedNames) {
|
|
96
|
+
const named = namedNames.map((n) => ` ${n}: vi.fn(),`).join("\n");
|
|
97
|
+
const namedPart = named ? `\n${named}\n` : "";
|
|
98
|
+
return `vi.mock('${importPath}', () => ({\n default: vi.fn(),${namedPart}}));`;
|
|
99
|
+
}
|
|
83
100
|
}
|
|
84
101
|
exports.VitestAdapter = VitestAdapter;
|
|
85
102
|
// ── Factory ───────────────────────────────────────────────────────────────────
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frameworkAdapter.js","sourceRoot":"","sources":["../src/frameworkAdapter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;
|
|
1
|
+
{"version":3,"file":"frameworkAdapter.js","sourceRoot":"","sources":["../src/frameworkAdapter.ts"],"names":[],"mappings":"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"}
|
package/dist/generator.js
CHANGED
|
@@ -216,7 +216,12 @@ function detectExistingDescribes(content) {
|
|
|
216
216
|
*/
|
|
217
217
|
function buildSignatureFingerprint(scenario) {
|
|
218
218
|
const params = scenario.parameters
|
|
219
|
-
.map((p) =>
|
|
219
|
+
.map((p) => {
|
|
220
|
+
// Sanitize destructured names and complex types to keep the fingerprint single-line
|
|
221
|
+
const name = p.name.startsWith("{") ? "params" : p.name;
|
|
222
|
+
const type = p.type.replace(/\s+/g, "").replace(/[{}]/g, "_");
|
|
223
|
+
return `${name}:${type}`;
|
|
224
|
+
})
|
|
220
225
|
.join(",");
|
|
221
226
|
return `${scenario.functionName}(${params}):${scenario.returnType.replace(/\s+/g, "")}`;
|
|
222
227
|
}
|
|
@@ -452,64 +457,68 @@ function buildClassDescribe(className, methods, mockResult, tableThreshold = 0,
|
|
|
452
457
|
lines.push(` let instance: ${className};`);
|
|
453
458
|
}
|
|
454
459
|
// Generate mock objects for constructor dependencies
|
|
460
|
+
// E-3: declare as `let` at describe scope, assign fresh instances in beforeEach
|
|
455
461
|
const ctorParams = methods[0]?.constructorParams ?? [];
|
|
456
462
|
const ormUsage = methods[0]?.ormUsage;
|
|
457
|
-
const
|
|
463
|
+
const letDeclarations = []; // `let mockFoo: any;` — describe scope
|
|
464
|
+
const beforeEachAssignments = []; // `mockFoo = { ... };` — inside beforeEach
|
|
458
465
|
for (const param of ctorParams) {
|
|
459
466
|
const mockName = `mock${capitalize(param.name)}`;
|
|
467
|
+
letDeclarations.push(` let ${mockName}: any;`);
|
|
460
468
|
// If this constructor param matches the ORM variable, use ORM mocks
|
|
461
469
|
if (ormUsage && (param.name === ormUsage.variableName || param.type.toLowerCase().includes(ormUsage.kind))) {
|
|
462
470
|
const ormMocks = (0, ormMockGenerator_1.generateOrmMocks)(ormUsage);
|
|
463
|
-
// Only alias if the file-level ORM var has a DIFFERENT name from the ctor param mock name
|
|
464
471
|
if (ormMocks.mockVarNames.length > 0 && ormMocks.mockVarNames[0] !== mockName) {
|
|
465
|
-
|
|
472
|
+
beforeEachAssignments.push(` ${mockName} = ${ormMocks.mockVarNames[0]}; // ORM mock`);
|
|
466
473
|
}
|
|
467
474
|
else if (ormMocks.mockVarNames.length === 0) {
|
|
468
|
-
|
|
475
|
+
beforeEachAssignments.push(` ${mockName} = {} as any; // TODO: add mock methods for ${param.type}`);
|
|
469
476
|
}
|
|
470
|
-
// else: same name — variable already declared at file level; no re-declaration needed
|
|
471
477
|
}
|
|
472
478
|
else {
|
|
473
|
-
//
|
|
479
|
+
// E-1: use mockResolvedValue for async repo/service methods
|
|
474
480
|
const typeLower = param.type.toLowerCase();
|
|
481
|
+
const fn = adapter.mockFn();
|
|
482
|
+
const asyncFn = `${fn}.mockResolvedValue(null)`;
|
|
483
|
+
const asyncIdFn = `${fn}.mockResolvedValue({ id: 1 })`;
|
|
475
484
|
if (typeLower.includes("repository") || typeLower.includes("repo")) {
|
|
476
|
-
|
|
477
|
-
|
|
485
|
+
beforeEachAssignments.push(` ${mockName} = { find: ${fn}.mockResolvedValue([]), findOne: ${asyncFn}, findById: ${asyncFn}, ` +
|
|
486
|
+
`save: ${asyncIdFn}, create: ${asyncIdFn}, update: ${asyncIdFn}, delete: ${asyncIdFn}, ` +
|
|
487
|
+
`createQueryBuilder: ${fn}.mockReturnValue({ where: ${fn}.mockReturnThis(), getOne: ${asyncFn}, getMany: ${fn}.mockResolvedValue([]) }) } as any;`);
|
|
478
488
|
}
|
|
479
489
|
else if (typeLower.includes("service")) {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
490
|
+
beforeEachAssignments.push(` ${mockName} = { findAll: ${fn}.mockResolvedValue([]), findOne: ${asyncFn}, findById: ${asyncFn}, ` +
|
|
491
|
+
`create: ${asyncIdFn}, update: ${asyncIdFn}, delete: ${asyncFn} } as any;`);
|
|
492
|
+
beforeEachAssignments.push(` // TODO: add or remove ${param.type} mock methods to match the actual interface`);
|
|
483
493
|
}
|
|
484
494
|
else if (typeLower.includes("logger") || typeLower.includes("log")) {
|
|
485
|
-
|
|
486
|
-
mockDeclarations.push(` const ${mockName} = { log: ${fn}, warn: ${fn}, error: ${fn}, debug: ${fn}, verbose: ${fn} } as any;`);
|
|
495
|
+
beforeEachAssignments.push(` ${mockName} = { log: ${fn}, warn: ${fn}, error: ${fn}, debug: ${fn}, verbose: ${fn} } as any;`);
|
|
487
496
|
}
|
|
488
497
|
else if (typeLower.includes("cache") || typeLower.includes("redis")) {
|
|
489
|
-
|
|
490
|
-
mockDeclarations.push(` const ${mockName} = { get: ${fn}, set: ${fn}, del: ${fn}, exists: ${fn} } as any;`);
|
|
498
|
+
beforeEachAssignments.push(` ${mockName} = { get: ${asyncFn}, set: ${fn}.mockResolvedValue('OK'), del: ${asyncFn}, exists: ${fn}.mockResolvedValue(0) } as any;`);
|
|
491
499
|
}
|
|
492
500
|
else if (typeLower.includes("queue") || typeLower.includes("producer") || typeLower.includes("publisher")) {
|
|
493
|
-
|
|
494
|
-
mockDeclarations.push(` const ${mockName} = { send: ${fn}, emit: ${fn}, publish: ${fn}, add: ${fn} } as any;`);
|
|
501
|
+
beforeEachAssignments.push(` ${mockName} = { send: ${asyncFn}, emit: ${fn}, publish: ${asyncFn}, add: ${asyncFn} } as any;`);
|
|
495
502
|
}
|
|
496
503
|
else {
|
|
497
|
-
|
|
498
|
-
mockDeclarations.push(` const ${mockName} = { } as any; // TODO: add mock methods for ${param.type}`);
|
|
499
|
-
// Suppress the unused variable warning when no methods are known
|
|
500
|
-
mockDeclarations.push(` void ${mockName}; // remove this line once you add method stubs above`);
|
|
504
|
+
beforeEachAssignments.push(` ${mockName} = {} as any; // TODO: add mock methods for ${param.type}`);
|
|
501
505
|
}
|
|
502
506
|
}
|
|
503
507
|
}
|
|
504
|
-
if (
|
|
508
|
+
if (letDeclarations.length > 0) {
|
|
505
509
|
lines.push("");
|
|
506
|
-
for (const decl of
|
|
510
|
+
for (const decl of letDeclarations) {
|
|
507
511
|
lines.push(decl);
|
|
508
512
|
}
|
|
509
513
|
}
|
|
510
514
|
lines.push("");
|
|
511
515
|
lines.push(" beforeEach(() => {");
|
|
512
|
-
|
|
516
|
+
// FA-2: clearAllMocks in beforeEach (keeps implementations, clears call history)
|
|
517
|
+
lines.push(` ${adapter.clearAllMocks()}`);
|
|
518
|
+
// E-3: recreate fresh mock objects so mutations don't leak between tests
|
|
519
|
+
for (const assignment of beforeEachAssignments) {
|
|
520
|
+
lines.push(assignment);
|
|
521
|
+
}
|
|
513
522
|
if (hasInstanceMethods) {
|
|
514
523
|
if (ctorParams.length > 0) {
|
|
515
524
|
const args = ctorParams
|
|
@@ -524,14 +533,16 @@ function buildClassDescribe(className, methods, mockResult, tableThreshold = 0,
|
|
|
524
533
|
lines.push(" });");
|
|
525
534
|
lines.push("");
|
|
526
535
|
lines.push(" afterEach(() => {");
|
|
527
|
-
|
|
536
|
+
// FA-2: resetAllMocks in afterEach (resets implementations too)
|
|
537
|
+
lines.push(` ${adapter.resetAllMocks()}`);
|
|
538
|
+
// T-3: TODO for module-level singleton/cache reset
|
|
539
|
+
lines.push(" // TODO: reset any module-level singletons or caches if the SUT uses them");
|
|
540
|
+
lines.push(" });");
|
|
541
|
+
// T-2: always emit afterAll (not only when ctorParams.length > 0)
|
|
542
|
+
lines.push("");
|
|
543
|
+
lines.push(" afterAll(() => {");
|
|
544
|
+
lines.push(" // TODO: release shared resources (DB connections, file handles, timers)");
|
|
528
545
|
lines.push(" });");
|
|
529
|
-
if (ctorParams.length > 0) {
|
|
530
|
-
lines.push("");
|
|
531
|
-
lines.push(" afterAll(() => {");
|
|
532
|
-
lines.push(" // TODO: release shared resources (DB connections, file handles, timers)");
|
|
533
|
-
lines.push(" });");
|
|
534
|
-
}
|
|
535
546
|
// ── FileType-specific setup ──────────────────────────────────────
|
|
536
547
|
const fileType = methods[0]?.fileType ?? "unknown";
|
|
537
548
|
if (fileType === "controller") {
|
|
@@ -666,7 +677,7 @@ function buildTableBlock(scenario, tableCases, snapshotForComplexTypes = false)
|
|
|
666
677
|
const args = c.argLiterals.join(", ");
|
|
667
678
|
lines.push(` [${JSON.stringify(c.label)}, ${args}],`);
|
|
668
679
|
}
|
|
669
|
-
lines.push(`])('%s', ${isAsync ? "async " : ""}(_label, ${paramNames.join(", ")}) => {`);
|
|
680
|
+
lines.push(`])('%s', ${isAsync ? "async " : ""}(_label, ${paramNames.map(safeName).join(", ")}) => {`);
|
|
670
681
|
// Act
|
|
671
682
|
lines.push(` // Act`);
|
|
672
683
|
const isStatic = !!scenario.isStatic;
|
|
@@ -732,7 +743,7 @@ function buildStandardBlock(scenario, testCase, mockConstName, adapter = (0, fra
|
|
|
732
743
|
// Declare params so the function call compiles
|
|
733
744
|
if (hasParams) {
|
|
734
745
|
for (let i = 0; i < testCase.paramNames.length; i++) {
|
|
735
|
-
lines.push(` const ${testCase.paramNames[i]} = ${testCase.argLiterals[i] ?? "undefined"};`);
|
|
746
|
+
lines.push(` const ${safeName(testCase.paramNames[i])} = ${testCase.argLiterals[i] ?? "undefined"};`);
|
|
736
747
|
}
|
|
737
748
|
}
|
|
738
749
|
for (const l of mockSetupLines)
|
|
@@ -744,14 +755,14 @@ function buildStandardBlock(scenario, testCase, mockConstName, adapter = (0, fra
|
|
|
744
755
|
lines.push(" // Arrange");
|
|
745
756
|
const mockRef = `mocks.${mockConstName}.${caseKey}`;
|
|
746
757
|
for (const name of testCase.paramNames) {
|
|
747
|
-
lines.push(` const ${name} = ${mockRef}.${name};`);
|
|
758
|
+
lines.push(` const ${safeName(name)} = ${mockRef}.${safeName(name)};`);
|
|
748
759
|
}
|
|
749
760
|
lines.push("");
|
|
750
761
|
}
|
|
751
762
|
else if (testCase.argLiterals.length > 0) {
|
|
752
763
|
lines.push(" // Arrange");
|
|
753
764
|
for (let i = 0; i < testCase.paramNames.length; i++) {
|
|
754
|
-
const name = testCase.paramNames[i];
|
|
765
|
+
const name = safeName(testCase.paramNames[i]);
|
|
755
766
|
const literal = testCase.argLiterals[i] ?? "undefined";
|
|
756
767
|
lines.push(` const ${name} = ${literal};`);
|
|
757
768
|
}
|
|
@@ -759,7 +770,7 @@ function buildStandardBlock(scenario, testCase, mockConstName, adapter = (0, fra
|
|
|
759
770
|
}
|
|
760
771
|
// ── Act ──────────────────────────────────────────────────────────
|
|
761
772
|
lines.push(" // Act");
|
|
762
|
-
const argsStr = testCase.paramNames.join(", ");
|
|
773
|
+
const argsStr = testCase.paramNames.map(safeName).join(", ");
|
|
763
774
|
const caller = isStatic
|
|
764
775
|
? `${scenario.className}.${fnName}`
|
|
765
776
|
: isMethod ? `instance.${fnName}` : fnName;
|
|
@@ -817,14 +828,14 @@ function buildThrowsBlock(scenario, testCase, mockConstName) {
|
|
|
817
828
|
lines.push(" // Arrange");
|
|
818
829
|
const mockRef = `mocks.${mockConstName}.${caseKey}`;
|
|
819
830
|
for (const name of testCase.paramNames) {
|
|
820
|
-
lines.push(` const ${name} = ${mockRef}.${name};`);
|
|
831
|
+
lines.push(` const ${safeName(name)} = ${mockRef}.${safeName(name)};`);
|
|
821
832
|
}
|
|
822
833
|
lines.push("");
|
|
823
834
|
}
|
|
824
835
|
else if (testCase.argLiterals.length > 0) {
|
|
825
836
|
lines.push(" // Arrange");
|
|
826
837
|
for (let i = 0; i < testCase.paramNames.length; i++) {
|
|
827
|
-
const name = testCase.paramNames[i];
|
|
838
|
+
const name = safeName(testCase.paramNames[i]);
|
|
828
839
|
const literal = testCase.argLiterals[i] ?? "undefined";
|
|
829
840
|
lines.push(` const ${name} = ${literal};`);
|
|
830
841
|
}
|
|
@@ -832,7 +843,7 @@ function buildThrowsBlock(scenario, testCase, mockConstName) {
|
|
|
832
843
|
}
|
|
833
844
|
// ── Act & Assert ────────────────────────────────────────────────
|
|
834
845
|
lines.push(" // Act & Assert");
|
|
835
|
-
const argsStr = testCase.paramNames.join(", ");
|
|
846
|
+
const argsStr = testCase.paramNames.map(safeName).join(", ");
|
|
836
847
|
const caller = isStatic
|
|
837
848
|
? `${scenario.className}.${fnName}`
|
|
838
849
|
: isMethod ? `instance.${fnName}` : fnName;
|
|
@@ -854,14 +865,14 @@ function buildRejectsBlock(scenario, testCase, mockConstName) {
|
|
|
854
865
|
lines.push(" // Arrange");
|
|
855
866
|
const mockRef = `mocks.${mockConstName}.${caseKey}`;
|
|
856
867
|
for (const name of testCase.paramNames) {
|
|
857
|
-
lines.push(` const ${name} = ${mockRef}.${name};`);
|
|
868
|
+
lines.push(` const ${safeName(name)} = ${mockRef}.${safeName(name)};`);
|
|
858
869
|
}
|
|
859
870
|
lines.push("");
|
|
860
871
|
}
|
|
861
872
|
else if (testCase.argLiterals.length > 0) {
|
|
862
873
|
lines.push(" // Arrange");
|
|
863
874
|
for (let i = 0; i < testCase.paramNames.length; i++) {
|
|
864
|
-
const name = testCase.paramNames[i];
|
|
875
|
+
const name = safeName(testCase.paramNames[i]);
|
|
865
876
|
const literal = testCase.argLiterals[i] ?? "undefined";
|
|
866
877
|
lines.push(` const ${name} = ${literal};`);
|
|
867
878
|
}
|
|
@@ -869,7 +880,7 @@ function buildRejectsBlock(scenario, testCase, mockConstName) {
|
|
|
869
880
|
}
|
|
870
881
|
// ── Act & Assert ────────────────────────────────────────────────
|
|
871
882
|
lines.push(" // Act & Assert");
|
|
872
|
-
const argsStr = testCase.paramNames.join(", ");
|
|
883
|
+
const argsStr = testCase.paramNames.map(safeName).join(", ");
|
|
873
884
|
const caller = isStatic
|
|
874
885
|
? `${scenario.className}.${fnName}`
|
|
875
886
|
: isMethod ? `instance.${fnName}` : fnName;
|
|
@@ -1098,6 +1109,10 @@ function camelCase(label) {
|
|
|
1098
1109
|
: word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
1099
1110
|
.join("");
|
|
1100
1111
|
}
|
|
1112
|
+
/** Sanitize a parameter name for use as a JS identifier. Destructured patterns like "{ a, b }" become "params". */
|
|
1113
|
+
function safeName(name) {
|
|
1114
|
+
return name.startsWith("{") ? "params" : name;
|
|
1115
|
+
}
|
|
1101
1116
|
function capitalize(str) {
|
|
1102
1117
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
1103
1118
|
}
|