add vitest runner

This commit is contained in:
Sarthak Agarwal 2026-01-31 04:29:59 +05:30
parent c56002f287
commit 4bf664dc39
13 changed files with 7838 additions and 137 deletions

View file

@ -14,15 +14,13 @@
}
},
"../../../packages/codeflash": {
"version": "0.1.0",
"version": "0.3.1",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@msgpack/msgpack": "^3.0.0",
"better-sqlite3": "^12.0.0",
"jest-junit": "^16.0.0",
"jest-runner": "^29.7.0"
"better-sqlite3": "^12.0.0"
},
"bin": {
"codeflash": "bin/codeflash.js",
@ -33,7 +31,8 @@
},
"peerDependencies": {
"jest": ">=27.0.0",
"jest-runner": ">=27.0.0"
"jest-runner": ">=27.0.0",
"vitest": ">=1.0.0"
},
"peerDependenciesMeta": {
"jest": {
@ -41,6 +40,9 @@
},
"jest-runner": {
"optional": true
},
"vitest": {
"optional": true
}
}
},

View file

@ -14,15 +14,13 @@
}
},
"../../../packages/codeflash": {
"version": "0.2.0",
"version": "0.3.1",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@msgpack/msgpack": "^3.0.0",
"better-sqlite3": "^12.0.0",
"jest-junit": "^16.0.0",
"jest-runner": "^29.7.0"
"better-sqlite3": "^12.0.0"
},
"bin": {
"codeflash": "bin/codeflash.js",
@ -33,7 +31,8 @@
},
"peerDependencies": {
"jest": ">=27.0.0",
"jest-runner": ">=27.0.0"
"jest-runner": ">=27.0.0",
"vitest": ">=1.0.0"
},
"peerDependenciesMeta": {
"jest": {
@ -41,6 +40,9 @@
},
"jest-runner": {
"optional": true
},
"vitest": {
"optional": true
}
}
},

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,7 @@
}
},
"../../../packages/codeflash": {
"version": "0.1.0",
"version": "0.3.1",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@ -36,11 +36,19 @@
"node": ">=18.0.0"
},
"peerDependencies": {
"jest": ">=27.0.0"
"jest": ">=27.0.0",
"jest-runner": ">=27.0.0",
"vitest": ">=1.0.0"
},
"peerDependenciesMeta": {
"jest": {
"optional": true
},
"jest-runner": {
"optional": true
},
"vitest": {
"optional": true
}
}
},

View file

@ -15,15 +15,13 @@
}
},
"../../../packages/codeflash": {
"version": "0.3.0",
"version": "0.3.1",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@msgpack/msgpack": "^3.0.0",
"better-sqlite3": "^12.0.0",
"jest-junit": "^16.0.0",
"jest-runner": "^29.7.0"
"better-sqlite3": "^12.0.0"
},
"bin": {
"codeflash": "bin/codeflash.js",
@ -34,7 +32,8 @@
},
"peerDependencies": {
"jest": ">=27.0.0",
"jest-runner": ">=27.0.0"
"jest-runner": ">=27.0.0",
"vitest": ">=1.0.0"
},
"peerDependenciesMeta": {
"jest": {
@ -42,6 +41,9 @@
},
"jest-runner": {
"optional": true
},
"vitest": {
"optional": true
}
}
},

View file

@ -12,6 +12,7 @@ from codeflash.cli_cmds.extension import install_vscode_extension
from codeflash.code_utils import env_utils
from codeflash.code_utils.code_utils import exit_with_message
from codeflash.code_utils.config_parser import parse_config_file
from codeflash.languages.test_framework import set_current_test_framework
from codeflash.lsp.helpers import is_LSP_enabled
from codeflash.version import __version__ as version
@ -210,6 +211,11 @@ def process_pyproject_config(args: Namespace) -> Namespace:
# For JS/TS projects, tests_root is optional (Jest auto-discovers tests)
# Default to module_root if not specified
is_js_ts_project = pyproject_config.get("language") in ("javascript", "typescript")
# Set the test framework singleton for JS/TS projects
if is_js_ts_project and pyproject_config.get("test_runner"):
set_current_test_framework(pyproject_config["test_runner"])
if args.tests_root is None:
if is_js_ts_project:
# Try common JS test directories, or default to module_root

