fix-tests-ai 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gabriel Azambuja
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.
package/README.md ADDED
@@ -0,0 +1,321 @@
1
+ # Fix Tests AI ๐Ÿ”ง
2
+
3
+ Automatically fix failing tests using Claude AI. No more debugging test failures manually!
4
+
5
+ ## Features
6
+
7
+ - ๐Ÿ” **Auto-detects test runner** (Jest, Vitest, Mocha, AVA, Tape)
8
+ - ๐Ÿค– **AI-powered analysis** using the latest **Claude 4.5 Sonnet**
9
+ - ๐Ÿ”ง **Automatic fixing** applies fixes to your code
10
+ - ๐Ÿ”„ **Verification loop** re-runs tests to confirm
11
+ - ๐ŸŽฏ **One test at a time** focused and narrow
12
+ - ๐ŸŒˆ **Dry-run mode** preview changes first
13
+ - ๐Ÿ› ๏ธ **Diagnostic mode** verify your setup with `--check`
14
+ - ๐Ÿ“ **Recursive env loading** finds your `.env.local` automatically
15
+
16
+ ## Quick Start
17
+
18
+ ### 1. Install globally
19
+
20
+ ```bash
21
+ npm install -g fix-tests-ai
22
+ ```
23
+
24
+ ### 2. Set up API key
25
+
26
+ The easiest way is to create a `.env.local` file in your project:
27
+
28
+ ```bash
29
+ echo 'ANTHROPIC_API_KEY="sk-ant-..."' >> .env.local
30
+ ```
31
+
32
+ Or secure it globally in your shell config:
33
+
34
+ ```bash
35
+ echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.zshrc # or ~/.bashrc
36
+ ```
37
+
38
+ > [!TIP]
39
+ > Use `fix-tests --check` to verify your API key and connection.
40
+
41
+ ### 3. Run in any project with failing tests
42
+
43
+ ```bash
44
+ cd your-project
45
+ fix-tests
46
+ ```
47
+
48
+ That's it! ๐ŸŽ‰
49
+
50
+ ## Usage
51
+
52
+ ### Basic Usage
53
+
54
+ ```bash
55
+ # Fix failing tests
56
+ fix-tests
57
+
58
+ # Preview changes without applying
59
+ fix-tests --dry-run
60
+
61
+ # Run diagnostics to verify your setup and API key
62
+ fix-tests --check
63
+
64
+ # Show help
65
+ fix-tests --help
66
+
67
+ # Setup instructions
68
+ fix-tests --setup
69
+ ```
70
+
71
+ ### Example Session
72
+
73
+ ```bash
74
+ $ npm test
75
+ FAIL tests/calculator.test.ts
76
+ โ— should add two numbers
77
+ Expected: 4, Received: 5
78
+
79
+ $ fix-tests
80
+
81
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
82
+ โ•‘ ๐Ÿ”ง Fix Tests AI - by Claude โ•‘
83
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
84
+
85
+ ๐Ÿ” Detecting test runner...
86
+ โœ… Found: jest
87
+ Command: npm test
88
+
89
+ ๐Ÿงช Running tests: npm test
90
+
91
+ ๐Ÿ“Š Analyzing test failures...
92
+ โœ… Found 1 failing test(s)
93
+
94
+ Failed tests:
95
+ 1. should add two numbers
96
+ tests/calculator.test.ts
97
+
98
+ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
99
+ ๐Ÿ”ง Fixing: should add two numbers
100
+ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
101
+
102
+ ๐Ÿ” Analyzing: should add two numbers
103
+ ๐Ÿ“„ Test file: tests/calculator.test.ts
104
+ ๐Ÿ“„ Source file: src/calculator.ts
105
+
106
+ ๐Ÿค– Asking Claude to analyze the failure...
107
+
108
+ ๐Ÿ’ก Claude's Analysis:
109
+ The add function has an off-by-one error. Line 5 is adding
110
+ an extra 1: return a + b + 1; should be: return a + b;
111
+
112
+ ๐Ÿ“ Fixing: src/calculator.ts
113
+ โœ… Applied fix to src/calculator.ts
114
+
115
+ ๐Ÿ”„ Re-running tests to verify fix...
116
+
117
+ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
118
+ โœ… SUCCESS! All tests now passing!
119
+ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
120
+ ```
121
+
122
+ ## How It Works
123
+
124
+ 1. **Detects** your test runner from `package.json`
125
+ 2. **Runs** your tests and captures failures
126
+ 3. **Parses** the test output (runner-specific)
127
+ 4. **Analyzes** with Claude AI (test + source code)
128
+ 5. **Applies** the suggested fix
129
+ 6. **Verifies** by re-running tests
130
+ 7. **Retries** if needed (up to 3 attempts)
131
+
132
+ ## Supported Test Runners
133
+
134
+ | Test Runner | Status | Auto-detected |
135
+ |------------|--------|---------------|
136
+ | Jest | โœ… | โœ… |
137
+ | Vitest | โœ… | โœ… |
138
+ | Mocha | โœ… | โœ… |
139
+ | AVA | โœ… | โœ… |
140
+ | Tape | โœ… | โœ… |
141
+ | Others | โš ๏ธ Generic | - |
142
+
143
+ ## API Key Setup
144
+
145
+ ### Option 1: .env.local (Recommended for Local Dev)
146
+
147
+ The tool recursively searches for `.env` and `.env.local` files in parent directories. **This is the primary way to manage variables locally.**
148
+
149
+ > [!NOTE]
150
+ > `.env.local` is included in `.gitignore` by default to ensure your API keys are never committed to your repository.
151
+
152
+ ```bash
153
+ # In your project root
154
+ echo 'ANTHROPIC_API_KEY=sk-ant-...' >> .env.local
155
+ ```
156
+
157
+ ### Option 2: Environment Variable
158
+
159
+ ```bash
160
+ export ANTHROPIC_API_KEY="sk-ant-..."
161
+ ```
162
+
163
+ ### Option 3: Shell Config (Persistent)
164
+
165
+ ```bash
166
+ # Bash
167
+ echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.bashrc
168
+ source ~/.bashrc
169
+
170
+ # Zsh
171
+ echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.zshrc
172
+ source ~/.zshrc
173
+ ```
174
+
175
+ ## Troubleshooting
176
+
177
+ ### "No API key found"
178
+
179
+ **Solution**: Set the `ANTHROPIC_API_KEY` environment variable
180
+
181
+ ```bash
182
+ export ANTHROPIC_API_KEY="sk-ant-..."
183
+ fix-tests
184
+ ```
185
+
186
+ ### "Could not detect test runner"
187
+
188
+ **Solution**: The tool will fall back to `npm test`. Make sure you have a `test` script in `package.json`:
189
+
190
+ ```json
191
+ {
192
+ "scripts": {
193
+ "test": "jest"
194
+ }
195
+ }
196
+ ```
197
+
198
+ ### "Tests failed but could not parse output"
199
+
200
+ **Solution**: Your test runner format might not be supported. Open an issue with the output format.
201
+
202
+ ### "Claude API error"
203
+
204
+ **Solutions**:
205
+ - Check your API key is valid
206
+ - Ensure you have API credits
207
+ - Check network connection
208
+
209
+ ## Limitations (v0.1.0)
210
+
211
+ - โŒ Fixes **one test at a time** (run multiple times for multiple failures)
212
+ - โŒ Works best with **unit tests** (not complex E2E tests)
213
+ - โŒ May not fix tests requiring **external service setup**
214
+ - โŒ Requires valid **Anthropic API key** (costs ~$0.01-0.10 per fix)
215
+
216
+ ## Roadmap
217
+
218
+ - [ ] Fix multiple tests in one run
219
+ - [ ] Interactive mode (approve each fix)
220
+ - [ ] Better diff visualization
221
+ - [ ] Support more test runners
222
+ - [ ] Rollback on failed fix
223
+ - [ ] Configuration file support
224
+ - [ ] CI/CD integration guide
225
+
226
+ ## Development
227
+
228
+ ### Clone & Build
229
+
230
+ ```bash
231
+ git clone https://github.com/starslingdev/refactored-palm-tree
232
+ cd fix-tests-ai
233
+ npm install
234
+ npm run build
235
+ ```
236
+
237
+ ### Test Locally
238
+
239
+ We've provided a demo script to quickly test the tool in a sandbox:
240
+
241
+ ```bash
242
+ # 1. Setup the demo project
243
+ ./demo-setup.sh
244
+
245
+ # 2. Enter the demo
246
+ cd fix-tests-demo
247
+
248
+ # 3. Fix the tests
249
+ node ../dist/cli.js
250
+ ```
251
+
252
+ ### Mimic Real NPM Installation
253
+
254
+ To test the package as if it were installed via NPM:
255
+
256
+ #### Method 1: Using npm link (Recommended)
257
+ This creates a symlink so your changes are reflected immediately.
258
+
259
+ ```bash
260
+ # In the fix-tests-ai directory
261
+ npm link
262
+
263
+ # In your project directory
264
+ npm link fix-tests-ai
265
+ fix-tests
266
+ ```
267
+
268
+ #### Method 2: Global Installation from Source
269
+ This mimics a true global installation.
270
+
271
+ ```bash
272
+ # In the fix-tests-ai directory
273
+ npm install -g .
274
+ ```
275
+
276
+ You can now run `fix-tests` from anywhere on your system.
277
+
278
+ ### Project Structure
279
+
280
+ ```
281
+ fix-tests-ai/
282
+ โ”œโ”€โ”€ src/
283
+ โ”‚ โ”œโ”€โ”€ cli.ts # CLI entry point
284
+ โ”‚ โ”œโ”€โ”€ detector.ts # Test runner detection
285
+ โ”‚ โ”œโ”€โ”€ runner.ts # Run tests
286
+ โ”‚ โ”œโ”€โ”€ parser.ts # Parse test output
287
+ โ”‚ โ”œโ”€โ”€ fixer.ts # Claude API + apply fixes
288
+ โ”‚ โ”œโ”€โ”€ types.ts # TypeScript types
289
+ โ”‚ โ””โ”€โ”€ index.ts # Exported API
290
+ โ”œโ”€โ”€ package.json
291
+ โ”œโ”€โ”€ tsconfig.json
292
+ โ””โ”€โ”€ README.md
293
+ ```
294
+
295
+ ## Contributing
296
+
297
+ Contributions welcome! Please:
298
+
299
+ 1. Fork the repo
300
+ 2. Create a feature branch
301
+ 3. Add tests (when we have them ๐Ÿ˜…)
302
+ 4. Submit a PR
303
+
304
+ ## Cost
305
+
306
+ Claude API pricing (as of 2024):
307
+ - **Sonnet 4**: ~$0.003 per 1K input tokens, ~$0.015 per 1K output tokens
308
+ - **Estimated cost per fix**: $0.01 - $0.10 depending on code size
309
+
310
+ Much cheaper than your time debugging! โฐ๐Ÿ’ฐ
311
+
312
+ ## License
313
+
314
+ MIT
315
+
316
+ ## Credits
317
+
318
+ Built with:
319
+ - [Claude AI](https://claude.ai) by Anthropic
320
+ - TypeScript
321
+ - Node.js
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for fix-tests
4
+ * Usage: npx fix-tests-ai
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
package/dist/cli.js ADDED
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * CLI entry point for fix-tests
5
+ * Usage: npx fix-tests-ai
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const fs_1 = require("fs");
9
+ const os_1 = require("os");
10
+ const path_1 = require("path");
11
+ const promises_1 = require("fs/promises");
12
+ const dotenv_1 = require("dotenv");
13
+ const detector_1 = require("./detector");
14
+ const runner_1 = require("./runner");
15
+ const parser_1 = require("./parser");
16
+ const fixer_1 = require("./fixer");
17
+ const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.fix-tests-ai');
18
+ const CONFIG_FILE = (0, path_1.join)(CONFIG_DIR, 'config.json');
19
+ /**
20
+ * Searches for a file in the current directory and parent directories
21
+ */
22
+ function findEnvFile(filename, startDir) {
23
+ let currentDir = startDir;
24
+ while (currentDir !== (0, path_1.dirname)(currentDir)) {
25
+ const filePath = (0, path_1.join)(currentDir, filename);
26
+ if ((0, fs_1.existsSync)(filePath)) {
27
+ return filePath;
28
+ }
29
+ currentDir = (0, path_1.dirname)(currentDir);
30
+ }
31
+ // Check root directory as well
32
+ const rootPath = (0, path_1.join)(currentDir, filename);
33
+ if ((0, fs_1.existsSync)(rootPath))
34
+ return rootPath;
35
+ return null;
36
+ }
37
+ // Load environment variables from current directory or parents
38
+ const cwd = process.cwd();
39
+ const envPaths = [
40
+ findEnvFile('.env.local', cwd),
41
+ findEnvFile('.env', cwd)
42
+ ].filter(Boolean);
43
+ for (const path of envPaths) {
44
+ (0, dotenv_1.config)({ path, override: true });
45
+ }
46
+ async function loadConfig() {
47
+ try {
48
+ if ((0, fs_1.existsSync)(CONFIG_FILE)) {
49
+ const content = await (0, promises_1.readFile)(CONFIG_FILE, 'utf-8');
50
+ return JSON.parse(content);
51
+ }
52
+ }
53
+ catch (err) {
54
+ // Config doesn't exist or is invalid
55
+ }
56
+ return {};
57
+ }
58
+ async function saveConfig(config) {
59
+ try {
60
+ await (0, promises_1.mkdir)(CONFIG_DIR, { recursive: true });
61
+ await (0, promises_1.writeFile)(CONFIG_FILE, JSON.stringify(config, null, 2));
62
+ }
63
+ catch (err) {
64
+ console.error('Failed to save config:', err);
65
+ }
66
+ }
67
+ async function getApiKey() {
68
+ // Priority: 1. Env var (from process.env or loaded via dotenv), 2. Config file
69
+ if (process.env.ANTHROPIC_API_KEY) {
70
+ return process.env.ANTHROPIC_API_KEY;
71
+ }
72
+ const config = await loadConfig();
73
+ return config.apiKey || null;
74
+ }
75
+ async function testAnthropicConnection(apiKey) {
76
+ try {
77
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ 'anthropic-version': '2023-06-01',
82
+ 'x-api-key': apiKey
83
+ },
84
+ body: JSON.stringify({
85
+ model: 'claude-3-haiku-20240307',
86
+ max_tokens: 10,
87
+ messages: [{ role: 'user', content: 'Ping' }]
88
+ })
89
+ });
90
+ if (response.ok) {
91
+ return { success: true, message: 'Successfully connected to Anthropic API.' };
92
+ }
93
+ else {
94
+ const error = await response.json();
95
+ return {
96
+ success: false,
97
+ message: `Claude API error: ${error.error?.message || response.statusText}`
98
+ };
99
+ }
100
+ }
101
+ catch (err) {
102
+ return { success: false, message: `Connectivity error: ${err.message || 'Network error'}` };
103
+ }
104
+ }
105
+ async function checkDiagnostics() {
106
+ console.log('\n๐Ÿ” Diagnostics\n');
107
+ console.log(`Current directory: ${process.cwd()}`);
108
+ const envLocal = findEnvFile('.env.local', process.cwd());
109
+ const env = findEnvFile('.env', process.cwd());
110
+ console.log(`.env.local found: ${envLocal || 'No'}`);
111
+ console.log(`.env found: ${env || 'No'}`);
112
+ const apiKey = await getApiKey();
113
+ if (apiKey) {
114
+ const maskedKey = apiKey.substring(0, 10) + '...' + apiKey.substring(apiKey.length - 4);
115
+ console.log(`API Key found: Yes (${maskedKey})`);
116
+ console.log('Testing connectivity...');
117
+ const connection = await testAnthropicConnection(apiKey);
118
+ if (connection.success) {
119
+ console.log(`Connectivity: โœ… ${connection.message}`);
120
+ }
121
+ else {
122
+ console.log(`Connectivity: โŒ ${connection.message}`);
123
+ }
124
+ }
125
+ else {
126
+ console.log('API Key found: No');
127
+ }
128
+ console.log('');
129
+ }
130
+ async function setupApiKey() {
131
+ console.log('\n๐Ÿ”‘ Anthropic API Key Setup\n');
132
+ console.log('Get your API key from: https://console.anthropic.com/settings/keys\n');
133
+ console.log('To use fix-tests-ai, you have a few options for your API key:');
134
+ console.log('\nOption 1: Environmental Variable (Recommended for local dev)');
135
+ console.log(' Create a .env.local file in your project:');
136
+ console.log(' ANTHROPIC_API_KEY=sk-ant-...');
137
+ console.log('\nOption 2: Persistence for all projects');
138
+ console.log(' Add to your bash/zsh profile (~/.zshrc or ~/.bashrc):');
139
+ console.log(' export ANTHROPIC_API_KEY="sk-ant-..."');
140
+ console.log('\nOption 3: Global Config');
141
+ console.log(' The tool will soon support: fix-tests --set-key sk-ant-...\n');
142
+ process.exit(0);
143
+ }
144
+ async function cli() {
145
+ const args = process.argv.slice(2);
146
+ const dryRun = args.includes('--dry-run') || args.includes('-d');
147
+ const help = args.includes('--help') || args.includes('-h');
148
+ const setup = args.includes('--setup') || args.includes('-s');
149
+ const check = args.includes('--check') || args.includes('-c');
150
+ const cwd = process.cwd();
151
+ if (help) {
152
+ console.log(`
153
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
154
+ โ•‘ ๐Ÿ”ง Fix Tests AI - by Claude โ•‘
155
+ โ•‘ Automatically fix failing tests with AI โ•‘
156
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
157
+
158
+ USAGE:
159
+ fix-tests [options]
160
+
161
+ OPTIONS:
162
+ --dry-run, -d Preview changes without applying them
163
+ --setup, -s Show API key setup instructions
164
+ --check, -c Run diagnostics to check API key and env files
165
+ --help, -h Show this help message
166
+
167
+ EXAMPLES:
168
+ # First time setup
169
+ fix-tests --setup
170
+
171
+ # Run diagnostics
172
+ fix-tests --check
173
+
174
+ # Fix tests
175
+ fix-tests
176
+
177
+ # Preview fixes without applying
178
+ fix-tests --dry-run
179
+
180
+ ENVIRONMENT:
181
+ ANTHROPIC_API_KEY Your Anthropic API key (required)
182
+
183
+ GET API KEY:
184
+ https://console.anthropic.com/settings/keys
185
+
186
+ SUPPORTED TEST RUNNERS:
187
+ โœ“ Jest
188
+ โœ“ Vitest
189
+ โœ“ Mocha
190
+ โœ“ AVA
191
+ โœ“ Tape
192
+
193
+ GITHUB:
194
+ https://github.com/yourusername/fix-tests-ai
195
+ `);
196
+ process.exit(0);
197
+ }
198
+ if (setup) {
199
+ await setupApiKey();
200
+ return;
201
+ }
202
+ if (check) {
203
+ await checkDiagnostics();
204
+ return;
205
+ }
206
+ // Check for API key
207
+ const apiKey = await getApiKey();
208
+ if (!apiKey) {
209
+ console.log('\nโŒ No API key found!\n');
210
+ console.log('Run: fix-tests --setup');
211
+ console.log('Or set: export ANTHROPIC_API_KEY="sk-ant-..."\n');
212
+ process.exit(1);
213
+ }
214
+ // Store API key in env for child processes
215
+ process.env.ANTHROPIC_API_KEY = apiKey;
216
+ console.log('\nโ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
217
+ console.log('โ•‘ ๐Ÿ”ง Fix Tests AI - by Claude โ•‘');
218
+ console.log('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n');
219
+ try {
220
+ // Detect test runner
221
+ console.log('๐Ÿ” Detecting test runner...');
222
+ const runner = await (0, detector_1.detectTestRunner)(cwd);
223
+ if (runner.detected) {
224
+ console.log(`โœ… Found: ${runner.name}`);
225
+ console.log(` Command: ${runner.command}\n`);
226
+ }
227
+ else {
228
+ console.log(`โš ๏ธ Using: ${runner.command}\n`);
229
+ }
230
+ // Run tests
231
+ const testResult = await (0, runner_1.runTests)(runner.command, cwd);
232
+ if (testResult.passed) {
233
+ console.log('โœ… All tests passing! Nothing to fix.\n');
234
+ process.exit(0);
235
+ }
236
+ // Parse failures
237
+ console.log('๐Ÿ“Š Analyzing test failures...');
238
+ const failures = (0, parser_1.parseTestFailures)(testResult.stdout + '\n' + testResult.stderr, runner);
239
+ if (failures.length === 0) {
240
+ console.log('โŒ Tests failed but could not parse the output.\n');
241
+ console.log('Output:', testResult.stdout.slice(0, 300));
242
+ process.exit(1);
243
+ }
244
+ console.log(`โœ… Found ${failures.length} failing test(s)\n`);
245
+ console.log('Failed tests:');
246
+ failures.forEach((f, i) => {
247
+ console.log(` ${i + 1}. ${f.testName}`);
248
+ console.log(` ${f.testFile}`);
249
+ });
250
+ console.log();
251
+ // Fix first failure
252
+ const failure = failures[0];
253
+ console.log('โ”'.repeat(60));
254
+ console.log(`๐Ÿ”ง Fixing: ${failure.testName}`);
255
+ console.log('โ”'.repeat(60) + '\n');
256
+ const fixResult = await (0, fixer_1.fixTestFailure)(failure, cwd, dryRun);
257
+ if (!fixResult) {
258
+ console.log('\nโŒ Could not generate a fix automatically.');
259
+ console.log(' This test may require manual intervention.\n');
260
+ process.exit(1);
261
+ }
262
+ if (dryRun) {
263
+ console.log('\nโœ… Dry run complete.');
264
+ console.log(' Run without --dry-run to apply changes.\n');
265
+ process.exit(0);
266
+ }
267
+ // Verify fix
268
+ console.log('\n๐Ÿ”„ Re-running tests to verify fix...\n');
269
+ const verifyResult = await (0, runner_1.runTests)(runner.command, cwd);
270
+ console.log('\n' + 'โ•'.repeat(60));
271
+ if (verifyResult.passed) {
272
+ console.log('โœ… SUCCESS! All tests now passing!');
273
+ console.log('โ•'.repeat(60) + '\n');
274
+ process.exit(0);
275
+ }
276
+ else {
277
+ console.log('โš ๏ธ Tests still failing after fix');
278
+ console.log('โ•'.repeat(60) + '\n');
279
+ const remainingFailures = (0, parser_1.parseTestFailures)(verifyResult.stdout + '\n' + verifyResult.stderr, runner);
280
+ if (remainingFailures.length > 0 && remainingFailures.length < failures.length) {
281
+ console.log(`Progress: ${failures.length - remainingFailures.length} test(s) fixed!`);
282
+ console.log(`Still ${remainingFailures.length} failing. Run again to continue.\n`);
283
+ }
284
+ else {
285
+ console.log('Manual review may be needed.\n');
286
+ }
287
+ process.exit(1);
288
+ }
289
+ }
290
+ catch (error) {
291
+ console.error('\nโŒ Error:', error.message || error);
292
+ console.error('\nFor help: fix-tests --help\n');
293
+ process.exit(1);
294
+ }
295
+ }
296
+ cli();
297
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { TestRunner } from './types';
2
+ export declare function detectTestRunner(cwd: string): Promise<TestRunner>;
3
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAe,MAAM,SAAS,CAAC;AAElD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmEvE"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectTestRunner = detectTestRunner;
4
+ const promises_1 = require("fs/promises");
5
+ const path_1 = require("path");
6
+ async function detectTestRunner(cwd) {
7
+ try {
8
+ const packageJsonPath = (0, path_1.join)(cwd, 'package.json');
9
+ const content = await (0, promises_1.readFile)(packageJsonPath, 'utf-8');
10
+ const pkg = JSON.parse(content);
11
+ const allDeps = {
12
+ ...pkg.dependencies,
13
+ ...pkg.devDependencies
14
+ };
15
+ // Check for test runners in dependencies
16
+ if (allDeps['vitest']) {
17
+ return {
18
+ name: 'vitest',
19
+ command: getTestCommand(pkg, 'vitest'),
20
+ detected: true
21
+ };
22
+ }
23
+ if (allDeps['jest'] || allDeps['@jest/core']) {
24
+ return {
25
+ name: 'jest',
26
+ command: getTestCommand(pkg, 'jest'),
27
+ detected: true
28
+ };
29
+ }
30
+ if (allDeps['mocha']) {
31
+ return {
32
+ name: 'mocha',
33
+ command: getTestCommand(pkg, 'mocha'),
34
+ detected: true
35
+ };
36
+ }
37
+ if (allDeps['ava']) {
38
+ return {
39
+ name: 'ava',
40
+ command: getTestCommand(pkg, 'ava'),
41
+ detected: true
42
+ };
43
+ }
44
+ if (allDeps['tape']) {
45
+ return {
46
+ name: 'tape',
47
+ command: getTestCommand(pkg, 'tape'),
48
+ detected: true
49
+ };
50
+ }
51
+ // Fallback to npm test
52
+ return {
53
+ name: 'unknown',
54
+ command: 'npm test',
55
+ detected: false
56
+ };
57
+ }
58
+ catch (err) {
59
+ console.error('Could not detect test runner:', err);
60
+ return {
61
+ name: 'unknown',
62
+ command: 'npm test',
63
+ detected: false
64
+ };
65
+ }
66
+ }
67
+ function getTestCommand(pkg, runner) {
68
+ const scripts = pkg.scripts || {};
69
+ // Check for test script
70
+ if (scripts.test) {
71
+ return 'npm test';
72
+ }
73
+ // Return direct command
74
+ return runner;
75
+ }
76
+ //# sourceMappingURL=detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.js","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":";;AAIA,4CAmEC;AAvED,0CAAuC;AACvC,+BAA4B;AAGrB,KAAK,UAAU,gBAAgB,CAAC,GAAW;IAC9C,IAAI,CAAC;QACD,MAAM,eAAe,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,GAAG,GAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE7C,MAAM,OAAO,GAAG;YACZ,GAAG,GAAG,CAAC,YAAY;YACnB,GAAG,GAAG,CAAC,eAAe;SACzB,CAAC;QAEF,yCAAyC;QACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpB,OAAO;gBACH,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC;gBACtC,QAAQ,EAAE,IAAI;aACjB,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3C,OAAO;gBACH,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC;gBACpC,QAAQ,EAAE,IAAI;aACjB,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnB,OAAO;gBACH,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC;gBACrC,QAAQ,EAAE,IAAI;aACjB,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO;gBACH,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC;gBACnC,QAAQ,EAAE,IAAI;aACjB,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClB,OAAO;gBACH,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC;gBACpC,QAAQ,EAAE,IAAI;aACjB,CAAC;QACN,CAAC;QAED,uBAAuB;QACvB,OAAO;YACH,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,KAAK;SAClB,CAAC;IAEN,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;QACpD,OAAO;YACH,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,KAAK;SAClB,CAAC;IACN,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,GAAgB,EAAE,MAAc;IACpD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAElC,wBAAwB;IACxB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,wBAAwB;IACxB,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { TestFailure, FixResult } from './types';
2
+ export declare function fixTestFailure(failure: TestFailure, cwd: string, dryRun?: boolean): Promise<FixResult | null>;
3
+ //# sourceMappingURL=fixer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixer.d.ts","sourceRoot":"","sources":["../src/fixer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAkB,MAAM,SAAS,CAAC;AAEjE,wBAAsB,cAAc,CAChC,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,OAAe,GACxB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAmE3B"}
package/dist/fixer.js ADDED
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fixTestFailure = fixTestFailure;
4
+ const promises_1 = require("fs/promises");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ async function fixTestFailure(failure, cwd, dryRun = false) {
8
+ console.log(`\n๐Ÿ” Analyzing: ${failure.testName}`);
9
+ console.log(`๐Ÿ“„ Test file: ${failure.testFile}`);
10
+ try {
11
+ // Read test file
12
+ const testFilePath = (0, path_1.join)(cwd, failure.testFile);
13
+ if (!(0, fs_1.existsSync)(testFilePath)) {
14
+ console.error(`โŒ Test file not found: ${testFilePath}`);
15
+ return null;
16
+ }
17
+ const testCode = await (0, promises_1.readFile)(testFilePath, 'utf-8');
18
+ // Read source file
19
+ const sourceFilePath = (0, path_1.join)(cwd, failure.sourceFile || 'src/index.ts');
20
+ let sourceCode = '';
21
+ if ((0, fs_1.existsSync)(sourceFilePath)) {
22
+ sourceCode = await (0, promises_1.readFile)(sourceFilePath, 'utf-8');
23
+ console.log(`๐Ÿ“„ Source file: ${failure.sourceFile}`);
24
+ }
25
+ else {
26
+ console.log(`โš ๏ธ Source file not found: ${sourceFilePath}`);
27
+ console.log(` Will analyze test file only`);
28
+ }
29
+ // Call Claude API
30
+ console.log(`\n๐Ÿค– Asking Claude to analyze the failure...`);
31
+ const fix = await callClaudeAPI(failure, testCode, sourceCode);
32
+ if (!fix) {
33
+ console.error(`โŒ Claude could not provide a fix`);
34
+ return null;
35
+ }
36
+ console.log(`\n๐Ÿ’ก Claude's Analysis:`);
37
+ console.log(fix.analysis);
38
+ console.log(`\n๐Ÿ“ Fixing: ${fix.fileToFix}`);
39
+ // Read the file to fix
40
+ const fileToFixPath = (0, path_1.join)(cwd, fix.fileToFix);
41
+ const originalCode = (0, fs_1.existsSync)(fileToFixPath)
42
+ ? await (0, promises_1.readFile)(fileToFixPath, 'utf-8')
43
+ : '';
44
+ if (dryRun) {
45
+ console.log(`\n๐Ÿ” DRY RUN - No files will be modified`);
46
+ console.log(`\nProposed changes to ${fix.fileToFix}:\n`);
47
+ console.log('--- Original');
48
+ console.log('+++ Fixed');
49
+ console.log(generateDiff(originalCode, fix.fix));
50
+ }
51
+ else {
52
+ // Apply the fix
53
+ await (0, promises_1.writeFile)(fileToFixPath, fix.fix, 'utf-8');
54
+ console.log(`โœ… Applied fix to ${fix.fileToFix}`);
55
+ }
56
+ return {
57
+ analysis: fix.analysis,
58
+ fileToFix: fix.fileToFix,
59
+ originalCode,
60
+ fixedCode: fix.fix,
61
+ confidence: fix.confidence || 'medium'
62
+ };
63
+ }
64
+ catch (err) {
65
+ console.error(`โŒ Error fixing test:`, err);
66
+ return null;
67
+ }
68
+ }
69
+ async function callClaudeAPI(failure, testCode, sourceCode) {
70
+ const prompt = `You are a test debugging expert. A test is failing and you need to fix it.
71
+
72
+ TEST INFORMATION:
73
+ - Test file: ${failure.testFile}
74
+ - Test name: ${failure.testName}
75
+ - Error: ${failure.error}
76
+ - Stack trace: ${failure.stackTrace}
77
+
78
+ TEST CODE:
79
+ \`\`\`typescript
80
+ ${testCode}
81
+ \`\`\`
82
+
83
+ ${sourceCode ? `SOURCE CODE:\n\`\`\`typescript\n${sourceCode}\n\`\`\`` : ''}
84
+
85
+ INSTRUCTIONS:
86
+ 1. Analyze why the test is failing
87
+ 2. Determine which file needs to be fixed (usually the source code, not the test)
88
+ 3. Provide the complete fixed code for that file
89
+ 4. Be conservative - only fix the specific bug causing the test failure
90
+
91
+ Respond ONLY with valid JSON in this exact format:
92
+ {
93
+ "analysis": "Brief explanation of the bug and the fix",
94
+ "fileToFix": "path/to/file.ts",
95
+ "fix": "complete fixed code for the entire file",
96
+ "confidence": "high|medium|low"
97
+ }
98
+
99
+ Do not include any markdown formatting, backticks, or preamble. Just the JSON.`;
100
+ try {
101
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
102
+ method: 'POST',
103
+ headers: {
104
+ 'Content-Type': 'application/json',
105
+ 'anthropic-version': '2023-06-01',
106
+ 'x-api-key': process.env.ANTHROPIC_API_KEY || ''
107
+ },
108
+ body: JSON.stringify({
109
+ model: 'claude-sonnet-4-5-20250929',
110
+ max_tokens: 8000,
111
+ messages: [
112
+ {
113
+ role: 'user',
114
+ content: prompt
115
+ }
116
+ ]
117
+ })
118
+ });
119
+ if (!response.ok) {
120
+ const error = await response.text();
121
+ console.error('Claude API error:', error);
122
+ return null;
123
+ }
124
+ const data = await response.json();
125
+ const content = data.content[0].text;
126
+ // Parse JSON response
127
+ const cleanContent = content
128
+ .replace(/```json/g, '')
129
+ .replace(/```/g, '')
130
+ .trim();
131
+ const parsed = JSON.parse(cleanContent);
132
+ return parsed;
133
+ }
134
+ catch (err) {
135
+ console.error('Error calling Claude API:', err);
136
+ return null;
137
+ }
138
+ }
139
+ function generateDiff(original, fixed) {
140
+ const originalLines = original.split('\n');
141
+ const fixedLines = fixed.split('\n');
142
+ const maxLines = Math.max(originalLines.length, fixedLines.length);
143
+ const diff = [];
144
+ for (let i = 0; i < maxLines; i++) {
145
+ const origLine = originalLines[i] || '';
146
+ const fixedLine = fixedLines[i] || '';
147
+ if (origLine !== fixedLine) {
148
+ if (origLine)
149
+ diff.push(`- ${origLine}`);
150
+ if (fixedLine)
151
+ diff.push(`+ ${fixedLine}`);
152
+ }
153
+ }
154
+ return diff.slice(0, 20).join('\n') + (diff.length > 20 ? '\n... (truncated)' : '');
155
+ }
156
+ //# sourceMappingURL=fixer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixer.js","sourceRoot":"","sources":["../src/fixer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { TestFailure, TestRunner } from './types';
2
+ export declare function parseTestFailures(output: string, runner: TestRunner): TestFailure[];
3
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAElD,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GACnB,WAAW,EAAE,CAaf"}
package/dist/parser.js ADDED
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTestFailures = parseTestFailures;
4
+ function parseTestFailures(output, runner) {
5
+ switch (runner.name) {
6
+ case 'jest':
7
+ return parseJestFailures(output);
8
+ case 'vitest':
9
+ return parseVitestFailures(output);
10
+ case 'mocha':
11
+ return parseMochaFailures(output);
12
+ case 'ava':
13
+ return parseAvaFailures(output);
14
+ default:
15
+ return parseGenericFailures(output);
16
+ }
17
+ }
18
+ function parseJestFailures(output) {
19
+ const failures = [];
20
+ // Jest format:
21
+ // FAIL tests/calculator.test.ts
22
+ // โ— should add two numbers
23
+ // expect(received).toBe(expected)
24
+ const lines = output.split('\n');
25
+ let currentFile = '';
26
+ let currentTest = '';
27
+ let errorLines = [];
28
+ let stackLines = [];
29
+ let inError = false;
30
+ let inStack = false;
31
+ for (let i = 0; i < lines.length; i++) {
32
+ const line = lines[i];
33
+ // Detect test file
34
+ if (line.match(/FAIL\s+(.+\.test\.(ts|js|tsx|jsx))/)) {
35
+ const match = line.match(/FAIL\s+(.+\.test\.(ts|js|tsx|jsx))/);
36
+ if (match) {
37
+ currentFile = match[1].trim();
38
+ }
39
+ }
40
+ // Detect test name
41
+ if (line.includes('โ—') && !line.includes('FAIL')) {
42
+ if (currentTest && errorLines.length > 0) {
43
+ // Save previous failure
44
+ failures.push({
45
+ testFile: currentFile,
46
+ testName: currentTest,
47
+ error: errorLines.join('\n'),
48
+ stackTrace: stackLines.join('\n'),
49
+ sourceFile: inferSourceFile(currentFile)
50
+ });
51
+ }
52
+ currentTest = line.replace('โ—', '').trim();
53
+ errorLines = [];
54
+ stackLines = [];
55
+ inError = true;
56
+ inStack = false;
57
+ continue;
58
+ }
59
+ // Collect error lines
60
+ if (inError && line.trim() && !line.includes('at ')) {
61
+ errorLines.push(line.trim());
62
+ }
63
+ // Detect stack trace
64
+ if (line.trim().startsWith('at ')) {
65
+ inError = false;
66
+ inStack = true;
67
+ }
68
+ if (inStack && line.trim().startsWith('at ')) {
69
+ stackLines.push(line.trim());
70
+ }
71
+ }
72
+ // Save last failure
73
+ if (currentTest && errorLines.length > 0) {
74
+ failures.push({
75
+ testFile: currentFile,
76
+ testName: currentTest,
77
+ error: errorLines.join('\n'),
78
+ stackTrace: stackLines.join('\n'),
79
+ sourceFile: inferSourceFile(currentFile)
80
+ });
81
+ }
82
+ return failures;
83
+ }
84
+ function parseVitestFailures(output) {
85
+ // Vitest has similar format to Jest
86
+ return parseJestFailures(output);
87
+ }
88
+ function parseMochaFailures(output) {
89
+ const failures = [];
90
+ // Mocha format:
91
+ // 1) should add two numbers:
92
+ // AssertionError: expected 5 to equal 4
93
+ const lines = output.split('\n');
94
+ let currentTest = '';
95
+ let errorLines = [];
96
+ let testFile = '';
97
+ for (let i = 0; i < lines.length; i++) {
98
+ const line = lines[i];
99
+ // Detect test name (e.g., "1) should add")
100
+ if (line.match(/^\s*\d+\)\s+(.+):/)) {
101
+ if (currentTest && errorLines.length > 0) {
102
+ failures.push({
103
+ testFile: testFile || 'unknown',
104
+ testName: currentTest,
105
+ error: errorLines.join('\n'),
106
+ stackTrace: '',
107
+ sourceFile: inferSourceFile(testFile)
108
+ });
109
+ }
110
+ const match = line.match(/^\s*\d+\)\s+(.+):/);
111
+ currentTest = match ? match[1].trim() : '';
112
+ errorLines = [];
113
+ continue;
114
+ }
115
+ // Collect error lines
116
+ if (currentTest && line.trim() && !line.includes('at ')) {
117
+ errorLines.push(line.trim());
118
+ }
119
+ // Try to find file from stack
120
+ if (line.includes('.test.') || line.includes('.spec.')) {
121
+ const fileMatch = line.match(/\((.+\.test\.(js|ts|tsx|jsx)):\d+:\d+\)/);
122
+ if (fileMatch) {
123
+ testFile = fileMatch[1];
124
+ }
125
+ }
126
+ }
127
+ // Save last failure
128
+ if (currentTest && errorLines.length > 0) {
129
+ failures.push({
130
+ testFile: testFile || 'unknown',
131
+ testName: currentTest,
132
+ error: errorLines.join('\n'),
133
+ stackTrace: '',
134
+ sourceFile: inferSourceFile(testFile)
135
+ });
136
+ }
137
+ return failures;
138
+ }
139
+ function parseAvaFailures(output) {
140
+ const failures = [];
141
+ // AVA format:
142
+ // โœ– should add two numbers
143
+ // Assertion failed
144
+ const lines = output.split('\n');
145
+ let currentTest = '';
146
+ let errorLines = [];
147
+ for (let i = 0; i < lines.length; i++) {
148
+ const line = lines[i];
149
+ if (line.trim().startsWith('โœ–')) {
150
+ if (currentTest && errorLines.length > 0) {
151
+ failures.push({
152
+ testFile: 'unknown',
153
+ testName: currentTest,
154
+ error: errorLines.join('\n'),
155
+ stackTrace: ''
156
+ });
157
+ }
158
+ currentTest = line.replace('โœ–', '').trim();
159
+ errorLines = [];
160
+ continue;
161
+ }
162
+ if (currentTest && line.trim() && !line.includes('at ')) {
163
+ errorLines.push(line.trim());
164
+ }
165
+ }
166
+ if (currentTest && errorLines.length > 0) {
167
+ failures.push({
168
+ testFile: 'unknown',
169
+ testName: currentTest,
170
+ error: errorLines.join('\n'),
171
+ stackTrace: ''
172
+ });
173
+ }
174
+ return failures;
175
+ }
176
+ function parseGenericFailures(output) {
177
+ // Generic parser for unknown test runners
178
+ const failures = [];
179
+ if (output.toLowerCase().includes('fail') ||
180
+ output.toLowerCase().includes('error')) {
181
+ failures.push({
182
+ testFile: 'unknown',
183
+ testName: 'Test failure detected',
184
+ error: output.slice(0, 500), // First 500 chars
185
+ stackTrace: ''
186
+ });
187
+ }
188
+ return failures;
189
+ }
190
+ function inferSourceFile(testFile) {
191
+ if (!testFile || testFile === 'unknown') {
192
+ return 'src/index.ts';
193
+ }
194
+ // Remove test/spec suffix and path
195
+ // tests/calculator.test.ts -> src/calculator.ts
196
+ // __tests__/utils.spec.js -> src/utils.js
197
+ let sourceFile = testFile
198
+ .replace(/\.test\./, '.')
199
+ .replace(/\.spec\./, '.')
200
+ .replace(/^tests\//, 'src/')
201
+ .replace(/^__tests__\//, 'src/')
202
+ .replace(/^test\//, 'src/');
203
+ return sourceFile;
204
+ }
205
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface TestRunResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ passed: boolean;
6
+ }
7
+ export declare function runTests(command: string, cwd: string): Promise<TestRunResult>;
8
+ export declare function runSingleTest(command: string, testFile: string, cwd: string): Promise<TestRunResult>;
9
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAyBnF;AAED,wBAAsB,aAAa,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,CAAC,CAIxB"}
package/dist/runner.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runTests = runTests;
4
+ exports.runSingleTest = runSingleTest;
5
+ const child_process_1 = require("child_process");
6
+ const util_1 = require("util");
7
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
8
+ async function runTests(command, cwd) {
9
+ console.log(`\n๐Ÿงช Running tests: ${command}\n`);
10
+ try {
11
+ const { stdout, stderr } = await execAsync(command, {
12
+ cwd,
13
+ env: { ...process.env, FORCE_COLOR: '0' }, // Disable colors for easier parsing
14
+ maxBuffer: 10 * 1024 * 1024 // 10MB buffer
15
+ });
16
+ return {
17
+ stdout,
18
+ stderr,
19
+ exitCode: 0,
20
+ passed: true
21
+ };
22
+ }
23
+ catch (err) {
24
+ // Tests failed (exit code !== 0)
25
+ return {
26
+ stdout: err.stdout || '',
27
+ stderr: err.stderr || '',
28
+ exitCode: err.code || 1,
29
+ passed: false
30
+ };
31
+ }
32
+ }
33
+ async function runSingleTest(command, testFile, cwd) {
34
+ // Run only the specific test file
35
+ const singleTestCommand = `${command} ${testFile}`;
36
+ return runTests(singleTestCommand, cwd);
37
+ }
38
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":";;AAYA,4BAyBC;AAED,sCAQC;AA/CD,iDAAqC;AACrC,+BAAiC;AAEjC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,oBAAI,CAAC,CAAC;AAS3B,KAAK,UAAU,QAAQ,CAAC,OAAe,EAAE,GAAW;IACvD,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,IAAI,CAAC,CAAC;IAEhD,IAAI,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE;YAChD,GAAG;YACH,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,oCAAoC;YAC/E,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,cAAc;SAC7C,CAAC,CAAC;QAEH,OAAO;YACH,MAAM;YACN,MAAM;YACN,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,IAAI;SACf,CAAC;IACN,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,iCAAiC;QACjC,OAAO;YACH,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;YACxB,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;YACxB,QAAQ,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;YACvB,MAAM,EAAE,KAAK;SAChB,CAAC;IACN,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,aAAa,CAC/B,OAAe,EACf,QAAgB,EAChB,GAAW;IAEX,kCAAkC;IAClC,MAAM,iBAAiB,GAAG,GAAG,OAAO,IAAI,QAAQ,EAAE,CAAC;IACnD,OAAO,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,32 @@
1
+ export interface TestFailure {
2
+ testFile: string;
3
+ testName: string;
4
+ error: string;
5
+ stackTrace: string;
6
+ sourceFile?: string;
7
+ lineNumber?: number;
8
+ }
9
+ export interface TestRunner {
10
+ name: 'jest' | 'vitest' | 'mocha' | 'ava' | 'tape' | 'unknown';
11
+ command: string;
12
+ detected: boolean;
13
+ }
14
+ export interface FixResult {
15
+ analysis: string;
16
+ fileToFix: string;
17
+ originalCode: string;
18
+ fixedCode: string;
19
+ confidence: 'high' | 'medium' | 'low';
20
+ }
21
+ export interface ClaudeResponse {
22
+ analysis: string;
23
+ fileToFix: string;
24
+ fix: string;
25
+ confidence?: string;
26
+ }
27
+ export interface PackageJson {
28
+ scripts?: Record<string, string>;
29
+ devDependencies?: Record<string, string>;
30
+ dependencies?: Record<string, string>;
31
+ }
32
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "fix-tests-ai",
3
+ "version": "0.1.0",
4
+ "description": "Automatically fix failing tests using Claude AI",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "fix-tests": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "prepublishOnly": "npm run build",
18
+ "test": "echo 'No tests yet'"
19
+ },
20
+ "keywords": [
21
+ "testing",
22
+ "ai",
23
+ "claude",
24
+ "automation",
25
+ "fix",
26
+ "debug"
27
+ ],
28
+ "author": "Gabriel Azambuja",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/starslingdev/refactored-palm-tree"
33
+ },
34
+ "dependencies": {
35
+ "@types/node": "^20.0.0",
36
+ "dotenv": "^17.2.3"
37
+ },
38
+ "devDependencies": {
39
+ "@types/dotenv": "^6.1.1",
40
+ "typescript": "^5.3.0"
41
+ },
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ }
45
+ }