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.
Files changed (72) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/LICENSE +22 -0
  3. package/README.md +538 -0
  4. package/bin/cli.js +4 -0
  5. package/dist/analyzer/componentAnalyzer.d.ts +12 -0
  6. package/dist/analyzer/componentAnalyzer.d.ts.map +1 -0
  7. package/dist/analyzer/componentAnalyzer.js +223 -0
  8. package/dist/analyzer/componentAnalyzer.js.map +1 -0
  9. package/dist/analyzer/fileAnalyzer.d.ts +17 -0
  10. package/dist/analyzer/fileAnalyzer.d.ts.map +1 -0
  11. package/dist/analyzer/fileAnalyzer.js +201 -0
  12. package/dist/analyzer/fileAnalyzer.js.map +1 -0
  13. package/dist/analyzer/functionAnalyzer.d.ts +12 -0
  14. package/dist/analyzer/functionAnalyzer.d.ts.map +1 -0
  15. package/dist/analyzer/functionAnalyzer.js +184 -0
  16. package/dist/analyzer/functionAnalyzer.js.map +1 -0
  17. package/dist/analyzer/index.d.ts +7 -0
  18. package/dist/analyzer/index.d.ts.map +1 -0
  19. package/dist/analyzer/index.js +14 -0
  20. package/dist/analyzer/index.js.map +1 -0
  21. package/dist/cli.d.ts +3 -0
  22. package/dist/cli.d.ts.map +1 -0
  23. package/dist/cli.js +113 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/generator/index.d.ts +6 -0
  26. package/dist/generator/index.d.ts.map +1 -0
  27. package/dist/generator/index.js +12 -0
  28. package/dist/generator/index.js.map +1 -0
  29. package/dist/generator/mockGenerator.d.ts +14 -0
  30. package/dist/generator/mockGenerator.d.ts.map +1 -0
  31. package/dist/generator/mockGenerator.js +123 -0
  32. package/dist/generator/mockGenerator.js.map +1 -0
  33. package/dist/generator/testGenerator.d.ts +14 -0
  34. package/dist/generator/testGenerator.d.ts.map +1 -0
  35. package/dist/generator/testGenerator.js +301 -0
  36. package/dist/generator/testGenerator.js.map +1 -0
  37. package/dist/index.d.ts +9 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +32 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/parser/astParser.d.ts +15 -0
  42. package/dist/parser/astParser.d.ts.map +1 -0
  43. package/dist/parser/astParser.js +100 -0
  44. package/dist/parser/astParser.js.map +1 -0
  45. package/dist/parser/index.d.ts +6 -0
  46. package/dist/parser/index.d.ts.map +1 -0
  47. package/dist/parser/index.js +12 -0
  48. package/dist/parser/index.js.map +1 -0
  49. package/dist/parser/typeExtractor.d.ts +14 -0
  50. package/dist/parser/typeExtractor.d.ts.map +1 -0
  51. package/dist/parser/typeExtractor.js +165 -0
  52. package/dist/parser/typeExtractor.js.map +1 -0
  53. package/dist/templates/component.ejs +67 -0
  54. package/dist/templates/function.ejs +59 -0
  55. package/dist/templates/snapshot.ejs +48 -0
  56. package/dist/types.d.ts +95 -0
  57. package/dist/types.d.ts.map +1 -0
  58. package/dist/types.js +6 -0
  59. package/dist/types.js.map +1 -0
  60. package/dist/utils/fileUtils.d.ts +43 -0
  61. package/dist/utils/fileUtils.d.ts.map +1 -0
  62. package/dist/utils/fileUtils.js +109 -0
  63. package/dist/utils/fileUtils.js.map +1 -0
  64. package/dist/utils/index.d.ts +6 -0
  65. package/dist/utils/index.d.ts.map +1 -0
  66. package/dist/utils/index.js +22 -0
  67. package/dist/utils/index.js.map +1 -0
  68. package/dist/utils/naming.d.ts +37 -0
  69. package/dist/utils/naming.d.ts.map +1 -0
  70. package/dist/utils/naming.js +73 -0
  71. package/dist/utils/naming.js.map +1 -0
  72. package/package.json +84 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,71 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Planned
