Follow-up to #1909 — the npm package now installs into a dedicated venv instead of using uv tool, but these references were missed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
219 lines
8.8 KiB
Python
219 lines
8.8 KiB
Python
"""Tests for JavaScript/TypeScript GitHub Actions workflow helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from codeflash.cli_cmds.init_javascript import (
|
|
JsPackageManager,
|
|
get_js_codeflash_install_step,
|
|
get_js_codeflash_run_command,
|
|
get_js_dependency_installation_commands,
|
|
get_js_runtime_setup_steps,
|
|
is_codeflash_dependency,
|
|
)
|
|
|
|
|
|
class TestIsCodeflashDependency:
|
|
"""Tests for is_codeflash_dependency function."""
|
|
|
|
def test_returns_true_when_in_dev_dependencies(self, tmp_path: Path) -> None:
|
|
"""Should return True when codeflash is in devDependencies."""
|
|
package_json = tmp_path / "package.json"
|
|
package_json.write_text(json.dumps({"devDependencies": {"codeflash": "^1.0.0"}}))
|
|
|
|
assert is_codeflash_dependency(tmp_path) is True
|
|
|
|
def test_returns_true_when_in_dependencies(self, tmp_path: Path) -> None:
|
|
"""Should return True when codeflash is in dependencies."""
|
|
package_json = tmp_path / "package.json"
|
|
package_json.write_text(json.dumps({"dependencies": {"codeflash": "^1.0.0"}}))
|
|
|
|
assert is_codeflash_dependency(tmp_path) is True
|
|
|
|
def test_returns_false_when_not_present(self, tmp_path: Path) -> None:
|
|
"""Should return False when codeflash is not in any dependencies."""
|
|
package_json = tmp_path / "package.json"
|
|
package_json.write_text(json.dumps({"devDependencies": {"jest": "^29.0.0"}}))
|
|
|
|
assert is_codeflash_dependency(tmp_path) is False
|
|
|
|
def test_returns_false_when_no_package_json(self, tmp_path: Path) -> None:
|
|
"""Should return False when package.json doesn't exist."""
|
|
assert is_codeflash_dependency(tmp_path) is False
|
|
|
|
def test_returns_false_for_invalid_json(self, tmp_path: Path) -> None:
|
|
"""Should return False for invalid package.json."""
|
|
package_json = tmp_path / "package.json"
|
|
package_json.write_text("invalid json")
|
|
|
|
assert is_codeflash_dependency(tmp_path) is False
|
|
|
|
def test_handles_empty_dependencies(self, tmp_path: Path) -> None:
|
|
"""Should handle empty dependencies objects."""
|
|
package_json = tmp_path / "package.json"
|
|
package_json.write_text(json.dumps({"name": "test", "dependencies": {}, "devDependencies": {}}))
|
|
|
|
assert is_codeflash_dependency(tmp_path) is False
|
|
|
|
|
|
class TestGetJsRuntimeSetupSteps:
|
|
"""Tests for get_js_runtime_setup_steps function."""
|
|
|
|
def test_npm_setup(self) -> None:
|
|
"""Should generate correct setup steps for npm."""
|
|
result = get_js_runtime_setup_steps(JsPackageManager.NPM)
|
|
|
|
assert "Setup Node.js" in result
|
|
assert "actions/setup-node@v4" in result
|
|
assert "node-version: '22'" in result
|
|
assert "cache: 'npm'" in result
|
|
|
|
def test_yarn_setup(self) -> None:
|
|
"""Should generate correct setup steps for yarn."""
|
|
result = get_js_runtime_setup_steps(JsPackageManager.YARN)
|
|
|
|
assert "Setup Node.js" in result
|
|
assert "actions/setup-node@v4" in result
|
|
assert "cache: 'yarn'" in result
|
|
|
|
def test_pnpm_setup(self) -> None:
|
|
"""Should generate correct setup steps for pnpm."""
|
|
result = get_js_runtime_setup_steps(JsPackageManager.PNPM)
|
|
|
|
assert "Setup pnpm" in result
|
|
assert "pnpm/action-setup@v4" in result
|
|
assert "Setup Node.js" in result
|
|
assert "cache: 'pnpm'" in result
|
|
|
|
def test_bun_setup(self) -> None:
|
|
"""Should generate correct setup steps for bun."""
|
|
result = get_js_runtime_setup_steps(JsPackageManager.BUN)
|
|
|
|
assert "Setup Bun" in result
|
|
assert "oven-sh/setup-bun@v2" in result
|
|
assert "bun-version: latest" in result
|
|
|
|
def test_unknown_defaults_to_npm(self) -> None:
|
|
"""Should default to npm setup for unknown package manager."""
|
|
result = get_js_runtime_setup_steps(JsPackageManager.UNKNOWN)
|
|
|
|
assert "cache: 'npm'" in result
|
|
|
|
|
|
class TestGetJsDependencyInstallationCommands:
|
|
"""Tests for get_js_dependency_installation_commands function."""
|
|
|
|
def test_npm_install(self) -> None:
|
|
"""Should return npm ci for npm."""
|
|
assert get_js_dependency_installation_commands(JsPackageManager.NPM) == "npm ci"
|
|
|
|
def test_yarn_install(self) -> None:
|
|
"""Should return yarn install for yarn."""
|
|
assert get_js_dependency_installation_commands(JsPackageManager.YARN) == "yarn install"
|
|
|
|
def test_pnpm_install(self) -> None:
|
|
"""Should return pnpm install for pnpm."""
|
|
assert get_js_dependency_installation_commands(JsPackageManager.PNPM) == "pnpm install"
|
|
|
|
def test_bun_install(self) -> None:
|
|
"""Should return bun install for bun."""
|
|
assert get_js_dependency_installation_commands(JsPackageManager.BUN) == "bun install"
|
|
|
|
|
|
class TestGetJsCodeflashInstallStep:
|
|
"""Tests for get_js_codeflash_install_step function."""
|
|
|
|
def test_returns_empty_when_is_dependency(self) -> None:
|
|
"""Should return empty string when codeflash is a dependency."""
|
|
result = get_js_codeflash_install_step(JsPackageManager.NPM, is_dependency=True)
|
|
|
|
assert result == ""
|
|
|
|
def test_uv_pip_install_when_not_dependency(self) -> None:
|
|
"""Should generate uv pip install when not a dependency, regardless of package manager."""
|
|
for pkg_manager in (JsPackageManager.NPM, JsPackageManager.YARN, JsPackageManager.PNPM, JsPackageManager.BUN):
|
|
result = get_js_codeflash_install_step(pkg_manager, is_dependency=False)
|
|
|
|
assert "Install Codeflash" in result
|
|
assert "uv pip install codeflash" in result
|
|
|
|
|
|
class TestGetJsCodeflashRunCommand:
|
|
"""Tests for get_js_codeflash_run_command function."""
|
|
|
|
def test_npm_with_dependency(self) -> None:
|
|
"""Should use npx when codeflash is a dependency."""
|
|
result = get_js_codeflash_run_command(JsPackageManager.NPM, is_dependency=True)
|
|
|
|
assert result == "npx codeflash"
|
|
|
|
def test_npm_without_dependency(self) -> None:
|
|
"""Should use direct codeflash when globally installed."""
|
|
result = get_js_codeflash_run_command(JsPackageManager.NPM, is_dependency=False)
|
|
|
|
assert result == "codeflash"
|
|
|
|
def test_yarn_with_dependency(self) -> None:
|
|
"""Should use yarn codeflash when it's a dependency."""
|
|
result = get_js_codeflash_run_command(JsPackageManager.YARN, is_dependency=True)
|
|
|
|
assert result == "yarn codeflash"
|
|
|
|
def test_pnpm_with_dependency(self) -> None:
|
|
"""Should use pnpm exec when it's a dependency."""
|
|
result = get_js_codeflash_run_command(JsPackageManager.PNPM, is_dependency=True)
|
|
|
|
assert result == "pnpm exec codeflash"
|
|
|
|
def test_bun_with_dependency(self) -> None:
|
|
"""Should use bun run when it's a dependency."""
|
|
result = get_js_codeflash_run_command(JsPackageManager.BUN, is_dependency=True)
|
|
|
|
assert result == "bun run codeflash"
|
|
|
|
def test_all_global_installs_use_direct_command(self) -> None:
|
|
"""All package managers should use direct 'codeflash' when globally installed."""
|
|
for pm in [JsPackageManager.NPM, JsPackageManager.YARN, JsPackageManager.PNPM, JsPackageManager.BUN]:
|
|
result = get_js_codeflash_run_command(pm, is_dependency=False)
|
|
assert result == "codeflash", f"Failed for {pm}"
|
|
|
|
|
|
class TestWorkflowTemplateIntegration:
|
|
"""Integration tests for workflow template generation."""
|
|
|
|
def test_workflow_template_exists(self) -> None:
|
|
"""Verify the JS workflow template file exists."""
|
|
from importlib.resources import files
|
|
|
|
template_path = files("codeflash").joinpath("cli_cmds", "workflows", "codeflash-optimize-js.yaml")
|
|
content = template_path.read_text(encoding="utf-8")
|
|
|
|
# Check all placeholders exist
|
|
assert "{{ codeflash_module_path }}" in content
|
|
assert "{{ working_directory }}" in content
|
|
assert "{{ setup_runtime_steps }}" in content
|
|
assert "{{ install_dependencies_command }}" in content
|
|
assert "{{ install_codeflash_step }}" in content
|
|
assert "{{ codeflash_command }}" in content
|
|
|
|
def test_workflow_template_has_correct_structure(self) -> None:
|
|
"""Verify the JS workflow template has the expected YAML structure."""
|
|
from importlib.resources import files
|
|
|
|
template_path = files("codeflash").joinpath("cli_cmds", "workflows", "codeflash-optimize-js.yaml")
|
|
content = template_path.read_text(encoding="utf-8")
|
|
|
|
# Check key sections
|
|
assert "name: Codeflash" in content
|
|
assert "pull_request:" in content
|
|
assert "workflow_dispatch:" in content
|
|
assert "concurrency:" in content
|
|
assert "cancel-in-progress: true" in content
|
|
assert "jobs:" in content
|
|
assert "optimize:" in content
|
|
assert "github.actor != 'codeflash-ai[bot]'" in content
|
|
assert "CODEFLASH_API_KEY" in content
|
|
assert "actions/checkout@v4" in content
|
|
assert "fetch-depth: 0" in content
|