View file

@ -48,9 +48,19 @@ from codeflash.languages.registry import (
get_supported_languages,
register_language,
)
from codeflash.languages.test_framework import (
current_test_framework,
get_js_test_framework_or_default,
is_jest,
is_mocha,
is_pytest,
is_unittest,
is_vitest,
reset_test_framework,
set_current_test_framework,
)
__all__ = [
# Base types
"CodeContext",
"FunctionInfo",
"HelperFunction",
@ -59,18 +69,25 @@ __all__ = [
"ParentInfo",
"TestInfo",
"TestResult",
# Current language singleton
"current_language",
"current_language_support",
# Registry functions
"current_test_framework",
"detect_project_language",
"get_js_test_framework_or_default",
"get_language_support",
"get_supported_extensions",
"get_supported_languages",
"is_javascript",
"is_jest",
"is_mocha",
"is_pytest",
"is_python",
"is_typescript",
"is_unittest",
"is_vitest",
"register_language",
"reset_current_language",
"reset_test_framework",
"set_current_language",
"set_current_test_framework",
]

View file

@ -1925,7 +1925,7 @@ class JavaScriptSupport:
project_root: Path | None = None,
enable_coverage: bool = False,
candidate_index: int = 0,
test_framework: str = "jest",
test_framework: str | None = None,
) -> tuple[Path, Any, Path | None, Path | None]:
"""Run behavioral tests using the detected test framework.
@ -1937,13 +1937,17 @@ class JavaScriptSupport:
project_root: Project root directory.
enable_coverage: Whether to collect coverage information.
candidate_index: Index of the candidate being tested.
test_framework: Test framework to use ("jest" or "vitest").
test_framework: Test framework to use ("jest" or "vitest"). If None, uses singleton.
Returns:
Tuple of (result_file_path, subprocess_result, coverage_path, config_path).
"""
if test_framework == "vitest":
from codeflash.languages.test_framework import get_js_test_framework_or_default
framework = test_framework or get_js_test_framework_or_default()
if framework == "vitest":
from codeflash.languages.javascript.vitest_runner import run_vitest_behavioral_tests
return run_vitest_behavioral_tests(
@ -1978,7 +1982,7 @@ class JavaScriptSupport:
min_loops: int = 5,
max_loops: int = 100_000,
target_duration_seconds: float = 10.0,
test_framework: str = "jest",
test_framework: str | None = None,
) -> tuple[Path, Any]:
"""Run benchmarking tests using the detected test framework.
@ -1991,13 +1995,17 @@ class JavaScriptSupport:
min_loops: Minimum number of loops for benchmarking.
max_loops: Maximum number of loops for benchmarking.
target_duration_seconds: Target duration for benchmarking in seconds.
test_framework: Test framework to use ("jest" or "vitest").
test_framework: Test framework to use ("jest" or "vitest"). If None, uses singleton.
Returns:
Tuple of (result_file_path, subprocess_result).
"""
if test_framework == "vitest":
from codeflash.languages.test_framework import get_js_test_framework_or_default
framework = test_framework or get_js_test_framework_or_default()
if framework == "vitest":
from codeflash.languages.javascript.vitest_runner import run_vitest_benchmarking_tests
return run_vitest_benchmarking_tests(
@ -2032,7 +2040,7 @@ class JavaScriptSupport:
timeout: int | None = None,
project_root: Path | None = None,
line_profile_output_file: Path | None = None,
test_framework: str = "jest",
test_framework: str | None = None,
) -> tuple[Path, Any]:
"""Run tests for line profiling using the detected test framework.
@ -2043,13 +2051,17 @@ class JavaScriptSupport:
timeout: Optional timeout in seconds.
project_root: Project root directory.
line_profile_output_file: Path where line profile results will be written.
test_framework: Test framework to use ("jest" or "vitest").
test_framework: Test framework to use ("jest" or "vitest"). If None, uses singleton.
Returns:
Tuple of (result_file_path, subprocess_result).
"""
if test_framework == "vitest":
from codeflash.languages.test_framework import get_js_test_framework_or_default
framework = test_framework or get_js_test_framework_or_default()
if framework == "vitest":
from codeflash.languages.javascript.vitest_runner import run_vitest_line_profile_tests
return run_vitest_line_profile_tests(

View file

@ -51,6 +51,22 @@ def _find_vitest_project_root(file_path: Path) -> Path | None:
return None
def _is_vitest_coverage_available(project_root: Path) -> bool:
"""Check if Vitest coverage package is available.
Args:
project_root: The project root directory.
Returns:
True if @vitest/coverage-v8 or @vitest/coverage-istanbul is installed.
"""
node_modules = project_root / "node_modules"
return (node_modules / "@vitest" / "coverage-v8").exists() or (
node_modules / "@vitest" / "coverage-istanbul"
).exists()
def _ensure_runtime_files(project_root: Path) -> None:
"""Ensure JavaScript runtime package is installed in the project.
@ -217,15 +233,19 @@ def run_vitest_behavioral_tests(
# Ensure the codeflash npm package is installed
_ensure_runtime_files(effective_cwd)
# Coverage output directory
# Coverage output directory - only enable if coverage package is available
coverage_dir = get_run_tmp_file(Path("vitest_coverage"))
coverage_json_path = coverage_dir / "coverage-final.json" if enable_coverage else None
coverage_available = _is_vitest_coverage_available(effective_cwd) if enable_coverage else False
coverage_json_path = coverage_dir / "coverage-final.json" if coverage_available else None
if enable_coverage and not coverage_available:
logger.debug("Vitest coverage package not installed, running without coverage")
# Build Vitest command
vitest_cmd = _build_vitest_behavioral_command(test_files=test_files, timeout=timeout, output_file=result_file_path)
# Add coverage flags if enabled
if enable_coverage:
# Add coverage flags only if coverage is available
if coverage_available:
vitest_cmd.extend(["--coverage", "--coverage.reporter=json", f"--coverage.reportsDirectory={coverage_dir}"])
# Set up environment

View file

@ -0,0 +1,145 @@
"""Singleton for the current test framework being used in the codeflash session.
This module provides a centralized way to access and set the current test framework
throughout the codeflash codebase, similar to how the language singleton works.
For JavaScript/TypeScript projects, this determines whether to use Jest or Vitest
for test execution.
Usage:
from codeflash.languages.test_framework import (
current_test_framework,
set_current_test_framework,
is_jest,
is_vitest,
)
# Set the test framework at the start of a session (auto-detected from package.json)
set_current_test_framework("vitest")
# Check the current test framework anywhere in the codebase
if is_vitest():
# Vitest-specific code
...
# Get the current test framework
framework = current_test_framework()
"""
from __future__ import annotations
from typing import Literal
TestFramework = Literal["jest", "vitest", "mocha", "pytest", "unittest"]
# Module-level singleton for the current test framework
_current_test_framework: TestFramework | None = None
def current_test_framework() -> TestFramework | None:
"""Get the current test framework being used in this codeflash session.
Returns:
The current test framework string, or None if not set.
"""
return _current_test_framework
def set_current_test_framework(framework: TestFramework | str | None) -> None:
"""Set the current test framework for this codeflash session.
This should be called once at the start of an optimization run,
typically after reading the project configuration.
Args:
framework: Test framework name ("jest", "vitest", "mocha", "pytest", "unittest").
"""
global _current_test_framework
if _current_test_framework is not None:
return
if framework is not None:
framework = framework.lower()
if framework not in ("jest", "vitest", "mocha", "pytest", "unittest"):
# Default to jest for unknown JS frameworks, pytest for unknown Python
from codeflash.languages.current import is_javascript
framework = "jest" if is_javascript() else "pytest"
_current_test_framework = framework
def reset_test_framework() -> None:
"""Reset the current test framework to None.
Useful for testing or when starting a new session.
"""
global _current_test_framework
_current_test_framework = None
def is_jest() -> bool:
"""Check if the current test framework is Jest.
Returns:
True if the current test framework is Jest.
"""
return _current_test_framework == "jest"
def is_vitest() -> bool:
"""Check if the current test framework is Vitest.
Returns:
True if the current test framework is Vitest.
"""
return _current_test_framework == "vitest"
def is_mocha() -> bool:
"""Check if the current test framework is Mocha.
Returns:
True if the current test framework is Mocha.
"""
return _current_test_framework == "mocha"
def is_pytest() -> bool:
"""Check if the current test framework is pytest.
Returns:
True if the current test framework is pytest.
"""
return _current_test_framework == "pytest"
def is_unittest() -> bool:
"""Check if the current test framework is unittest.
Returns:
True if the current test framework is unittest.
"""
return _current_test_framework == "unittest"
def get_js_test_framework_or_default() -> TestFramework:
"""Get the current test framework for JS/TS, defaulting to 'jest' if not set.
This is a convenience function for JS/TS code that needs a framework.
Returns:
The current test framework, or 'jest' as default.
"""
if _current_test_framework in ("jest", "vitest", "mocha"):
return _current_test_framework
return "jest"

View file

@ -1,6 +1,6 @@
{
"name": "codeflash",
"version": "0.3.0",
"version": "0.3.1",
"description": "Codeflash - AI-powered code optimization for JavaScript and TypeScript",
"main": "runtime/index.js",
"types": "runtime/index.d.ts",
@ -9,7 +9,7 @@
"codeflash-setup": "./bin/codeflash-setup.js"
},
"publishConfig": {
"access": "public"
"access": "public"
},
"exports": {
".": {
@ -52,7 +52,8 @@
"typescript",
"ai",
"cli",
"jest"
"jest",
"vitest"
],
"author": "Codeflash AI",
"license": "MIT",
@ -70,7 +71,8 @@
},
"peerDependencies": {
"jest": ">=27.0.0",
"jest-runner": ">=27.0.0"
"jest-runner": ">=27.0.0",
"vitest": ">=1.0.0"
},
"peerDependenciesMeta": {
"jest": {
@ -78,12 +80,13 @@
},
"jest-runner": {
"optional": true
},
"vitest": {
"optional": true
}
},
"dependencies": {
"better-sqlite3": "^12.0.0",
"@msgpack/msgpack": "^3.0.0",
"jest-runner": "^29.7.0",
"jest-junit": "^16.0.0"
"@msgpack/msgpack": "^3.0.0"
}
}

View file

@ -20,6 +20,10 @@
*
* Usage:
* npx jest --runner=codeflash/loop-runner
*
* NOTE: This runner requires jest-runner to be installed in your project.
* It is a Jest-specific feature and does not work with Vitest.
* For Vitest projects, external looping is handled by the Python runner.
*/
'use strict';
@ -27,9 +31,20 @@
const { createRequire } = require('module');
const path = require('path');
const jestRunnerPath = require.resolve('jest-runner');
const internalRequire = createRequire(jestRunnerPath);
const runTest = internalRequire('./runTest').default;
// Try to load jest-runner - it's a peer dependency that must be installed by the user
let runTest;
let jestRunnerAvailable = false;
try {
const jestRunnerPath = require.resolve('jest-runner');
const internalRequire = createRequire(jestRunnerPath);
runTest = internalRequire('./runTest').default;
jestRunnerAvailable = true;
} catch (e) {
// jest-runner not installed - this is expected for Vitest projects
// The runner will throw a helpful error if someone tries to use it without jest-runner
jestRunnerAvailable = false;
}
// Configuration
const MAX_BATCHES = parseInt(process.env.CODEFLASH_PERF_LOOP_COUNT || '10000', 10);
@ -90,6 +105,14 @@ function deepCopy(obj, seen = new WeakMap()) {
*/
class CodeflashLoopRunner {
constructor(globalConfig, context) {
if (!jestRunnerAvailable) {
throw new Error(
'codeflash/loop-runner requires jest-runner to be installed.\n' +
'Please install it: npm install --save-dev jest-runner\n\n' +
'If you are using Vitest, the loop-runner is not needed - ' +
'Vitest projects use external looping handled by the Python runner.'
);
}
this._globalConfig = globalConfig;
this._context = context || {};
this._eventEmitter = new SimpleEventEmitter();

View file

@ -2,7 +2,7 @@
These tests verify that run_behavioral_tests, run_benchmarking_tests, and
run_line_profile_tests correctly dispatch to Jest or Vitest based on the
test_framework parameter.
test_framework parameter or singleton.
"""
from __future__ import annotations
@ -13,6 +13,7 @@ from unittest.mock import MagicMock, patch
import pytest
from codeflash.languages.javascript.support import JavaScriptSupport, TypeScriptSupport
from codeflash.languages.test_framework import reset_test_framework, set_current_test_framework
@pytest.fixture
@ -27,6 +28,14 @@ def ts_support() -> TypeScriptSupport:
return TypeScriptSupport()
@pytest.fixture(autouse=True)
def reset_singleton() -> None:
"""Reset the test framework singleton before each test."""
reset_test_framework()
yield
reset_test_framework()
@pytest.fixture
def mock_test_paths() -> MagicMock:
"""Create a mock TestFiles object."""
@ -43,87 +52,54 @@ class TestBehavioralTestsDispatch:
@patch("codeflash.languages.javascript.test_runner.run_jest_behavioral_tests")
def test_dispatches_to_jest_by_default(
self,
mock_jest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should dispatch to Jest when test_framework is not specified."""
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
(tmp_path / "package.json").write_text('{"name": "test"}')
js_support.run_behavioral_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
)
js_support.run_behavioral_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
mock_jest_runner.assert_called_once()
@patch("codeflash.languages.javascript.test_runner.run_jest_behavioral_tests")
def test_dispatches_to_jest_explicitly(
self,
mock_jest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should dispatch to Jest when test_framework='jest'."""
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
(tmp_path / "package.json").write_text('{"name": "test"}')
js_support.run_behavioral_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
test_framework="jest",
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="jest"
)
mock_jest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_behavioral_tests")
def test_dispatches_to_vitest(
self,
mock_vitest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should dispatch to Vitest when test_framework='vitest'."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
(tmp_path / "package.json").write_text('{"name": "test"}')
js_support.run_behavioral_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
test_framework="vitest",
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
)
mock_vitest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_behavioral_tests")
def test_typescript_support_dispatches_to_vitest(
self,
mock_vitest_runner: MagicMock,
ts_support: TypeScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_vitest_runner: MagicMock, ts_support: TypeScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""TypeScriptSupport should also dispatch to Vitest when test_framework='vitest'."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
(tmp_path / "package.json").write_text('{"name": "test"}')
ts_support.run_behavioral_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
test_framework="vitest",
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
)
mock_vitest_runner.assert_called_once()
@ -134,54 +110,33 @@ class TestBenchmarkingTestsDispatch:
@patch("codeflash.languages.javascript.test_runner.run_jest_benchmarking_tests")
def test_dispatches_to_jest_by_default(
self,
mock_jest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should dispatch to Jest when test_framework is not specified."""
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock())
(tmp_path / "package.json").write_text('{"name": "test"}')
js_support.run_benchmarking_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
)
js_support.run_benchmarking_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
mock_jest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_benchmarking_tests")
def test_dispatches_to_vitest(
self,
mock_vitest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should dispatch to Vitest when test_framework='vitest'."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
(tmp_path / "package.json").write_text('{"name": "test"}')
js_support.run_benchmarking_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
test_framework="vitest",
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
)
mock_vitest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_benchmarking_tests")
def test_passes_loop_parameters(
self,
mock_vitest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should pass loop parameters to Vitest runner."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
@ -209,54 +164,33 @@ class TestLineProfileTestsDispatch:
@patch("codeflash.languages.javascript.test_runner.run_jest_line_profile_tests")
def test_dispatches_to_jest_by_default(
self,
mock_jest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should dispatch to Jest when test_framework is not specified."""
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock())
(tmp_path / "package.json").write_text('{"name": "test"}')
js_support.run_line_profile_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
)
js_support.run_line_profile_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
mock_jest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_line_profile_tests")
def test_dispatches_to_vitest(
self,
mock_vitest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should dispatch to Vitest when test_framework='vitest'."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
(tmp_path / "package.json").write_text('{"name": "test"}')
js_support.run_line_profile_tests(
test_paths=mock_test_paths,
test_env={},
cwd=tmp_path,
project_root=tmp_path,
test_framework="vitest",
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
)
mock_vitest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_line_profile_tests")
def test_passes_line_profile_output_file(
self,
mock_vitest_runner: MagicMock,
js_support: JavaScriptSupport,
mock_test_paths: MagicMock,
tmp_path: Path,
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should pass line_profile_output_file to Vitest runner."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
@ -286,3 +220,121 @@ class TestTestFrameworkProperty:
def test_typescript_default_framework_is_jest(self, ts_support: TypeScriptSupport) -> None:
"""TypeScriptSupport should have Jest as default test framework."""
assert ts_support.test_framework == "jest"
class TestTestFrameworkSingleton:
"""Tests for test_framework singleton behavior."""
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_behavioral_tests")
def test_uses_singleton_when_param_not_provided(
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Should use singleton test_framework when parameter is not provided."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
(tmp_path / "package.json").write_text('{"name": "test"}')
# Set singleton to vitest
set_current_test_framework("vitest")
# Don't pass test_framework parameter - should use singleton
js_support.run_behavioral_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
mock_vitest_runner.assert_called_once()
@patch("codeflash.languages.javascript.test_runner.run_jest_behavioral_tests")
def test_explicit_param_overrides_singleton(
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""Explicit test_framework parameter should override singleton."""
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
(tmp_path / "package.json").write_text('{"name": "test"}')
# Set singleton to vitest
set_current_test_framework("vitest")
# Pass explicit test_framework=jest - should override singleton
js_support.run_behavioral_tests(
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="jest"
)
mock_jest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_benchmarking_tests")
def test_benchmarking_uses_singleton(
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""run_benchmarking_tests should use singleton when param not provided."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
(tmp_path / "package.json").write_text('{"name": "test"}')
set_current_test_framework("vitest")
js_support.run_benchmarking_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
mock_vitest_runner.assert_called_once()
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_line_profile_tests")
def test_line_profile_uses_singleton(
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
) -> None:
"""run_line_profile_tests should use singleton when param not provided."""
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
(tmp_path / "package.json").write_text('{"name": "test"}')
set_current_test_framework("vitest")
js_support.run_line_profile_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
mock_vitest_runner.assert_called_once()
class TestTestFrameworkSingletonModule:
"""Tests for the test_framework singleton module itself."""
def test_initial_state_is_none(self) -> None:
"""Singleton should start as None."""
from codeflash.languages.test_framework import current_test_framework
assert current_test_framework() is None
def test_set_and_get(self) -> None:
"""Should be able to set and get test framework."""
from codeflash.languages.test_framework import current_test_framework, set_current_test_framework
set_current_test_framework("vitest")
assert current_test_framework() == "vitest"
def test_set_only_once(self) -> None:
"""Once set, singleton should not change."""
from codeflash.languages.test_framework import current_test_framework, set_current_test_framework
set_current_test_framework("jest")
set_current_test_framework("vitest") # Should be ignored
assert current_test_framework() == "jest"
def test_is_jest(self) -> None:
"""is_jest() should return True when framework is Jest."""
from codeflash.languages.test_framework import is_jest, set_current_test_framework
set_current_test_framework("jest")
assert is_jest() is True
def test_is_vitest(self) -> None:
"""is_vitest() should return True when framework is Vitest."""
from codeflash.languages.test_framework import is_vitest, set_current_test_framework
set_current_test_framework("vitest")
assert is_vitest() is True
def test_get_js_test_framework_or_default_returns_jest(self) -> None:
"""get_js_test_framework_or_default should return 'jest' when not set."""
from codeflash.languages.test_framework import get_js_test_framework_or_default
assert get_js_test_framework_or_default() == "jest"
def test_get_js_test_framework_or_default_returns_vitest(self) -> None:
"""get_js_test_framework_or_default should return 'vitest' when set."""
from codeflash.languages.test_framework import get_js_test_framework_or_default, set_current_test_framework
set_current_test_framework("vitest")
assert get_js_test_framework_or_default() == "vitest"