11
+ - Directory scanning (`scan` command)
12
+ - Configuration file support (`.testgenrc.js`)
13
+ - Node.js backend support
14
+ - Custom templates
15
+
16
+ ---
17
+
18
+ ## [0.1.0] - 2024-01-07
19
+
20
+ ### Added
21
+ - ๐ŸŽ‰ Initial release
22
+ - CLI interface with `generate` command
23
+ - AST parsing using Babel
24
+ - React component analysis
25
+ - Props extraction
26
+ - Hooks detection (useState, useEffect, etc.)
27
+ - Event handlers detection (onPress, onClick, etc.)
28
+ - React Native component support
29
+ - TypeScript function analysis
30
+ - Parameters extraction
31
+ - Return type detection
32
+ - Async function support
33
+ - EJS template system
34
+ - Component test template
35
+ - Function test template
36
+ - Snapshot test template
37
+ - Auto-detection of testing library
38
+ - `@testing-library/react` for React
39
+ - `@testing-library/react-native` for React Native
40
+ - Mock generation for common libraries
41
+ - React Navigation
42
+ - React Redux
43
+ - AsyncStorage
44
+ - GitHub Actions CI/CD
45
+ - Automated testing
46
+ - Automated npm publishing
47
+
48
+ ### Commands
49
+ - `test-gen-js generate <file>` - Generate test file
50
+ - `tgjs g <file>` - Shorthand alias
51
+
52
+ ### Options
53
+ - `--output, -o` - Custom output path
54
+ - `--snapshot` - Include snapshot tests
55
+ - `--mock` - Auto-generate mocks (default: true)
56
+ - `--overwrite` - Overwrite existing files
57
+
58
+ ---
59
+
60
+ ## [0.0.1] - 2024-01-07
61
+
62
+ ### Added
63
+ - Project initialization
64
+ - Basic project structure
65
+
66
+ ---
67
+
68
+ [Unreleased]: https://github.com/liveforownhappiness/test-gen-js-/compare/v0.1.0...HEAD
69
+ [0.1.0]: https://github.com/liveforownhappiness/test-gen-js-/releases/tag/v0.1.0
70
+ [0.0.1]: https://github.com/liveforownhappiness/test-gen-js-/releases/tag/v0.0.1
71
+
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 liveforownhappiness
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,538 @@
1
+ # test-gen-js
2
+
3
+ > ๐Ÿงช Auto-generate test boilerplate code for JavaScript/TypeScript, React, and React Native projects
4
+
5
+ [![npm version](https://badge.fury.io/js/test-gen-js.svg)](https://www.npmjs.com/package/test-gen-js)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![GitHub Actions](https://github.com/liveforownhappiness/test-gen-js-/actions/workflows/ci.yml/badge.svg)](https://github.com/liveforownhappiness/test-gen-js-/actions)
8
+
9
+ ---
10
+
11
+ ## ๐ŸŽฏ ๋ชฉํ‘œ (Goal)
12
+
13
+ > **"ํ…Œ์ŠคํŠธ 0๊ฐœ โ†’ ๊ธฐ๋ณธ ํ…Œ์ŠคํŠธ๋ผ๋„ ์žˆ๋Š” ์ƒํƒœ"**
14
+
15
+ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์™„๋ฒฝํ•œ ํ…Œ์ŠคํŠธ ์ž๋™ํ™”๊ฐ€ ์•„๋‹Œ, **ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์˜ ์ง„์ž… ์žฅ๋ฒฝ์„ ๋‚ฎ์ถ”๋Š” ๊ฒƒ**์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
16
+
17
+ ### ์ด ๋„๊ตฌ๊ฐ€ ํ•ด๊ฒฐํ•˜๋Š” ๋ฌธ์ œ
18
+
19
+ | ๋ฌธ์ œ | ํ•ด๊ฒฐ |
20
+ |------|------|
21
+ | ๐Ÿ˜ซ "ํ…Œ์ŠคํŠธ ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ ๊ท€์ฐฎ์•„์š”" | โœ… ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ž๋™ ์ƒ์„ฑ |
22
+ | ๐Ÿค” "์–ด๋–ป๊ฒŒ ์‹œ์ž‘ํ•ด์•ผ ํ• ์ง€ ๋ชจ๋ฅด๊ฒ ์–ด์š”" | โœ… ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์‹œ์ž‘์  ์ œ๊ณต |
23
+ | ๐Ÿ˜ฐ "๋ Œ๋”๋ง ๊ธฐ๋ณธ ํ…Œ์ŠคํŠธ๋„ ์—†์–ด์š”" | โœ… ์ตœ์†Œํ•œ์˜ ์•ˆ์ „๋ง ์ œ๊ณต |
24
+ | ๐Ÿ“š "ํ…Œ์ŠคํŠธ ์ž‘์„ฑ๋ฒ•์„ ๋ฐฐ์šฐ๊ณ  ์‹ถ์–ด์š”" | โœ… ํ•™์Šต ๋„๊ตฌ๋กœ ํ™œ์šฉ ๊ฐ€๋Šฅ |
25
+
26
+ ### ์ด ๋„๊ตฌ์˜ ํ•œ๊ณ„
27
+
28
+ ```
29
+ โŒ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ํ…Œ์ŠคํŠธ ์ž๋™ ์ƒ์„ฑ โ†’ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์ž‘์„ฑ ํ•„์š”
30
+ โŒ ์™„๋ฒฝํ•œ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ โ†’ ๋ถˆ๊ฐ€๋Šฅ (80% ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ, 20% ์ง์ ‘ ์ž‘์„ฑ)
31
+ ```
32
+
33
+ ---
34
+
35
+ ## ๐Ÿ“ฆ ์„ค์น˜ (Installation)
36
+
37
+ ```bash
38
+ # ์ „์—ญ ์„ค์น˜
39
+ npm install -g test-gen-js
40
+
41
+ # ๋˜๋Š” npx๋กœ ๋ฐ”๋กœ ์‚ฌ์šฉ (์„ค์น˜ ์—†์ด)
42
+ npx test-gen-js generate src/components/Button.tsx
43
+
44
+ # ๋˜๋Š” ํ”„๋กœ์ ํŠธ devDependency๋กœ ์„ค์น˜
45
+ npm install -D test-gen-js
46
+ ```
47
+
48
+ ---
49
+
50
+ ## ๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘ (Quick Start)
51
+
52
+ ### 1. React ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ ์ƒ์„ฑ
53
+
54
+ **์ž…๋ ฅ: `src/components/Button.tsx`**
55
+
56
+ ```tsx
57
+ import React from 'react';
58
+
59
+ interface ButtonProps {
60
+ title: string;
61
+ onPress: () => void;
62
+ disabled?: boolean;
63
+ loading?: boolean;
64
+ }
65
+
66
+ export const Button = ({ title, onPress, disabled = false, loading = false }: ButtonProps) => {
67
+ return (
68
+ <button onClick={onPress} disabled={disabled || loading}>
69
+ {loading ? 'Loading...' : title}
70
+ </button>
71
+ );
72
+ };
73
+ ```
74
+
75
+ **๋ช…๋ น์–ด ์‹คํ–‰:**
76
+
77
+ ```bash
78
+ npx test-gen-js generate src/components/Button.tsx
79
+ ```
80
+
81
+ **์ถœ๋ ฅ: `src/components/Button.test.tsx`**
82
+
83
+ ```tsx
84
+ import React from 'react';
85
+ import { render, fireEvent, screen, waitFor } from '@testing-library/react';
86
+ import { Button } from './Button';
87
+
88
+ describe('Button', () => {
89
+ const defaultProps = {
90
+ title: 'Test Title',
91
+ onPress: jest.fn(),
92
+ disabled: false,
93
+ loading: false
94
+ };
95
+
96
+ beforeEach(() => {
97
+ jest.clearAllMocks();
98
+ });
99
+
100
+ it('renders without crashing', () => {
101
+ render(<Button {...defaultProps} />);
102
+ });
103
+
104
+ it('renders with title prop', () => {
105
+ render(<Button {...defaultProps} />);
106
+ // TODO: Add specific assertions for title
107
+ });
108
+
109
+ it('calls onPress when triggered', () => {
110
+ const handler = jest.fn();
111
+ render(<Button {...defaultProps} onPress={handler} />);
112
+
113
+ // TODO: Trigger the onPress event
114
+ // fireEvent.click(screen.getByRole('button'));
115
+
116
+ // expect(handler).toHaveBeenCalled();
117
+ });
118
+ });
119
+ ```
120
+
121
+ ---
122
+
123
+ ### 2. React Native ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ ์ƒ์„ฑ
124
+
125
+ **์ž…๋ ฅ: `src/components/Card.tsx`**
126
+
127
+ ```tsx
128
+ import React, { useState } from 'react';
129
+ import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
130
+
131
+ interface CardProps {
132
+ title: string;
133
+ description: string;
134
+ onPress?: () => void;
135
+ }
136
+
137
+ export const Card = ({ title, description, onPress }: CardProps) => {
138
+ const [expanded, setExpanded] = useState(false);
139
+
140
+ return (
141
+ <TouchableOpacity onPress={onPress} style={styles.container}>
142
+ <Text style={styles.title}>{title}</Text>
143
+ <Text style={styles.description}>{description}</Text>
144
+ </TouchableOpacity>
145
+ );
146
+ };
147
+
148
+ const styles = StyleSheet.create({
149
+ container: { padding: 16 },
150
+ title: { fontSize: 18, fontWeight: 'bold' },
151
+ description: { fontSize: 14 },
152
+ });
153
+ ```
154
+
155
+ **๋ช…๋ น์–ด ์‹คํ–‰:**
156
+
157
+ ```bash
158
+ npx test-gen-js generate src/components/Card.tsx --snapshot
159
+ ```
160
+
161
+ **์ถœ๋ ฅ: `src/components/Card.test.tsx`**
162
+
163
+ ```tsx
164
+ import React from 'react';
165
+ import { render, fireEvent, screen, waitFor } from '@testing-library/react-native';
166
+ import { Card } from './Card';
167
+
168
+ describe('Card', () => {
169
+ const defaultProps = {
170
+ title: 'Test Title',
171
+ description: 'Test Text',
172
+ onPress: jest.fn()
173
+ };
174
+
175
+ beforeEach(() => {
176
+ jest.clearAllMocks();
177
+ });
178
+
179
+ it('renders without crashing', () => {
180
+ render(<Card {...defaultProps} />);
181
+ });
182
+
183
+ it('matches snapshot', () => {
184
+ const { toJSON } = render(<Card {...defaultProps} />);
185
+ expect(toJSON()).toMatchSnapshot();
186
+ });
187
+
188
+ it('calls onPress when triggered', () => {
189
+ const handler = jest.fn();
190
+ render(<Card {...defaultProps} onPress={handler} />);
191
+
192
+ // fireEvent.press(screen.getByTestId('card'));
193
+ // expect(handler).toHaveBeenCalled();
194
+ });
195
+
196
+ // Hook: useState
197
+ it('uses useState correctly', () => {
198
+ render(<Card {...defaultProps} />);
199
+ // TODO: Add assertions for useState behavior
200
+ });
201
+ });
202
+ ```
203
+
204
+ ---
205
+
206
+ ### 3. ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ…Œ์ŠคํŠธ ์ƒ์„ฑ
207
+
208
+ **์ž…๋ ฅ: `src/utils/calculate.ts`**
209
+
210
+ ```typescript
211
+ export function calculateDiscount(price: number, discountRate: number): number {
212
+ if (discountRate < 0 || discountRate > 1) {
213
+ throw new Error('Invalid discount rate');
214
+ }
215
+ return price * (1 - discountRate);
216
+ }
217
+
218
+ export async function fetchUserData(userId: string): Promise<User> {
219
+ const response = await fetch(`/api/users/${userId}`);
220
+ return response.json();
221
+ }
222
+ ```
223
+
224
+ **๋ช…๋ น์–ด ์‹คํ–‰:**
225
+
226
+ ```bash
227
+ npx test-gen-js generate src/utils/calculate.ts
228
+ ```
229
+
230
+ **์ถœ๋ ฅ: `src/utils/calculate.test.ts`**
231
+
232
+ ```typescript
233
+ import { calculateDiscount, fetchUserData } from './calculate';
234
+
235
+ describe('calculateDiscount', () => {
236
+ beforeEach(() => {
237
+ jest.clearAllMocks();
238
+ });
239
+
240
+ it('should return expected result', () => {
241
+ const result = calculateDiscount(42, 42);
242
+
243
+ // TODO: Add assertions
244
+ expect(result).toBeDefined();
245
+ });
246
+
247
+ describe('price parameter', () => {
248
+ it('should handle valid price', () => {
249
+ // TODO: Test with valid price values
250
+ });
251
+ });
252
+
253
+ describe('discountRate parameter', () => {
254
+ it('should handle valid discountRate', () => {
255
+ // TODO: Test with valid discountRate values
256
+ });
257
+ });
258
+ });
259
+
260
+ describe('fetchUserData', () => {
261
+ beforeEach(() => {
262
+ jest.clearAllMocks();
263
+ });
264
+
265
+ it('should resolve successfully', async () => {
266
+ const result = await fetchUserData('test-string');
267
+
268
+ // TODO: Add assertions
269
+ expect(result).toBeDefined();
270
+ });
271
+
272
+ it('should handle errors gracefully', async () => {
273
+ // TODO: Mock error scenario
274
+ // jest.spyOn(global, 'fetch').mockRejectedValue(new Error('Network error'));
275
+ // await expect(fetchUserData('123')).rejects.toThrow('Network error');
276
+ });
277
+ });
278
+ ```
279
+
280
+ ---
281
+
282
+ ## ๐Ÿ“‹ CLI ๋ช…๋ น์–ด
283
+
284
+ ### `generate` (๋ณ„์นญ: `g`)
285
+
286
+ ๋‹จ์ผ ํŒŒ์ผ์—์„œ ํ…Œ์ŠคํŠธ ์ƒ์„ฑ
287
+
288
+ ```bash
289
+ # ๊ธฐ๋ณธ ์‚ฌ์šฉ
290
+ test-gen-js generate <file>
291
+ tgjs g <file>
292
+
293
+ # ์˜ต์…˜
294
+ --output, -o <path> # ์ถœ๋ ฅ ํŒŒ์ผ ๊ฒฝ๋กœ ์ง€์ •
295
+ --template, -t <type> # ํ…œํ”Œ๋ฆฟ ํƒ€์ž… (component | function | hook)
296
+ --snapshot # ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ ํฌํ•จ
297
+ --mock # Mock ์ž๋™ ์ƒ์„ฑ (๊ธฐ๋ณธ: true)
298
+ --overwrite # ๊ธฐ์กด ํŒŒ์ผ ๋ฎ์–ด์“ฐ๊ธฐ
299
+ ```
300
+
301
+ **์˜ˆ์‹œ:**
302
+
303
+ ```bash
304
+ # ๊ธฐ๋ณธ ์ƒ์„ฑ
305
+ tgjs g src/components/Header.tsx
306
+
307
+ # ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ ํฌํ•จ
308
+ tgjs g src/components/Header.tsx --snapshot
309
+
310
+ # ์ปค์Šคํ…€ ์ถœ๋ ฅ ๊ฒฝ๋กœ
311
+ tgjs g src/components/Header.tsx -o __tests__/Header.test.tsx
312
+
313
+ # ๊ธฐ์กด ํŒŒ์ผ ๋ฎ์–ด์“ฐ๊ธฐ
314
+ tgjs g src/components/Header.tsx --overwrite
315
+ ```
316
+
317
+ ### `scan` (๋ณ„์นญ: `s`) - v0.2.0 ์˜ˆ์ •
318
+
319
+ ๋””๋ ‰ํ† ๋ฆฌ ์ „์ฒด ์Šค์บ” ๋ฐ ์ผ๊ด„ ์ƒ์„ฑ
320
+
321
+ ```bash
322
+ # ๊ธฐ๋ณธ ์‚ฌ์šฉ
323
+ test-gen-js scan <directory>
324
+
325
+ # ์˜ต์…˜
326
+ --dry-run # ๋ฏธ๋ฆฌ๋ณด๊ธฐ (ํŒŒ์ผ ์ƒ์„ฑ ์•ˆ ํ•จ)
327
+ --pattern <glob> # ํŒŒ์ผ ํŒจํ„ด (๊ธฐ๋ณธ: **/*.{ts,tsx,js,jsx})
328
+ --exclude <patterns> # ์ œ์™ธ ํŒจํ„ด
329
+ ```
330
+
331
+ ### `init` - v0.2.0 ์˜ˆ์ •
332
+
333
+ ์„ค์ • ํŒŒ์ผ ์ดˆ๊ธฐํ™”
334
+
335
+ ```bash
336
+ test-gen-js init
337
+ ```
338
+
339
+ ---
340
+
341
+ ## ๐Ÿ“Š ์ง€์› ๋ฒ”์œ„
342
+
343
+ | ํƒ€์ž… | ์ง€์› ์—ฌ๋ถ€ | ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ | ๋น„๊ณ  |
344
+ |------|----------|-----------------|------|
345
+ | JavaScript ํ•จ์ˆ˜ | โœ… | Jest | |
346
+ | TypeScript ํ•จ์ˆ˜ | โœ… | Jest | ํƒ€์ž… ๋ถ„์„ ์ง€์› |
347
+ | React ์ปดํฌ๋„ŒํŠธ | โœ… | Jest + @testing-library/react | |
348
+ | React Native ์ปดํฌ๋„ŒํŠธ | โœ… | Jest + @testing-library/react-native | |
349
+ | Custom Hooks | โœ… | Jest + @testing-library/react-hooks | |
350
+ | Node.js ๋ชจ๋“ˆ | ๐Ÿ”œ v0.2 | Jest | |
351
+ | Express ํ•ธ๋“ค๋Ÿฌ | ๐Ÿ”œ v0.2 | Jest + supertest | |
352
+ | Vue ์ปดํฌ๋„ŒํŠธ | ๐Ÿ”œ ํ”Œ๋Ÿฌ๊ทธ์ธ | Vitest | |
353
+ | Angular ์ปดํฌ๋„ŒํŠธ | ๐Ÿ”œ ํ”Œ๋Ÿฌ๊ทธ์ธ | Jasmine | |
354
+
355
+ ---
356
+
357
+ ## ๐Ÿ”ง ์ž‘๋™ ์›๋ฆฌ
358
+
359
+ ### AST (Abstract Syntax Tree) ๋ถ„์„
360
+
361
+ ```
362
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
363
+ โ”‚ 1. ์ž…๋ ฅ: Button.tsx โ”‚
364
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
365
+ โ”‚ export const Button = ({ title, onPress, disabled }) => { โ”‚
366
+ โ”‚ const [loading, setLoading] = useState(false); โ”‚
367
+ โ”‚ return ( โ”‚
368
+ โ”‚ <TouchableOpacity onPress={onPress} disabled={disabled}> โ”‚
369
+ โ”‚ <Text>{title}</Text> โ”‚
370
+ โ”‚ </TouchableOpacity> โ”‚
371
+ โ”‚ ); โ”‚
372
+ โ”‚ } โ”‚
373
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
374
+ โ”‚
375
+ โ–ผ Babel Parser
376
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
377
+ โ”‚ 2. AST ๋ถ„์„ ๊ฒฐ๊ณผ โ”‚
378
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
379
+ โ”‚ { โ”‚
380
+ โ”‚ name: "Button", โ”‚
381
+ โ”‚ type: "arrow", โ”‚
382
+ โ”‚ props: [ โ”‚
383
+ โ”‚ { name: "title", type: "string", required: true }, โ”‚
384
+ โ”‚ { name: "onPress", type: "function", required: true }, โ”‚
385
+ โ”‚ { name: "disabled", type: "boolean", required: false } โ”‚
386
+ โ”‚ ], โ”‚
387
+ โ”‚ hooks: ["useState"], โ”‚
388
+ โ”‚ events: ["onPress"], โ”‚
389
+ โ”‚ framework: "react-native" โ”‚
390
+ โ”‚ } โ”‚
391
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
392
+ โ”‚
393
+ โ–ผ EJS Template
394
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
395
+ โ”‚ 3. ์ถœ๋ ฅ: Button.test.tsx โ”‚
396
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
397
+ โ”‚ describe('Button', () => { โ”‚
398
+ โ”‚ const defaultProps = { title: '...', onPress: jest.fn() }; โ”‚
399
+ โ”‚ it('renders without crashing', () => { ... }); โ”‚
400
+ โ”‚ it('calls onPress when pressed', () => { ... }); โ”‚
401
+ โ”‚ it('uses useState correctly', () => { ... }); โ”‚
402
+ โ”‚ }); โ”‚
403
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
404
+ ```
405
+
406
+ ### ์ž๋™ํ™” ๋ฒ”์œ„
407
+
408
+ | ์˜์—ญ | ์ž๋™ํ™” ์ˆ˜์ค€ | ์„ค๋ช… |
409
+ |------|------------|------|
410
+ | import ๋ฌธ | โœ… 100% | ํ”„๋ ˆ์ž„์›Œํฌ ์ž๋™ ๊ฐ์ง€ |
411
+ | describe/it ๊ตฌ์กฐ | โœ… 100% | ์ปดํฌ๋„ŒํŠธ/ํ•จ์ˆ˜๋ช… ๊ธฐ๋ฐ˜ |
412
+ | defaultProps ์ƒ์„ฑ | โœ… 80% | TypeScript ํƒ€์ž… ๋ถ„์„ |
413
+ | Mock ์„ค์ • | โœ… 70% | ์ฃผ์š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž๋™ ๊ฐ์ง€ |
414
+ | ๋ Œ๋”๋ง ํ…Œ์ŠคํŠธ | โœ… 100% | ๊ธฐ๋ณธ ์ œ๊ณต |
415
+ | ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ…Œ์ŠคํŠธ | โœ… 60% | onPress, onClick ๋“ฑ ๊ฐ์ง€ |
416
+ | Hook ํ…Œ์ŠคํŠธ | โœ… 50% | useState, useEffect ๋“ฑ ๊ฐ์ง€ |
417
+ | **๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ํ…Œ์ŠคํŠธ** | โŒ 0% | **๊ฐœ๋ฐœ์ž ์ง์ ‘ ์ž‘์„ฑ ํ•„์š”** |
418
+
419
+ ---
420
+
421
+ ## ๐Ÿ—บ๏ธ ๋กœ๋“œ๋งต (Roadmap)
422
+
423
+ ### โœ… 1๋‹จ๊ณ„: MVP (v0.1.x) - ํ˜„์žฌ
424
+
425
+ - [x] ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์„ค์ •
426
+ - [x] AST ํŒŒ์„œ ๊ตฌํ˜„ (Babel ๊ธฐ๋ฐ˜)
427
+ - [x] CLI ์ธํ„ฐํŽ˜์ด์Šค (commander)
428
+ - [x] ๊ธฐ๋ณธ ํ…Œ์ŠคํŠธ ์ƒ์„ฑ๊ธฐ
429
+ - [x] React ์ปดํฌ๋„ŒํŠธ
430
+ - [x] React Native ์ปดํฌ๋„ŒํŠธ
431
+ - [x] JavaScript/TypeScript ํ•จ์ˆ˜
432
+ - [x] EJS ํ…œํ”Œ๋ฆฟ ์‹œ์Šคํ…œ
433
+ - [x] GitHub Actions CI/CD
434
+ - [x] npm ์ž๋™ ํผ๋ธ”๋ฆฌ์‹œ
435
+
436
+ ### ๐Ÿ”œ 2๋‹จ๊ณ„: ํ™•์žฅ (v0.2.x)
437
+
438
+ - [ ] ๋””๋ ‰ํ† ๋ฆฌ ์Šค์บ” ๋ฐ ์ผ๊ด„ ์ƒ์„ฑ (`scan` ๋ช…๋ น์–ด)
439
+ - [ ] ์„ค์ • ํŒŒ์ผ ์ง€์› (`.testgenrc.js`)
440
+ - [ ] Node.js ๋ฐฑ์—”๋“œ ์ง€์›
441
+ - [ ] Mock ์ž๋™ ์ƒ์„ฑ ๊ฐœ์„ 
442
+ - [ ] Prettier/ESLint ์—ฐ๋™
443
+ - [ ] Watch ๋ชจ๋“œ
444
+ - [ ] ์ปค์Šคํ…€ ํ…œํ”Œ๋ฆฟ ์ง€์›
445
+
446
+ ### ๐Ÿ”ฎ 3๋‹จ๊ณ„: ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ (v0.3.x+)
447
+
448
+ - [ ] ํ”Œ๋Ÿฌ๊ทธ์ธ ์•„ํ‚คํ…์ฒ˜
449
+ - [ ] Vue.js ํ”Œ๋Ÿฌ๊ทธ์ธ
450
+ - [ ] Angular ํ”Œ๋Ÿฌ๊ทธ์ธ
451
+ - [ ] VS Code ํ™•์žฅ
452
+ - [ ] AI ํ†ตํ•ฉ (์„ ํƒ์ )
453
+
454
+ ---
455
+
456
+ ## ๐Ÿ“ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ
457
+
458
+ ```
459
+ test-gen-js/
460
+ โ”œโ”€โ”€ bin/
461
+ โ”‚ โ””โ”€โ”€ cli.js # CLI ์ง„์ž…์ 
462
+ โ”œโ”€โ”€ src/
463
+ โ”‚ โ”œโ”€โ”€ index.ts # ๋ฉ”์ธ export
464
+ โ”‚ โ”œโ”€โ”€ cli.ts # CLI ๋กœ์ง (commander)
465
+ โ”‚ โ”œโ”€โ”€ types.ts # TypeScript ํƒ€์ž… ์ •์˜
466
+ โ”‚ โ”œโ”€โ”€ analyzer/
467
+ โ”‚ โ”‚ โ”œโ”€โ”€ index.ts
468
+ โ”‚ โ”‚ โ”œโ”€โ”€ fileAnalyzer.ts # ํŒŒ์ผ ๋ถ„์„ ๋ฉ”์ธ
469
+ โ”‚ โ”‚ โ”œโ”€โ”€ componentAnalyzer.ts # React ์ปดํฌ๋„ŒํŠธ ๋ถ„์„
470
+ โ”‚ โ”‚ โ””โ”€โ”€ functionAnalyzer.ts # ํ•จ์ˆ˜ ๋ถ„์„
471
+ โ”‚ โ”œโ”€โ”€ parser/
472
+ โ”‚ โ”‚ โ”œโ”€โ”€ index.ts
473
+ โ”‚ โ”‚ โ”œโ”€โ”€ astParser.ts # Babel AST ํŒŒ์‹ฑ
474
+ โ”‚ โ”‚ โ””โ”€โ”€ typeExtractor.ts # TypeScript ํƒ€์ž… ์ถ”์ถœ
475
+ โ”‚ โ”œโ”€โ”€ generator/
476
+ โ”‚ โ”‚ โ”œโ”€โ”€ index.ts
477
+ โ”‚ โ”‚ โ”œโ”€โ”€ testGenerator.ts # ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ƒ์„ฑ
478
+ โ”‚ โ”‚ โ””โ”€โ”€ mockGenerator.ts # Mock ์ฝ”๋“œ ์ƒ์„ฑ
479
+ โ”‚ โ”œโ”€โ”€ templates/
480
+ โ”‚ โ”‚ โ”œโ”€โ”€ component.ejs # ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ ํ…œํ”Œ๋ฆฟ
481
+ โ”‚ โ”‚ โ”œโ”€โ”€ function.ejs # ํ•จ์ˆ˜ ํ…Œ์ŠคํŠธ ํ…œํ”Œ๋ฆฟ
482
+ โ”‚ โ”‚ โ””โ”€โ”€ snapshot.ejs # ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ ํ…œํ”Œ๋ฆฟ
483
+ โ”‚ โ””โ”€โ”€ utils/
484
+ โ”‚ โ”œโ”€โ”€ fileUtils.ts # ํŒŒ์ผ ์œ ํ‹ธ๋ฆฌํ‹ฐ
485
+ โ”‚ โ””โ”€โ”€ naming.ts # ๋„ค์ด๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ
486
+ โ”œโ”€โ”€ .github/
487
+ โ”‚ โ””โ”€โ”€ workflows/
488
+ โ”‚ โ”œโ”€โ”€ ci.yml # CI (๋นŒ๋“œ/ํ…Œ์ŠคํŠธ)
489
+ โ”‚ โ””โ”€โ”€ publish.yml # npm ์ž๋™ ํผ๋ธ”๋ฆฌ์‹œ
490
+ โ”œโ”€โ”€ package.json
491
+ โ”œโ”€โ”€ tsconfig.json
492
+ โ””โ”€โ”€ README.md
493
+ ```
494
+
495
+ ---
496
+
497
+ ## ๐Ÿค ๊ธฐ์—ฌํ•˜๊ธฐ (Contributing)
498
+
499
+ ๊ธฐ์—ฌ๋Š” ์–ธ์ œ๋‚˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!
500
+
501
+ ### ๊ธฐ์—ฌ ๋ฐฉ๋ฒ•
502
+
503
+ 1. ๐Ÿด Fork the repository
504
+ 2. ๐ŸŒฟ Create your feature branch (`git checkout -b feature/amazing-feature`)
505
+ 3. ๐Ÿ’พ Commit your changes (`git commit -m 'Add some amazing feature'`)
506
+ 4. ๐Ÿ“ค Push to the branch (`git push origin feature/amazing-feature`)
507
+ 5. ๐Ÿ”ƒ Open a Pull Request
508
+
509
+ ### ๊ธฐ์—ฌ ์œ ํ˜•
510
+
511
+ - ๐Ÿ› ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ
512
+ - ๐Ÿ’ก ๊ธฐ๋Šฅ ์ œ์•ˆ
513
+ - ๐Ÿ“ ๋ฌธ์„œ ๊ฐœ์„ 
514
+ - ๐Ÿ”ง ์ฝ”๋“œ ๊ธฐ์—ฌ
515
+ - ๐ŸŒ ๋ฒˆ์—ญ
516
+
517
+ ---
518
+
519
+ ## ๐Ÿ“„ ๋ผ์ด์„ ์Šค (License)
520
+
521
+ MIT License - ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉ, ์ˆ˜์ •, ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
522
+
523
+ ---
524
+
525
+ ## ๐Ÿ™ ๊ฐ์‚ฌ์˜ ๊ธ€ (Acknowledgments)
526
+
527
+ - [Babel](https://babeljs.io/) - JavaScript AST ํŒŒ์‹ฑ
528
+ - [Jest](https://jestjs.io/) - ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ
529
+ - [Testing Library](https://testing-library.com/) - ํ…Œ์ŠคํŠธ ์œ ํ‹ธ๋ฆฌํ‹ฐ
530
+ - [Commander.js](https://github.com/tj/commander.js) - CLI ํ”„๋ ˆ์ž„์›Œํฌ
531
+ - [EJS](https://ejs.co/) - ํ…œํ”Œ๋ฆฟ ์—”์ง„
532
+
533
+ ---
534
+
535
+ ## ๐Ÿ“ž ๋ฌธ์˜ (Contact)
536
+
537
+ - GitHub Issues: [https://github.com/liveforownhappiness/test-gen-js-/issues](https://github.com/liveforownhappiness/test-gen-js-/issues)
538
+ - npm: [https://www.npmjs.com/package/test-gen-js](https://www.npmjs.com/package/test-gen-js)
package/bin/cli.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('../dist/cli.js');
4
+
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Component Analyzer
3
+ * Extracts information from React/React Native components
4
+ */
5
+ import type { NodePath } from '@babel/traverse';
6
+ import * as t from '@babel/types';
7
+ import type { ComponentInfo } from '../types';
8
+ /**
9
+ * Analyze a component and extract its information
10
+ */
11
+ export declare function analyzeComponent(nodePath: NodePath<t.FunctionDeclaration | t.VariableDeclarator>, filePath: string): ComponentInfo | null;
12
+ //# sourceMappingURL=componentAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"componentAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/componentAnalyzer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAElC,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,UAAU,CAAC;AAExD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,mBAAmB,GAAG,CAAC,CAAC,kBAAkB,CAAC,EAChE,QAAQ,EAAE,MAAM,GACf,aAAa,GAAG,IAAI,CAgDtB"}