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 +21 -0
- package/README.md +321 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +297 -0
- package/dist/cli.js.map +1 -0
- package/dist/detector.d.ts +3 -0
- package/dist/detector.d.ts.map +1 -0
- package/dist/detector.js +76 -0
- package/dist/detector.js.map +1 -0
- package/dist/fixer.d.ts +3 -0
- package/dist/fixer.d.ts.map +1 -0
- package/dist/fixer.js +156 -0
- package/dist/fixer.js.map +1 -0
- package/dist/parser.d.ts +3 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +205 -0
- package/dist/parser.js.map +1 -0
- package/dist/runner.d.ts +9 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +38 -0
- package/dist/runner.js.map +1 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
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 @@
|
|
|
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
|
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":"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"}
|
package/dist/detector.js
ADDED
|
@@ -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"}
|
package/dist/fixer.d.ts
ADDED
|
@@ -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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"}
|
package/dist/parser.d.ts
ADDED
|
@@ -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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"}
|
package/dist/runner.d.ts
ADDED
|
@@ -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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
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
|
+
}
|