Skip to content

fix: Jest XML path resolution and runner support for monorepos#1315

Merged
mohammedahmed18 merged 6 commits intomainfrom
fix/jest-xml-path-resolution-monorepo
Feb 3, 2026
Merged

fix: Jest XML path resolution and runner support for monorepos#1315
mohammedahmed18 merged 6 commits intomainfrom
fix/jest-xml-path-resolution-monorepo

Conversation

@mohammedahmed18
Copy link
Contributor

Summary

This PR fixes two critical issues preventing CodeFlash from working in monorepo environments like Budibase when running from the workspace root.

Changes

  1. Jest XML test path resolution - Handle relative paths with .. components in monorepos
  2. Jest runner monorepo resolution - Find jest-runner in parent node_modules directories
  3. Flexible test parsing - Allow result parsing even when test files are cleaned up

Problem 1: Test Path Resolution

When running CodeFlash from a monorepo root (e.g., ~/budibase), Jest XML reports contain relative paths like:

../../tests/test_validEmail__unit_test_1.test.ts

These paths couldn't be resolved because:

  • The base_dir is /home/user/budibase/tests
  • The path ../../tests/... needs proper resolution to find the actual file
  • Test files may be cleaned up before parsing completes

Example Failure

WARNING: Could not resolve test file for Jest test: ../../tests/test_validEmail__unit_test_1.test.ts
INFO: No Jest test results parsed from jest_results.xml (found 2 suites, 60 testcases)
WARNING: Couldn't run any tests for original function validEmail

Problem 2: Jest Runner Resolution

When running in a monorepo package (e.g., packages/backend-core), jest-runner is installed at the workspace root:

budibase/
├── node_modules/
│   └── jest-runner/          # Installed here
└── packages/
    └── backend-core/
        └── node_modules/     # Not here

The loop-runner would fail with:

Error: codeflash/loop-runner requires jest-runner to be installed.
Please install it: npm install --save-dev jest-runner

Solution

1. Improved Path Resolution

# Before: Simple concatenation failed with .. paths
potential_path = base_dir / test_class_path

# After: Use .resolve() to handle .. and . components
potential_path = (base_dir / test_class_path).resolve()

2. Monorepo-Aware Jest Runner Resolution

function resolveJestRunner() {
    // Try standard resolution first (simple projects)
    try {
        return require.resolve('jest-runner');
    } catch (e) {
        // Walk up directory tree for monorepos
    }

    const monorepoMarkers = ['yarn.lock', 'pnpm-workspace.yaml', 'lerna.json'];
    let currentDir = process.cwd();

    while (currentDir !== path.dirname(currentDir)) {
        // Check for jest-runner in node_modules at this level
        const jestRunnerPath = path.join(currentDir, 'node_modules', 'jest-runner');
        if (fs.existsSync(jestRunnerPath)) {
            return jestRunnerPath;
        }

        // Stop at workspace root markers
        if (monorepoMarkers.some(marker => 
            fs.existsSync(path.join(currentDir, marker))
        )) {
            break;
        }

        currentDir = path.dirname(currentDir);
    }
}

3. Flexible Test Type Inference

# Infer test type from filename pattern when files don't exist
filename = test_file_path.name
if "__perf_test_" in filename:
    test_type = TestType.GENERATED_PERFORMANCE
elif "__unit_test_" in filename:
    test_type = TestType.GENERATED_REGRESSION

Testing

Before (Failure)

cd ~/budibase
codeflash --file packages/backend-core/src/utils/stringUtils.ts --function validEmail

# Output:
# WARNING: Could not resolve test file for Jest test
# ERROR: No Jest test results parsed
# ERROR: Failed to establish a baseline

After (Success)

cd ~/budibase
codeflash --file packages/backend-core/src/utils/stringUtils.ts --function validEmail

# Output:
# ✓ Generated Regression Tests - Passed: 59, Failed: 0
# ✓ Running performance benchmarks...
# ✓ Baseline established

Test Results on Budibase Monorepo

Function Location Behavioral Tests Status
validEmail packages/backend-core/src/utils/stringUtils.ts 59 passed
punctuateList packages/shared-core/src/helpers/lists.ts 51 passed
isDevWorkspaceID packages/backend-core/src/docIds/conversions.ts 63 passed

Impact

✅ Fixes

  • Jest test path resolution in monorepos
  • Jest runner detection in workspaces
  • Test result parsing after cleanup

✅ Maintains Backward Compatibility

  • Standard require.resolve() tried first for simple projects
  • Falls back to monorepo resolution only when needed
  • No changes to existing non-monorepo workflows

✅ Tested On

  • Budibase monorepo (Yarn workspaces)
  • Running from workspace root directory
  • Multiple packages: backend-core, server, shared-core

Files Changed

  • codeflash/verification/parse_test_output.py - Path resolution with .resolve() and flexible test type inference
  • packages/codeflash/runtime/loop-runner.js - Monorepo-aware jest-runner resolution

🤖 Generated with Claude Code

mohammedahmed18 and others added 2 commits February 3, 2026 12:32
When running in monorepos, test files may be cleaned up before results
are parsed. This fix:
1. Uses .resolve() to properly handle relative paths with .. components
2. Infers test type from filename pattern when files don't exist
3. Removes requirement for test files to exist when parsing results

Tested on Budibase monorepo - behavioral tests now parse correctly.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added resolveJestRunner() function that walks up the directory tree to
find jest-runner in workspace root node_modules. This fixes the
"jest-runner requires jest-runner to be installed" error when running
in monorepo packages.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Walks up the directory tree looking for node_modules/jest-runner.
*/
function resolveJestRunner() {
// Try standard resolution first (works in simple projects)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use _find_js_project_root or _find_project_root function too to figure out the project root.

Copy link
Contributor

@Saga4 Saga4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add unit tests for figuring out root path.

…lution

Instead of duplicating monorepo detection logic in JavaScript, leverage
the existing Python _find_node_project_root and add _find_monorepo_root
functions. Pass the detected monorepo root via CODEFLASH_MONOREPO_ROOT
environment variable to the loop-runner.

This approach:
- Reuses existing Python project detection logic
- Provides a reliable monorepo root hint to JavaScript
- Maintains fallback directory traversal for edge cases

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@mohammedahmed18 mohammedahmed18 force-pushed the fix/jest-xml-path-resolution-monorepo branch from a815e54 to 7f954d1 Compare February 3, 2026 14:26
Saga4 and others added 3 commits February 3, 2026 20:00
jest-runner v30+ uses webpack bundling and doesn't export runTest separately.
This commit adds version detection and implements external looping for v30+
while maintaining loop-runner support for v29.x.

Changes:
- Added _get_jest_runner_version() to detect installed jest-runner version
- Modified run_jest_benchmarking_tests() to check version and choose strategy
- For v29: Use loop-runner (in-process batching)
- For v30+: Use external looping (run Jest multiple times)
- External looping respects min_loops, max_loops, and target_duration_ms

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@mohammedahmed18 mohammedahmed18 requested a review from Saga4 February 3, 2026 14:43
@mohammedahmed18 mohammedahmed18 merged commit 2f19cdd into main Feb 3, 2026
25 of 27 checks passed
@mohammedahmed18 mohammedahmed18 deleted the fix/jest-xml-path-resolution-monorepo branch February 3, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants