From 390397ec6c0c22bfe1d2cff7d64f5af692b780b4 Mon Sep 17 00:00:00 2001 From: mohammedahmed18 Date: Wed, 4 Feb 2026 09:31:41 +0000 Subject: [PATCH 1/3] fix: support monorepo hoisted dependencies in JS requirements check The verify_requirements() method only checked for test frameworks (jest/vitest) in the local package's node_modules. In monorepos with workspace hoisting (yarn/pnpm), dependencies are often installed at the workspace root instead. Changes: - Check both local node_modules and workspace root node_modules - Use _find_monorepo_root() to locate workspace root - Add debug logging for framework resolution - Update docstring to document monorepo support Fixes false positive "jest is not installed" warnings in monorepo projects where jest is hoisted to the workspace root. Tested with Budibase monorepo where jest is at workspace root. --- codeflash/languages/javascript/support.py | 47 +++++++++++++++++------ 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/codeflash/languages/javascript/support.py b/codeflash/languages/javascript/support.py index eecf11064..820455fb3 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -1846,9 +1846,12 @@ 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 + 3. Test framework (jest/vitest) installation (with monorepo support) 4. node_modules existence + For monorepos, checks both local node_modules and workspace root node_modules + for hoisted dependencies. + Args: project_root: The project root directory. test_framework: The test framework to check for ("jest" or "vitest"). @@ -1879,16 +1882,38 @@ 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." - ) - else: - # Check test framework is installed - framework_path = node_modules / test_framework - if not framework_path.exists(): + # Check test framework is installed (with monorepo support) + # First try local node_modules, then check workspace root for hoisted dependencies + framework_found = False + + # Check local node_modules + local_node_modules = project_root / "node_modules" + if local_node_modules.exists(): + local_framework = local_node_modules / test_framework + if local_framework.exists(): + framework_found = True + logger.debug("Found %s in local node_modules at %s", test_framework, local_framework) + + # If not found locally, check for hoisted dependencies in monorepo workspace root + if not framework_found: + from codeflash.languages.javascript.test_runner import _find_monorepo_root + + workspace_root = _find_monorepo_root(project_root) + if workspace_root: + workspace_framework = workspace_root / "node_modules" / test_framework + if workspace_framework.exists(): + framework_found = True + logger.debug( + "Found %s in workspace root node_modules at %s", test_framework, workspace_framework + ) + + # Report errors if framework not found anywhere + if not framework_found: + 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." From adc4832999a73e29457d81b223097815452929f5 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 09:33:24 +0000 Subject: [PATCH 2/3] style: auto-fix formatting issues --- codeflash/languages/javascript/support.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/codeflash/languages/javascript/support.py b/codeflash/languages/javascript/support.py index 820455fb3..19016ddda 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -1903,9 +1903,7 @@ def verify_requirements(self, project_root: Path, test_framework: str = "jest") workspace_framework = workspace_root / "node_modules" / test_framework if workspace_framework.exists(): framework_found = True - logger.debug( - "Found %s in workspace root node_modules at %s", test_framework, workspace_framework - ) + logger.debug("Found %s in workspace root node_modules at %s", test_framework, workspace_framework) # Report errors if framework not found anywhere if not framework_found: From 54110a821e525821f46c55ee852f0910ec370d55 Mon Sep 17 00:00:00 2001 From: mohammedahmed18 Date: Wed, 4 Feb 2026 09:58:33 +0000 Subject: [PATCH 3/3] refactor: move test framework discovery to init_javascript - Add find_node_modules_with_package() to init_javascript.py - Uses same tree-search pattern as determine_js_package_manager() - Simplify verify_requirements() to use the new helper - Reduces code duplication and centralizes monorepo logic Benefits: - Consistent monorepo support across codebase - Single source of truth for finding node_modules - Easier to maintain and test - Works alongside determine_js_package_manager() pattern --- codeflash/cli_cmds/init_javascript.py | 26 +++++++++++++++ codeflash/languages/javascript/support.py | 39 +++++++---------------- 2 files changed, 38 insertions(+), 27 deletions(-) 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 19016ddda..7ba69ce50 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -1847,10 +1847,10 @@ def verify_requirements(self, project_root: Path, test_framework: str = "jest") 1. Node.js installation 2. npm availability 3. Test framework (jest/vitest) installation (with monorepo support) - 4. node_modules existence - For monorepos, checks both local node_modules and workspace root node_modules - for hoisted dependencies. + 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. @@ -1883,30 +1883,15 @@ def verify_requirements(self, project_root: Path, test_framework: str = "jest") errors.append(f"Failed to check npm: {e}") # Check test framework is installed (with monorepo support) - # First try local node_modules, then check workspace root for hoisted dependencies - framework_found = False - - # Check local node_modules - local_node_modules = project_root / "node_modules" - if local_node_modules.exists(): - local_framework = local_node_modules / test_framework - if local_framework.exists(): - framework_found = True - logger.debug("Found %s in local node_modules at %s", test_framework, local_framework) - - # If not found locally, check for hoisted dependencies in monorepo workspace root - if not framework_found: - from codeflash.languages.javascript.test_runner import _find_monorepo_root - - workspace_root = _find_monorepo_root(project_root) - if workspace_root: - workspace_framework = workspace_root / "node_modules" / test_framework - if workspace_framework.exists(): - framework_found = True - logger.debug("Found %s in workspace root node_modules at %s", test_framework, workspace_framework) - - # Report errors if framework not found anywhere - if not framework_found: + # 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 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."