diff --git a/codeflash/languages/javascript/mocha_runner.py b/codeflash/languages/javascript/mocha_runner.py index 0dd385050..59d9c1043 100644 --- a/codeflash/languages/javascript/mocha_runner.py +++ b/codeflash/languages/javascript/mocha_runner.py @@ -185,14 +185,25 @@ def _extract_mocha_json(stdout: str) -> str | None: pass # Find the outermost JSON object containing "stats" + # Use find() to jump between braces instead of checking every character depth = 0 start = None - for i, ch in enumerate(stdout): - if ch == "{": + pos = 0 + while True: + next_open = stdout.find("{", pos) + next_close = stdout.find("}", pos) + + if next_open == -1 and next_close == -1: + break + + if next_open != -1 and (next_close == -1 or next_open < next_close): + i = next_open if depth == 0: start = i depth += 1 - elif ch == "}": + pos = i + 1 + else: + i = next_close depth -= 1 if depth == 0 and start is not None: candidate = stdout[start : i + 1] @@ -203,19 +214,72 @@ def _extract_mocha_json(stdout: str) -> str | None: except json.JSONDecodeError: pass start = None + pos = i + 1 return None -def _build_mocha_command( - test_files: list[Path], timeout: int | None = None, default_timeout_ms: int = 60000 +def _build_mocha_behavioral_command( + test_files: list[Path], timeout: int | None = None, project_root: Path | None = None +) -> list[str]: + """Build Mocha command for behavioral tests. + + Args: + test_files: List of test files to run. + timeout: Optional timeout in seconds (converted to ms for Mocha). + project_root: Project root directory. + + Returns: + Command list for subprocess execution. + + """ + cmd = ["npx", "mocha", "--reporter", "json", "--jobs", "1", "--exit"] + + if timeout: + cmd.extend(["--timeout", str(timeout * 1000)]) + else: + cmd.extend(["--timeout", "60000"]) + + cmd.extend(str(f.resolve()) for f in test_files) + + return cmd + + +def _build_mocha_benchmarking_command( + test_files: list[Path], timeout: int | None = None, project_root: Path | None = None +) -> list[str]: + """Build Mocha command for benchmarking tests. + + Args: + test_files: List of test files to run. + timeout: Optional timeout in seconds (converted to ms for Mocha). + project_root: Project root directory. + + Returns: + Command list for subprocess execution. + + """ + cmd = ["npx", "mocha", "--reporter", "json", "--jobs", "1", "--exit"] + + if timeout: + cmd.extend(["--timeout", str(timeout * 1000)]) + else: + cmd.extend(["--timeout", "120000"]) + + cmd.extend(str(f.resolve()) for f in test_files) + + return cmd + + +def _build_mocha_line_profile_command( + test_files: list[Path], timeout: int | None = None, project_root: Path | None = None ) -> list[str]: - """Build a Mocha command. + """Build Mocha command for line profiling tests. Args: test_files: List of test files to run. timeout: Optional timeout in seconds (converted to ms for Mocha). - default_timeout_ms: Default timeout in milliseconds when timeout is not provided. + project_root: Project root directory. Returns: Command list for subprocess execution. @@ -226,7 +290,7 @@ def _build_mocha_command( if timeout: cmd.extend(["--timeout", str(timeout * 1000)]) else: - cmd.extend(["--timeout", str(default_timeout_ms)]) + cmd.extend(["--timeout", "60000"]) cmd.extend(str(f.resolve()) for f in test_files) @@ -339,7 +403,7 @@ def run_mocha_behavioral_tests( _ensure_runtime_files(effective_cwd) - mocha_cmd = _build_mocha_command(test_files=test_files, timeout=timeout) + mocha_cmd = _build_mocha_behavioral_command(test_files=test_files, timeout=timeout, project_root=effective_cwd) mocha_env = test_env.copy() codeflash_sqlite_file = get_run_tmp_file(Path(f"test_return_values_{candidate_index}.sqlite")) @@ -423,7 +487,7 @@ def run_mocha_benchmarking_tests( _ensure_runtime_files(effective_cwd) - mocha_cmd = _build_mocha_command(test_files=test_files, timeout=timeout, default_timeout_ms=120000) + mocha_cmd = _build_mocha_benchmarking_command(test_files=test_files, timeout=timeout, project_root=effective_cwd) mocha_env = test_env.copy() codeflash_sqlite_file = get_run_tmp_file(Path("test_return_values_0.sqlite")) @@ -511,7 +575,7 @@ def run_mocha_line_profile_tests( _ensure_runtime_files(effective_cwd) - mocha_cmd = _build_mocha_command(test_files=test_files, timeout=timeout) + mocha_cmd = _build_mocha_line_profile_command(test_files=test_files, timeout=timeout, project_root=effective_cwd) mocha_env = test_env.copy() codeflash_sqlite_file = get_run_tmp_file(Path("test_return_values_line_profile.sqlite"))