codeflash/tests/test_languages/test_vitest_e2e.py
Kevin Turcios eceac13fc3 Merge remote-tracking branch 'origin/main' into omni-java
# Conflicts:
#	.claude/rules/architecture.md
#	.claude/rules/code-style.md
#	.github/workflows/claude.yml
#	.github/workflows/duplicate-code-detector.yml
#	codeflash/api/aiservice.py
#	codeflash/cli_cmds/console.py
#	codeflash/cli_cmds/logging_config.py
#	codeflash/code_utils/deduplicate_code.py
#	codeflash/discovery/discover_unit_tests.py
#	codeflash/languages/base.py
#	codeflash/languages/code_replacer.py
#	codeflash/languages/javascript/mocha_runner.py
#	codeflash/languages/javascript/support.py
#	codeflash/languages/python/support.py
#	codeflash/optimization/function_optimizer.py
#	codeflash/verification/parse_test_output.py
#	codeflash/verification/verification_utils.py
#	codeflash/verification/verifier.py
#	packages/codeflash/package-lock.json
#	packages/codeflash/package.json
#	tests/languages/javascript/test_support_dispatch.py
#	tests/test_codeflash_capture.py
#	tests/test_languages/test_javascript_test_runner.py
#	tests/test_multi_file_code_replacement.py
2026-03-04 01:52:32 -05:00

310 lines
12 KiB
Python

