test-gen-js 0.1.1
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/CHANGELOG.md +71 -0
- package/LICENSE +22 -0
- package/README.md +538 -0
- package/bin/cli.js +4 -0
- package/dist/analyzer/componentAnalyzer.d.ts +12 -0
- package/dist/analyzer/componentAnalyzer.d.ts.map +1 -0
- package/dist/analyzer/componentAnalyzer.js +223 -0
- package/dist/analyzer/componentAnalyzer.js.map +1 -0
- package/dist/analyzer/fileAnalyzer.d.ts +17 -0
- package/dist/analyzer/fileAnalyzer.d.ts.map +1 -0
- package/dist/analyzer/fileAnalyzer.js +201 -0
- package/dist/analyzer/fileAnalyzer.js.map +1 -0
- package/dist/analyzer/functionAnalyzer.d.ts +12 -0
- package/dist/analyzer/functionAnalyzer.d.ts.map +1 -0
- package/dist/analyzer/functionAnalyzer.js +184 -0
- package/dist/analyzer/functionAnalyzer.js.map +1 -0
- package/dist/analyzer/index.d.ts +7 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +14 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -0
- package/dist/generator/index.d.ts +6 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +12 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/mockGenerator.d.ts +14 -0
- package/dist/generator/mockGenerator.d.ts.map +1 -0
- package/dist/generator/mockGenerator.js +123 -0
- package/dist/generator/mockGenerator.js.map +1 -0
- package/dist/generator/testGenerator.d.ts +14 -0
- package/dist/generator/testGenerator.d.ts.map +1 -0
- package/dist/generator/testGenerator.js +301 -0
- package/dist/generator/testGenerator.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/astParser.d.ts +15 -0
- package/dist/parser/astParser.d.ts.map +1 -0
- package/dist/parser/astParser.js +100 -0
- package/dist/parser/astParser.js.map +1 -0
- package/dist/parser/index.d.ts +6 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +12 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/typeExtractor.d.ts +14 -0
- package/dist/parser/typeExtractor.d.ts.map +1 -0
- package/dist/parser/typeExtractor.js +165 -0
- package/dist/parser/typeExtractor.js.map +1 -0
- package/dist/templates/component.ejs +67 -0
- package/dist/templates/function.ejs +59 -0
- package/dist/templates/snapshot.ejs +48 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/fileUtils.d.ts +43 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +109 -0
- package/dist/utils/fileUtils.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +22 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/naming.d.ts +37 -0
- package/dist/utils/naming.d.ts.map +1 -0
- package/dist/utils/naming.js +73 -0
- package/dist/utils/naming.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyzer module - Analyzes parsed AST to extract component/function information
|
|
3
|
+
*/
|
|
4
|
+
export { analyzeFile, analyzeDirectory } from './fileAnalyzer';
|
|
5
|
+
export { analyzeComponent } from './componentAnalyzer';
|
|
6
|
+
export { analyzeFunction } from './functionAnalyzer';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Analyzer module - Analyzes parsed AST to extract component/function information
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.analyzeFunction = exports.analyzeComponent = exports.analyzeDirectory = exports.analyzeFile = void 0;
|
|
7
|
+
var fileAnalyzer_1 = require("./fileAnalyzer");
|
|
8
|
+
Object.defineProperty(exports, "analyzeFile", { enumerable: true, get: function () { return fileAnalyzer_1.analyzeFile; } });
|
|
9
|
+
Object.defineProperty(exports, "analyzeDirectory", { enumerable: true, get: function () { return fileAnalyzer_1.analyzeDirectory; } });
|
|
10
|
+
var componentAnalyzer_1 = require("./componentAnalyzer");
|
|
11
|
+
Object.defineProperty(exports, "analyzeComponent", { enumerable: true, get: function () { return componentAnalyzer_1.analyzeComponent; } });
|
|
12
|
+
var functionAnalyzer_1 = require("./functionAnalyzer");
|
|
13
|
+
Object.defineProperty(exports, "analyzeFunction", { enumerable: true, get: function () { return functionAnalyzer_1.analyzeFunction; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,+CAA+D;AAAtD,2GAAA,WAAW,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AACtC,yDAAuD;AAA9C,qHAAA,gBAAgB,OAAA;AACzB,uDAAqD;AAA5C,mHAAA,eAAe,OAAA"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const ora_1 = __importDefault(require("ora"));
|
|
10
|
+
const analyzer_1 = require("./analyzer");
|
|
11
|
+
const generator_1 = require("./generator");
|
|
12
|
+
const program = new commander_1.Command();
|
|
13
|
+
program
|
|
14
|
+
.name('test-gen-js')
|
|
15
|
+
.description('Auto-generate test boilerplate code for JavaScript/TypeScript projects')
|
|
16
|
+
.version('0.1.0');
|
|
17
|
+
// Generate command
|
|
18
|
+
program
|
|
19
|
+
.command('generate <file>')
|
|
20
|
+
.alias('g')
|
|
21
|
+
.description('Generate test file for a component or function')
|
|
22
|
+
.option('-o, --output <path>', 'Output path for test file')
|
|
23
|
+
.option('-t, --template <type>', 'Template type: component | function | hook', 'auto')
|
|
24
|
+
.option('--snapshot', 'Include snapshot tests', false)
|
|
25
|
+
.option('--mock', 'Auto-generate mocks for dependencies', true)
|
|
26
|
+
.option('--overwrite', 'Overwrite existing test file', false)
|
|
27
|
+
.action(async (file, options) => {
|
|
28
|
+
const spinner = (0, ora_1.default)('Analyzing file...').start();
|
|
29
|
+
try {
|
|
30
|
+
// Analyze the source file
|
|
31
|
+
const analysis = await (0, analyzer_1.analyzeFile)(file);
|
|
32
|
+
spinner.text = 'Generating tests...';
|
|
33
|
+
// Generate test code
|
|
34
|
+
const result = await (0, generator_1.generateTest)(analysis, {
|
|
35
|
+
output: options.output,
|
|
36
|
+
snapshot: options.snapshot,
|
|
37
|
+
mock: options.mock,
|
|
38
|
+
overwrite: options.overwrite,
|
|
39
|
+
});
|
|
40
|
+
spinner.succeed(chalk_1.default.green('Test file generated!'));
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log(chalk_1.default.cyan('📄 Source:'), file);
|
|
43
|
+
console.log(chalk_1.default.cyan('📝 Output:'), result.outputPath);
|
|
44
|
+
console.log(chalk_1.default.cyan('📊 Action:'), result.action);
|
|
45
|
+
console.log('');
|
|
46
|
+
if (analysis.components.length > 0) {
|
|
47
|
+
console.log(chalk_1.default.yellow('Components found:'));
|
|
48
|
+
analysis.components.forEach((c) => {
|
|
49
|
+
console.log(` - ${c.name} (${c.props.length} props, ${c.hooks.length} hooks)`);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (analysis.functions.length > 0) {
|
|
53
|
+
console.log(chalk_1.default.yellow('Functions found:'));
|
|
54
|
+
analysis.functions.forEach((f) => {
|
|
55
|
+
console.log(` - ${f.name}(${f.params.map((p) => p.name).join(', ')})`);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
spinner.fail(chalk_1.default.red('Failed to generate tests'));
|
|
61
|
+
if (error instanceof Error) {
|
|
62
|
+
console.error(chalk_1.default.red(error.message));
|
|
63
|
+
}
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// Scan command
|
|
68
|
+
program
|
|
69
|
+
.command('scan <directory>')
|
|
70
|
+
.alias('s')
|
|
71
|
+
.description('Scan directory and generate tests for all files')
|
|
72
|
+
.option('--dry-run', 'Preview without creating files', false)
|
|
73
|
+
.option('--pattern <glob>', 'File pattern to match', '**/*.{ts,tsx,js,jsx}')
|
|
74
|
+
.option('--exclude <patterns...>', 'Patterns to exclude', ['node_modules', 'dist', '*.test.*', '*.spec.*'])
|
|
75
|
+
.action(async (directory, options) => {
|
|
76
|
+
const spinner = (0, ora_1.default)('Scanning directory...').start();
|
|
77
|
+
try {
|
|
78
|
+
// TODO: Implement directory scanning
|
|
79
|
+
spinner.info(chalk_1.default.yellow('Directory scanning is coming in v0.2.0'));
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log(chalk_1.default.cyan('Directory:'), directory);
|
|
82
|
+
console.log(chalk_1.default.cyan('Pattern:'), options.pattern);
|
|
83
|
+
console.log(chalk_1.default.cyan('Exclude:'), options.exclude.join(', '));
|
|
84
|
+
console.log(chalk_1.default.cyan('Dry run:'), options.dryRun);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
spinner.fail(chalk_1.default.red('Failed to scan directory'));
|
|
88
|
+
if (error instanceof Error) {
|
|
89
|
+
console.error(chalk_1.default.red(error.message));
|
|
90
|
+
}
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// Init command
|
|
95
|
+
program
|
|
96
|
+
.command('init')
|
|
97
|
+
.description('Initialize test-gen-js configuration')
|
|
98
|
+
.action(async () => {
|
|
99
|
+
const spinner = (0, ora_1.default)('Creating configuration...').start();
|
|
100
|
+
try {
|
|
101
|
+
// TODO: Implement config initialization
|
|
102
|
+
spinner.info(chalk_1.default.yellow('Configuration file is coming in v0.2.0'));
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
spinner.fail(chalk_1.default.red('Failed to create configuration'));
|
|
106
|
+
if (error instanceof Error) {
|
|
107
|
+
console.error(chalk_1.default.red(error.message));
|
|
108
|
+
}
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
program.parse();
|
|
113
|
+
//# 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":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generator module - Generates test code from analyzed information
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateMocks = exports.generateTests = exports.generateTest = void 0;
|
|
7
|
+
var testGenerator_1 = require("./testGenerator");
|
|
8
|
+
Object.defineProperty(exports, "generateTest", { enumerable: true, get: function () { return testGenerator_1.generateTest; } });
|
|
9
|
+
Object.defineProperty(exports, "generateTests", { enumerable: true, get: function () { return testGenerator_1.generateTests; } });
|
|
10
|
+
var mockGenerator_1 = require("./mockGenerator");
|
|
11
|
+
Object.defineProperty(exports, "generateMocks", { enumerable: true, get: function () { return mockGenerator_1.generateMocks; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,iDAA8D;AAArD,6GAAA,YAAY,OAAA;AAAE,8GAAA,aAAa,OAAA;AACpC,iDAAgD;AAAvC,8GAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock Generator
|
|
3
|
+
* Generates mock code for dependencies
|
|
4
|
+
*/
|
|
5
|
+
import type { ImportInfo } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* Generate mock statements for imports
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateMocks(imports: ImportInfo[]): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Generate mock for a hook
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateHookMock(hookName: string): string;
|
|
14
|
+
//# sourceMappingURL=mockGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockGenerator.d.ts","sourceRoot":"","sources":["../../src/generator/mockGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAW7D;AAmGD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYzD"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mock Generator
|
|
4
|
+
* Generates mock code for dependencies
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.generateMocks = generateMocks;
|
|
8
|
+
exports.generateHookMock = generateHookMock;
|
|
9
|
+
/**
|
|
10
|
+
* Generate mock statements for imports
|
|
11
|
+
*/
|
|
12
|
+
function generateMocks(imports) {
|
|
13
|
+
const mocks = [];
|
|
14
|
+
for (const imp of imports) {
|
|
15
|
+
const mock = generateMockForImport(imp);
|
|
16
|
+
if (mock) {
|
|
17
|
+
mocks.push(mock);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return mocks;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Generate mock for a single import
|
|
24
|
+
*/
|
|
25
|
+
function generateMockForImport(imp) {
|
|
26
|
+
// Skip React and testing library imports
|
|
27
|
+
if (shouldSkipMock(imp.source)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
// Navigation mocks
|
|
31
|
+
if (imp.source === '@react-navigation/native') {
|
|
32
|
+
return `jest.mock('@react-navigation/native', () => ({
|
|
33
|
+
useNavigation: () => ({
|
|
34
|
+
navigate: jest.fn(),
|
|
35
|
+
goBack: jest.fn(),
|
|
36
|
+
reset: jest.fn(),
|
|
37
|
+
}),
|
|
38
|
+
useRoute: () => ({
|
|
39
|
+
params: {},
|
|
40
|
+
}),
|
|
41
|
+
useFocusEffect: jest.fn(),
|
|
42
|
+
}));`;
|
|
43
|
+
}
|
|
44
|
+
if (imp.source === '@react-navigation/stack') {
|
|
45
|
+
return `jest.mock('@react-navigation/stack', () => ({
|
|
46
|
+
createStackNavigator: jest.fn(() => ({
|
|
47
|
+
Navigator: ({ children }: any) => children,
|
|
48
|
+
Screen: ({ children }: any) => children,
|
|
49
|
+
})),
|
|
50
|
+
}));`;
|
|
51
|
+
}
|
|
52
|
+
// Redux mocks
|
|
53
|
+
if (imp.source === 'react-redux') {
|
|
54
|
+
return `jest.mock('react-redux', () => ({
|
|
55
|
+
useSelector: jest.fn(),
|
|
56
|
+
useDispatch: () => jest.fn(),
|
|
57
|
+
Provider: ({ children }: any) => children,
|
|
58
|
+
}));`;
|
|
59
|
+
}
|
|
60
|
+
// Async storage mock
|
|
61
|
+
if (imp.source === '@react-native-async-storage/async-storage') {
|
|
62
|
+
return `jest.mock('@react-native-async-storage/async-storage', () => ({
|
|
63
|
+
setItem: jest.fn(() => Promise.resolve()),
|
|
64
|
+
getItem: jest.fn(() => Promise.resolve(null)),
|
|
65
|
+
removeItem: jest.fn(() => Promise.resolve()),
|
|
66
|
+
clear: jest.fn(() => Promise.resolve()),
|
|
67
|
+
}));`;
|
|
68
|
+
}
|
|
69
|
+
// Animated mock for React Native
|
|
70
|
+
if (imp.source === 'react-native' && imp.specifiers.includes('Animated')) {
|
|
71
|
+
return `jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');`;
|
|
72
|
+
}
|
|
73
|
+
// Generic mock for other imports
|
|
74
|
+
if (imp.source.startsWith('.') || imp.source.startsWith('@/') || imp.source.startsWith('~/')) {
|
|
75
|
+
// Local imports - generate basic mock
|
|
76
|
+
const mockExports = imp.specifiers
|
|
77
|
+
.map((spec) => {
|
|
78
|
+
if (spec.startsWith('* as')) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return ` ${spec}: jest.fn()`;
|
|
82
|
+
})
|
|
83
|
+
.filter(Boolean)
|
|
84
|
+
.join(',\n');
|
|
85
|
+
if (mockExports) {
|
|
86
|
+
return `jest.mock('${imp.source}', () => ({
|
|
87
|
+
${mockExports},
|
|
88
|
+
}));`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if import should be skipped for mocking
|
|
95
|
+
*/
|
|
96
|
+
function shouldSkipMock(source) {
|
|
97
|
+
const skipList = [
|
|
98
|
+
'react',
|
|
99
|
+
'react-native',
|
|
100
|
+
'@testing-library/react',
|
|
101
|
+
'@testing-library/react-native',
|
|
102
|
+
'@testing-library/jest-native',
|
|
103
|
+
'jest',
|
|
104
|
+
'@jest',
|
|
105
|
+
];
|
|
106
|
+
return skipList.some((skip) => source === skip || source.startsWith(`${skip}/`));
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Generate mock for a hook
|
|
110
|
+
*/
|
|
111
|
+
function generateHookMock(hookName) {
|
|
112
|
+
// Common hooks
|
|
113
|
+
const hookMocks = {
|
|
114
|
+
useState: `jest.spyOn(React, 'useState').mockImplementation((init) => [init, jest.fn()]);`,
|
|
115
|
+
useEffect: `jest.spyOn(React, 'useEffect').mockImplementation((f) => f());`,
|
|
116
|
+
useContext: `jest.spyOn(React, 'useContext').mockReturnValue({});`,
|
|
117
|
+
useRef: `jest.spyOn(React, 'useRef').mockReturnValue({ current: null });`,
|
|
118
|
+
useMemo: `jest.spyOn(React, 'useMemo').mockImplementation((f) => f());`,
|
|
119
|
+
useCallback: `jest.spyOn(React, 'useCallback').mockImplementation((f) => f);`,
|
|
120
|
+
};
|
|
121
|
+
return hookMocks[hookName] || `// TODO: Mock ${hookName}`;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=mockGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockGenerator.js","sourceRoot":"","sources":["../../src/generator/mockGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Generator
|
|
3
|
+
* Generates test code from analyzed file information
|
|
4
|
+
*/
|
|
5
|
+
import type { FileAnalysis, GeneratorOptions, GeneratedTest } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* Generate test for a single file analysis
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateTest(analysis: FileAnalysis, options?: GeneratorOptions): Promise<GeneratedTest>;
|
|
10
|
+
/**
|
|
11
|
+
* Generate tests for multiple file analyses
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateTests(analyses: FileAnalysis[], options?: GeneratorOptions): Promise<GeneratedTest[]>;
|
|
14
|
+
//# sourceMappingURL=testGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testGenerator.d.ts","sourceRoot":"","sources":["../../src/generator/testGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAM9E;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,YAAY,EACtB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,aAAa,CAAC,CA+CxB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC,CAS1B"}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Test Generator
|
|
4
|
+
* Generates test code from analyzed file information
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.generateTest = generateTest;
|
|
11
|
+
exports.generateTests = generateTests;
|
|
12
|
+
const ejs_1 = __importDefault(require("ejs"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
15
|
+
const typeExtractor_1 = require("../parser/typeExtractor");
|
|
16
|
+
// Templates directory
|
|
17
|
+
const TEMPLATES_DIR = path_1.default.join(__dirname, '../templates');
|
|
18
|
+
/**
|
|
19
|
+
* Generate test for a single file analysis
|
|
20
|
+
*/
|
|
21
|
+
async function generateTest(analysis, options = {}) {
|
|
22
|
+
const { output, snapshot = false, mock = true, testSuffix = '.test', overwrite = false, } = options;
|
|
23
|
+
// Determine output path
|
|
24
|
+
const ext = path_1.default.extname(analysis.filePath);
|
|
25
|
+
const baseName = path_1.default.basename(analysis.filePath, ext);
|
|
26
|
+
const dirName = path_1.default.dirname(analysis.filePath);
|
|
27
|
+
const outputPath = output || path_1.default.join(dirName, `${baseName}${testSuffix}${ext}`);
|
|
28
|
+
// Check if file exists
|
|
29
|
+
const exists = await fs_extra_1.default.pathExists(outputPath);
|
|
30
|
+
if (exists && !overwrite) {
|
|
31
|
+
return {
|
|
32
|
+
code: '',
|
|
33
|
+
outputPath,
|
|
34
|
+
sourcePath: analysis.filePath,
|
|
35
|
+
action: 'skipped',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Generate test code
|
|
39
|
+
let code;
|
|
40
|
+
if (analysis.components.length > 0) {
|
|
41
|
+
code = await generateComponentTest(analysis, { snapshot, mock });
|
|
42
|
+
}
|
|
43
|
+
else if (analysis.functions.length > 0) {
|
|
44
|
+
code = await generateFunctionTest(analysis, { mock });
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error('No components or functions found to generate tests for');
|
|
48
|
+
}
|
|
49
|
+
// Write to file
|
|
50
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(outputPath));
|
|
51
|
+
await fs_extra_1.default.writeFile(outputPath, code, 'utf-8');
|
|
52
|
+
return {
|
|
53
|
+
code,
|
|
54
|
+
outputPath,
|
|
55
|
+
sourcePath: analysis.filePath,
|
|
56
|
+
action: exists ? 'updated' : 'created',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Generate tests for multiple file analyses
|
|
61
|
+
*/
|
|
62
|
+
async function generateTests(analyses, options = {}) {
|
|
63
|
+
const results = [];
|
|
64
|
+
for (const analysis of analyses) {
|
|
65
|
+
const result = await generateTest(analysis, options);
|
|
66
|
+
results.push(result);
|
|
67
|
+
}
|
|
68
|
+
return results;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Generate test code for components
|
|
72
|
+
*/
|
|
73
|
+
async function generateComponentTest(analysis, options) {
|
|
74
|
+
const templatePath = path_1.default.join(TEMPLATES_DIR, 'component.ejs');
|
|
75
|
+
// Check if custom template exists, otherwise use default
|
|
76
|
+
let template;
|
|
77
|
+
if (await fs_extra_1.default.pathExists(templatePath)) {
|
|
78
|
+
template = await fs_extra_1.default.readFile(templatePath, 'utf-8');
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
template = getDefaultComponentTemplate();
|
|
82
|
+
}
|
|
83
|
+
// Prepare template data
|
|
84
|
+
const data = {
|
|
85
|
+
analysis,
|
|
86
|
+
options,
|
|
87
|
+
helpers: {
|
|
88
|
+
generateMockValue: typeExtractor_1.generateMockValue,
|
|
89
|
+
generatePropValue,
|
|
90
|
+
getRelativeImport,
|
|
91
|
+
getTestingLibrary,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
return ejs_1.default.render(template, data);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Generate test code for functions
|
|
98
|
+
*/
|
|
99
|
+
async function generateFunctionTest(analysis, options) {
|
|
100
|
+
const templatePath = path_1.default.join(TEMPLATES_DIR, 'function.ejs');
|
|
101
|
+
// Check if custom template exists, otherwise use default
|
|
102
|
+
let template;
|
|
103
|
+
if (await fs_extra_1.default.pathExists(templatePath)) {
|
|
104
|
+
template = await fs_extra_1.default.readFile(templatePath, 'utf-8');
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
template = getDefaultFunctionTemplate();
|
|
108
|
+
}
|
|
109
|
+
// Prepare template data
|
|
110
|
+
const data = {
|
|
111
|
+
analysis,
|
|
112
|
+
options,
|
|
113
|
+
helpers: {
|
|
114
|
+
generateMockValue: typeExtractor_1.generateMockValue,
|
|
115
|
+
getRelativeImport,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
return ejs_1.default.render(template, data);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Generate a prop value for testing
|
|
122
|
+
*/
|
|
123
|
+
function generatePropValue(prop) {
|
|
124
|
+
// Event handlers
|
|
125
|
+
if (prop.name.startsWith('on') && prop.name.length > 2) {
|
|
126
|
+
return 'jest.fn()';
|
|
127
|
+
}
|
|
128
|
+
// Common prop patterns
|
|
129
|
+
if (prop.name === 'children')
|
|
130
|
+
return "'Test Children'";
|
|
131
|
+
if (prop.name === 'className' || prop.name === 'style')
|
|
132
|
+
return "{}";
|
|
133
|
+
if (prop.name === 'testID' || prop.name === 'data-testid')
|
|
134
|
+
return "'test-id'";
|
|
135
|
+
if (prop.name.toLowerCase().includes('id'))
|
|
136
|
+
return "'test-id'";
|
|
137
|
+
if (prop.name.toLowerCase().includes('name'))
|
|
138
|
+
return "'Test Name'";
|
|
139
|
+
if (prop.name.toLowerCase().includes('title'))
|
|
140
|
+
return "'Test Title'";
|
|
141
|
+
if (prop.name.toLowerCase().includes('label'))
|
|
142
|
+
return "'Test Label'";
|
|
143
|
+
if (prop.name.toLowerCase().includes('text'))
|
|
144
|
+
return "'Test Text'";
|
|
145
|
+
if (prop.name.toLowerCase().includes('disabled'))
|
|
146
|
+
return 'false';
|
|
147
|
+
if (prop.name.toLowerCase().includes('loading'))
|
|
148
|
+
return 'false';
|
|
149
|
+
if (prop.name.toLowerCase().includes('visible'))
|
|
150
|
+
return 'true';
|
|
151
|
+
if (prop.name.toLowerCase().includes('active'))
|
|
152
|
+
return 'true';
|
|
153
|
+
return (0, typeExtractor_1.generateMockValue)(prop.type);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get relative import path
|
|
157
|
+
*/
|
|
158
|
+
function getRelativeImport(testPath, sourcePath) {
|
|
159
|
+
const relative = path_1.default.relative(path_1.default.dirname(testPath), sourcePath);
|
|
160
|
+
const ext = path_1.default.extname(relative);
|
|
161
|
+
const withoutExt = relative.slice(0, -ext.length);
|
|
162
|
+
// Ensure it starts with ./
|
|
163
|
+
if (!withoutExt.startsWith('.')) {
|
|
164
|
+
return `./${withoutExt}`;
|
|
165
|
+
}
|
|
166
|
+
return withoutExt;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get the appropriate testing library import based on framework
|
|
170
|
+
*/
|
|
171
|
+
function getTestingLibrary(framework) {
|
|
172
|
+
switch (framework) {
|
|
173
|
+
case 'react-native':
|
|
174
|
+
return {
|
|
175
|
+
package: '@testing-library/react-native',
|
|
176
|
+
imports: ['render', 'fireEvent', 'screen', 'waitFor'],
|
|
177
|
+
};
|
|
178
|
+
case 'react':
|
|
179
|
+
return {
|
|
180
|
+
package: '@testing-library/react',
|
|
181
|
+
imports: ['render', 'fireEvent', 'screen', 'waitFor'],
|
|
182
|
+
};
|
|
183
|
+
default:
|
|
184
|
+
return {
|
|
185
|
+
package: '@testing-library/react',
|
|
186
|
+
imports: ['render', 'fireEvent', 'screen', 'waitFor'],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Default component test template
|
|
192
|
+
*/
|
|
193
|
+
function getDefaultComponentTemplate() {
|
|
194
|
+
return `<%
|
|
195
|
+
const testLib = helpers.getTestingLibrary(analysis.framework);
|
|
196
|
+
const sourceImport = helpers.getRelativeImport(analysis.filePath.replace(/\\.(tsx?|jsx?)$/, '.test.$1'), analysis.filePath);
|
|
197
|
+
%>
|
|
198
|
+
import React from 'react';
|
|
199
|
+
import { <%= testLib.imports.join(', ') %> } from '<%= testLib.package %>';
|
|
200
|
+
<% analysis.components.forEach(component => { %>
|
|
201
|
+
import { <%= component.name %> } from '<%= sourceImport %>';
|
|
202
|
+
<% }); %>
|
|
203
|
+
|
|
204
|
+
<% analysis.components.forEach(component => { %>
|
|
205
|
+
describe('<%= component.name %>', () => {
|
|
206
|
+
const defaultProps = {
|
|
207
|
+
<% component.props.forEach((prop, index) => { %>
|
|
208
|
+
<%= prop.name %>: <%= helpers.generatePropValue(prop) %><%= index < component.props.length - 1 ? ',' : '' %>
|
|
209
|
+
<% }); %>
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
beforeEach(() => {
|
|
213
|
+
jest.clearAllMocks();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('renders without crashing', () => {
|
|
217
|
+
render(<<%= component.name %> {...defaultProps} />);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
<% if (options.snapshot) { %>
|
|
221
|
+
it('matches snapshot', () => {
|
|
222
|
+
const { toJSON } = render(<<%= component.name %> {...defaultProps} />);
|
|
223
|
+
expect(toJSON()).toMatchSnapshot();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
<% } %>
|
|
227
|
+
<% component.events.forEach(event => { %>
|
|
228
|
+
it('calls <%= event %> when triggered', () => {
|
|
229
|
+
const handler = jest.fn();
|
|
230
|
+
render(<<%= component.name %> {...defaultProps} <%= event %>={handler} />);
|
|
231
|
+
|
|
232
|
+
// TODO: Trigger the <%= event %> event
|
|
233
|
+
// fireEvent.press(screen.getByTestId('...'));
|
|
234
|
+
|
|
235
|
+
// expect(handler).toHaveBeenCalled();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
<% }); %>
|
|
239
|
+
<% component.hooks.forEach(hook => { %>
|
|
240
|
+
// TODO: Test <%= hook %> behavior
|
|
241
|
+
it('uses <%= hook %> correctly', () => {
|
|
242
|
+
render(<<%= component.name %> {...defaultProps} />);
|
|
243
|
+
// Add assertions for <%= hook %>
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
<% }); %>
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
<% }); %>
|
|
250
|
+
`;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Default function test template
|
|
254
|
+
*/
|
|
255
|
+
function getDefaultFunctionTemplate() {
|
|
256
|
+
return `<%
|
|
257
|
+
const sourceImport = helpers.getRelativeImport(analysis.filePath.replace(/\\.(tsx?|jsx?)$/, '.test.$1'), analysis.filePath);
|
|
258
|
+
%>
|
|
259
|
+
<% analysis.functions.forEach(func => { %>
|
|
260
|
+
import { <%= func.name %> } from '<%= sourceImport %>';
|
|
261
|
+
<% }); %>
|
|
262
|
+
|
|
263
|
+
<% analysis.functions.forEach(func => { %>
|
|
264
|
+
describe('<%= func.name %>', () => {
|
|
265
|
+
beforeEach(() => {
|
|
266
|
+
jest.clearAllMocks();
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
<% if (func.isAsync) { %>
|
|
270
|
+
it('should resolve successfully', async () => {
|
|
271
|
+
const result = await <%= func.name %>(<%= func.params.map(p => helpers.generateMockValue(p.type)).join(', ') %>);
|
|
272
|
+
|
|
273
|
+
// TODO: Add assertions
|
|
274
|
+
expect(result).toBeDefined();
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('should handle errors', async () => {
|
|
278
|
+
// TODO: Mock error scenario
|
|
279
|
+
// await expect(<%= func.name %>()).rejects.toThrow();
|
|
280
|
+
});
|
|
281
|
+
<% } else { %>
|
|
282
|
+
it('should return expected result', () => {
|
|
283
|
+
const result = <%= func.name %>(<%= func.params.map(p => helpers.generateMockValue(p.type)).join(', ') %>);
|
|
284
|
+
|
|
285
|
+
// TODO: Add assertions
|
|
286
|
+
expect(result).toBeDefined();
|
|
287
|
+
});
|
|
288
|
+
<% } %>
|
|
289
|
+
|
|
290
|
+
<% func.params.forEach(param => { %>
|
|
291
|
+
it('should handle <%= param.name %> parameter', () => {
|
|
292
|
+
// TODO: Test with different <%= param.name %> values
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
<% }); %>
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
<% }); %>
|
|
299
|
+
`;
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=testGenerator.js.map
|