diff --git a/codeflash/cli_cmds/init_javascript.py b/codeflash/cli_cmds/init_javascript.py index 2977323bb..d88c69904 100644 --- a/codeflash/cli_cmds/init_javascript.py +++ b/codeflash/cli_cmds/init_javascript.py @@ -146,6 +146,32 @@ def determine_js_package_manager(project_root: Path) -> JsPackageManager: return JsPackageManager.UNKNOWN +def find_node_modules_with_package(project_root: Path, package_name: str) -> Path | None: + """Find node_modules directory containing a specific package. + + Searches from project_root up to filesystem root for node_modules containing + the specified package. This supports monorepo setups where dependencies are + hoisted to the workspace root. + + Args: + project_root: Starting directory for the search. + package_name: Name of the package to look for (e.g., "jest", "vitest"). + + Returns: + Path to the node_modules directory containing the package, or None if not found. + + """ + current_dir = project_root.resolve() + while current_dir != current_dir.parent: + node_modules = current_dir / "node_modules" + if node_modules.exists(): + package_path = node_modules / package_name + if package_path.exists(): + return node_modules + current_dir = current_dir.parent + return None + + def get_package_install_command(project_root: Path, package: str, dev: bool = True) -> list[str]: """Get the correct install command for the project's package manager. diff --git a/codeflash/languages/javascript/support.py b/codeflash/languages/javascript/support.py index eecf11064..7ba69ce50 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -1846,8 +1846,11 @@ def verify_requirements(self, project_root: Path, test_framework: str = "jest") Checks for: 1. Node.js installation 2. npm availability - 3. Test framework (jest/vitest) installation - 4. node_modules existence + 3. Test framework (jest/vitest) installation (with monorepo support) + + Uses find_node_modules_with_package() from init_javascript to search up the + directory tree for node_modules containing the test framework. This supports + monorepo setups where dependencies are hoisted to the workspace root. Args: project_root: The project root directory. @@ -1879,16 +1882,21 @@ def verify_requirements(self, project_root: Path, test_framework: str = "jest") except Exception as e: errors.append(f"Failed to check npm: {e}") - # Check node_modules exists - node_modules = project_root / "node_modules" - if not node_modules.exists(): - errors.append( - f"node_modules not found in {project_root}. Please run 'npm install' to install dependencies." - ) + # Check test framework is installed (with monorepo support) + # Uses find_node_modules_with_package which searches up the directory tree + from codeflash.cli_cmds.init_javascript import find_node_modules_with_package + + node_modules = find_node_modules_with_package(project_root, test_framework) + if node_modules: + logger.debug("Found %s in node_modules at %s", test_framework, node_modules / test_framework) else: - # Check test framework is installed - framework_path = node_modules / test_framework - if not framework_path.exists(): + # Check if local node_modules exists at all + local_node_modules = project_root / "node_modules" + if not local_node_modules.exists(): + errors.append( + f"node_modules not found in {project_root}. Please run 'npm install' to install dependencies." + ) + else: errors.append( f"{test_framework} is not installed. " f"Please run 'npm install --save-dev {test_framework}' to install it."