"""End-to-end integration tests for Vitest pipeline.
Tests the full optimization pipeline for Vitest projects:
- Function discovery
- Code context extraction
- Test discovery
- Test framework detection
Note: These tests require JS/TS language support to be registered.
They will be skipped in environments where only Python is supported.
"""
from pathlib import Path
import pytest
from codeflash.code_utils.config_js import detect_test_runner, get_package_json_data
def skip_if_js_not_supported():
"""Skip test if JavaScript/TypeScript languages are not supported."""
try:
from codeflash.languages import get_language_support
from codeflash.languages.base import Language
get_language_support(Language.JAVASCRIPT)
except Exception as e:
pytest.skip(f"JavaScript/TypeScript language support not available: {e}")
class TestVitestProjectDiscovery:
"""Tests for function discovery in a Vitest project."""
@pytest.fixture
def vitest_project_dir(self):
"""Get the Vitest sample project directory."""
project_root = Path(__file__).parent.parent.parent
vitest_dir = project_root / "code_to_optimize" / "js" / "code_to_optimize_vitest"
if not vitest_dir.exists():
pytest.skip("code_to_optimize_vitest directory not found")
return vitest_dir
def test_detects_vitest_as_test_runner(self, vitest_project_dir):
"""Test that Vitest is detected as the test runner."""
package_json = vitest_project_dir / "package.json"
package_data = get_package_json_data(package_json)
assert package_data is not None
runner = detect_test_runner(vitest_project_dir, package_data)
assert runner == "vitest"
def test_discover_functions_in_fibonacci(self, vitest_project_dir):
"""Test discovering functions in fibonacci.ts."""
skip_if_js_not_supported()
from codeflash.discovery.functions_to_optimize import find_all_functions_in_file
fib_file = vitest_project_dir / "fibonacci.ts"
if not fib_file.exists():
pytest.skip("fibonacci.ts not found")
functions = find_all_functions_in_file(fib_file)
assert fib_file in functions
func_list = functions[fib_file]
func_names = {f.function_name for f in func_list}
assert func_names == {"fibonacci", "isFibonacci", "isPerfectSquare", "fibonacciSequence"}
for func in func_list:
assert func.language == "typescript"
def test_discover_functions_in_string_utils(self, vitest_project_dir):
"""Test discovering functions in string_utils.ts."""
skip_if_js_not_supported()
from codeflash.discovery.functions_to_optimize import find_all_functions_in_file
utils_file = vitest_project_dir / "string_utils.ts"
if not utils_file.exists():
pytest.skip("string_utils.ts not found")
functions = find_all_functions_in_file(utils_file)
assert utils_file in functions
func_list = functions[utils_file]
func_names = {f.function_name for f in func_list}
assert func_names == {"reverseString", "isPalindrome", "countVowels", "uniqueWords"}
def test_get_typescript_files(self, vitest_project_dir):
"""Test getting TypeScript files from Vitest project directory."""
skip_if_js_not_supported()
from codeflash.discovery.functions_to_optimize import get_files_for_language
from codeflash.languages.base import Language
files = get_files_for_language(vitest_project_dir, Language.TYPESCRIPT)
ts_files = [f for f in files if f.suffix == ".ts" and "test" not in f.name]
assert len(ts_files) >= 2
root_files = [f for f in ts_files if f.parent == vitest_project_dir]
assert len(root_files) >= 2
class TestVitestCodeContext:
"""Tests for code context extraction in Vitest project."""
@pytest.fixture
def vitest_project_dir(self):
"""Get the Vitest sample project directory."""
project_root = Path(__file__).parent.parent.parent
vitest_dir = project_root / "code_to_optimize" / "js" / "code_to_optimize_vitest"
if not vitest_dir.exists():
pytest.skip("code_to_optimize_vitest directory not found")
return vitest_dir
def test_extract_code_context_for_typescript(self, vitest_project_dir):
"""Test extracting code context for a TypeScript function."""
skip_if_js_not_supported()
from codeflash.discovery.functions_to_optimize import find_all_functions_in_file
from codeflash.languages import get_language_support
from codeflash.languages.base import Language
from codeflash.languages.javascript.function_optimizer import JavaScriptFunctionOptimizer
fib_file = vitest_project_dir / "fibonacci.ts"
if not fib_file.exists():
pytest.skip("fibonacci.ts not found")
functions = find_all_functions_in_file(fib_file)
func_list = functions[fib_file]
fib_func = next((f for f in func_list if f.function_name == "fibonacci"), None)
assert fib_func is not None
ts_support = get_language_support(Language.TYPESCRIPT)
code_context = ts_support.extract_code_context(fib_func, vitest_project_dir, vitest_project_dir)
context = JavaScriptFunctionOptimizer._build_optimization_context(
code_context, fib_file, "typescript", vitest_project_dir
)
assert context.read_writable_code is not None
assert context.read_writable_code.language == "typescript"
assert len(context.read_writable_code.code_strings) > 0
code = context.read_writable_code.code_strings[0].code
expected_code = """export function fibonacci(n: number): number {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
"""
assert code == expected_code
class TestVitestTestDiscovery:
"""Tests for Vitest test discovery."""
@pytest.fixture
def vitest_project_dir(self):
"""Get the Vitest sample project directory."""
project_root = Path(__file__).parent.parent.parent
vitest_dir = project_root / "code_to_optimize" / "js" / "code_to_optimize_vitest"
if not vitest_dir.exists():
pytest.skip("code_to_optimize_vitest directory not found")
return vitest_dir
def test_discover_vitest_tests(self, vitest_project_dir):
"""Test discovering Vitest tests for TypeScript functions."""
skip_if_js_not_supported()
from codeflash.languages import get_language_support
from codeflash.languages.base import FunctionInfo, Language
ts_support = get_language_support(Language.TYPESCRIPT)
test_root = vitest_project_dir / "tests"
if not test_root.exists():
pytest.skip("tests directory not found")
fib_file = vitest_project_dir / "fibonacci.ts"
func_info = FunctionInfo(
function_name="fibonacci", file_path=fib_file, starting_line=11, ending_line=16, language="typescript"
)
tests = ts_support.discover_tests(test_root, [func_info])
assert func_info.qualified_name in tests or len(tests) > 0
class TestVitestRunnerDispatch:
"""Tests for Vitest runner dispatch in support.py."""
@pytest.fixture
def vitest_project_dir(self):
"""Get the Vitest sample project directory."""
project_root = Path(__file__).parent.parent.parent
vitest_dir = project_root / "code_to_optimize" / "js" / "code_to_optimize_vitest"
if not vitest_dir.exists():
pytest.skip("code_to_optimize_vitest directory not found")
return vitest_dir
def test_language_support_has_test_framework_property(self):
"""Test that JavaScriptSupport has test_framework property."""
skip_if_js_not_supported()
from codeflash.languages import get_language_support
from codeflash.languages.base import Language
js_support = get_language_support(Language.JAVASCRIPT)
ts_support = get_language_support(Language.TYPESCRIPT)
assert js_support.test_framework == "jest"
assert ts_support.test_framework == "jest"
def test_behavioral_tests_accepts_test_framework(self):
"""Test that run_behavioral_tests accepts test_framework parameter."""
skip_if_js_not_supported()
import inspect
from codeflash.languages import get_language_support
from codeflash.languages.base import Language
ts_support = get_language_support(Language.TYPESCRIPT)
sig = inspect.signature(ts_support.run_behavioral_tests)
params = list(sig.parameters.keys())
assert "test_framework" in params
def test_benchmarking_tests_accepts_test_framework(self):
"""Test that run_benchmarking_tests accepts test_framework parameter."""
skip_if_js_not_supported()
import inspect
from codeflash.languages import get_language_support
from codeflash.languages.base import Language
ts_support = get_language_support(Language.TYPESCRIPT)
sig = inspect.signature(ts_support.run_benchmarking_tests)
params = list(sig.parameters.keys())
assert "test_framework" in params
def test_line_profile_tests_accepts_test_framework(self):
"""Test that run_line_profile_tests accepts test_framework parameter."""
skip_if_js_not_supported()
import inspect
from codeflash.languages import get_language_support
from codeflash.languages.base import Language
ts_support = get_language_support(Language.TYPESCRIPT)
sig = inspect.signature(ts_support.run_line_profile_tests)
params = list(sig.parameters.keys())
assert "test_framework" in params
class TestVitestVsJestDetection:
"""Tests comparing Vitest and Jest project detection."""
@pytest.fixture
def jest_project_dir(self):
"""Get the Jest sample project directory."""
project_root = Path(__file__).parent.parent.parent
jest_dir = project_root / "code_to_optimize" / "js" / "code_to_optimize_ts"
if not jest_dir.exists():
pytest.skip("code_to_optimize_ts directory not found")
return jest_dir
@pytest.fixture
def vitest_project_dir(self):
"""Get the Vitest sample project directory."""
project_root = Path(__file__).parent.parent.parent
vitest_dir = project_root / "code_to_optimize" / "js" / "code_to_optimize_vitest"
if not vitest_dir.exists():
pytest.skip("code_to_optimize_vitest directory not found")
return vitest_dir
def test_jest_detected_in_jest_project(self, jest_project_dir):
"""Test that Jest is detected in the Jest project."""
package_json = jest_project_dir / "package.json"
package_data = get_package_json_data(package_json)
assert package_data is not None
runner = detect_test_runner(jest_project_dir, package_data)
assert runner == "jest"
def test_vitest_detected_in_vitest_project(self, vitest_project_dir):
"""Test that Vitest is detected in the Vitest project."""
package_json = vitest_project_dir / "package.json"
package_data = get_package_json_data(package_json)
assert package_data is not None
runner = detect_test_runner(vitest_project_dir, package_data)
assert runner == "vitest"
def test_vitest_prioritized_over_jest(self, tmp_path):
"""Test that Vitest is prioritized when both are present."""
import json
package_json = tmp_path / "package.json"
package_json.write_text(
json.dumps({"name": "test", "devDependencies": {"vitest": "^2.0.0", "jest": "^29.0.0"}})
)
package_data = get_package_json_data(package_json)
runner = detect_test_runner(tmp_path, package_data)
assert runner == "vitest"