Skip to content

Commit 0f2c50c

Browse files
authored
Merge pull request #1982 from codeflash-ai/fix/vitest-mock-path-resolution
Fix vi.mock() path resolution in generated vitest tests
2 parents c63defa + cdb361b commit 0f2c50c

2 files changed

Lines changed: 101 additions & 7 deletions

File tree

codeflash/languages/javascript/instrument.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,13 +1287,13 @@ def fix_imports_inside_test_blocks(test_code: str) -> str:
12871287

12881288

12891289
def fix_jest_mock_paths(test_code: str, test_file_path: Path, source_file_path: Path, tests_root: Path) -> str:
1290-
"""Fix relative paths in jest.mock() calls to be correct from the test file's location.
1290+
"""Fix relative paths in jest.mock() and vi.mock() calls to be correct from the test file's location.
12911291
1292-
The AI sometimes generates jest.mock() calls with paths relative to the source file
1292+
The AI sometimes generates mock calls with paths relative to the source file
12931293
instead of the test file. For example:
12941294
- Source at `src/queue/queue.ts` imports `../environment` (-> src/environment)
1295-
- Test at `tests/test.test.ts` generates `jest.mock('../environment')` (-> ./environment, wrong!)
1296-
- Should generate `jest.mock('../src/environment')`
1295+
- Test at `tests/test.test.ts` generates `jest.mock('../environment')` or `vi.mock('../environment')` (-> ./environment, wrong!)
1296+
- Should generate `jest.mock('../src/environment')` or `vi.mock('../src/environment')`
12971297
12981298
This function detects relative mock paths and adjusts them based on the test file's
12991299
location relative to the source file's directory.
@@ -1318,8 +1318,8 @@ def fix_jest_mock_paths(test_code: str, test_file_path: Path, source_file_path:
13181318
test_dir = test_file_path.resolve().parent
13191319
project_root = tests_root.resolve().parent if tests_root.name == "tests" else tests_root.resolve()
13201320

1321-
# Pattern to match jest.mock() or jest.doMock() with relative paths
1322-
mock_pattern = re.compile(r"(jest\.(?:mock|doMock)\s*\(\s*['\"])(\.\./[^'\"]+|\.\/[^'\"]+)(['\"])")
1321+
# Pattern to match jest.mock(), jest.doMock(), or vi.mock() with relative paths
1322+
mock_pattern = re.compile(r"((?:jest|vi)\.(?:mock|doMock)\s*\(\s*['\"])(\.\./[^'\"]+|\.\/[^'\"]+)(['\"])")
13231323

13241324
def fix_mock_path(match: re.Match[str]) -> str:
13251325
original = match.group(0)
@@ -1359,7 +1359,7 @@ def fix_mock_path(match: re.Match[str]) -> str:
13591359
if not new_rel_path.startswith("../") and not new_rel_path.startswith("./"):
13601360
new_rel_path = f"./{new_rel_path}"
13611361

1362-
logger.debug(f"Fixed jest.mock path: {rel_path} -> {new_rel_path}")
1362+
logger.debug(f"Fixed mock path: {rel_path} -> {new_rel_path}")
13631363
return f"{prefix}{new_rel_path}{suffix}"
13641364

13651365
except (ValueError, OSError):
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""Test fix_jest_mock_paths function with vitest mocks."""
2+
3+
from pathlib import Path
4+
5+
from codeflash.languages.javascript.instrument import fix_jest_mock_paths
6+
7+
8+
def test_fix_vitest_mock_paths():
9+
"""Test that vi.mock() paths are fixed correctly."""
10+
# Simulate source at src/agents/workspace.ts importing from ../routing/session-key
11+
# Test at test/test_workspace.test.ts should mock ../src/routing/session-key, not ../routing/session-key
12+
13+
test_code = """
14+
vi.mock('../routing/session-key', () => ({
15+
isSubagentSessionKey: vi.fn(),
16+
isCronSessionKey: vi.fn(),
17+
}));
18+
19+
import { filterBootstrapFilesForSession } from '../src/agents/workspace.js';
20+
"""
21+
22+
# Create temp directories and files for testing
23+
import tempfile
24+
25+
with tempfile.TemporaryDirectory() as tmpdir:
26+
project = Path(tmpdir)
27+
28+
# Create directory structure
29+
src = project / "src"
30+
src_agents = src / "agents"
31+
src_routing = src / "routing"
32+
test_dir = project / "test"
33+
34+
src_agents.mkdir(parents=True)
35+
src_routing.mkdir(parents=True)
36+
test_dir.mkdir(parents=True)
37+
38+
# Create files
39+
source_file = src_agents / "workspace.ts"
40+
source_file.write_text("export function filterBootstrapFilesForSession() {}")
41+
42+
routing_file = src_routing / "session-key.ts"
43+
routing_file.write_text("export function isSubagentSessionKey() {}")
44+
45+
test_file = test_dir / "test_workspace.test.ts"
46+
test_file.write_text(test_code)
47+
48+
# Fix the paths
49+
fixed = fix_jest_mock_paths(test_code, test_file, source_file, test_dir)
50+
51+
# Should change ../routing/session-key to ../src/routing/session-key
52+
assert "../src/routing/session-key" in fixed, f"Expected path to be fixed, got: {fixed}"
53+
assert "../routing/session-key" not in fixed or "../src/routing/session-key" in fixed
54+
55+
56+
def test_fix_jest_mock_paths_still_works():
57+
"""Test that jest.mock() paths are still fixed correctly."""
58+
test_code = """
59+
jest.mock('../routing/session-key', () => ({
60+
isSubagentSessionKey: jest.fn(),
61+
}));
62+
"""
63+
64+
import tempfile
65+
66+
with tempfile.TemporaryDirectory() as tmpdir:
67+
project = Path(tmpdir)
68+
src = project / "src"
69+
src_agents = src / "agents"
70+
src_routing = src / "routing"
71+
test_dir = project / "test"
72+
73+
src_agents.mkdir(parents=True)
74+
src_routing.mkdir(parents=True)
75+
test_dir.mkdir(parents=True)
76+
77+
source_file = src_agents / "workspace.ts"
78+
source_file.write_text("")
79+
80+
routing_file = src_routing / "session-key.ts"
81+
routing_file.write_text("")
82+
83+
test_file = test_dir / "test_workspace.test.ts"
84+
test_file.write_text(test_code)
85+
86+
fixed = fix_jest_mock_paths(test_code, test_file, source_file, test_dir)
87+
88+
assert "../src/routing/session-key" in fixed
89+
90+
91+
if __name__ == "__main__":
92+
test_fix_vitest_mock_paths()
93+
test_fix_jest_mock_paths_still_works()
94+
print("All tests passed!")

0 commit comments

Comments
 (0)