Add test suite (68 tests)
Some checks failed
CI / test (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled

This commit is contained in:
2026-01-30 19:00:44 +00:00
parent 7837e1ab3a
commit 218c29d65c

215
tests/test_cli.py Normal file
View File

@@ -0,0 +1,215 @@
"""Tests for CLI commands module."""
import tempfile
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
from typer.testing import CliRunner
from codexchange.main import app
from codexchange.cli.commands import (
show_supported_languages,
convert_cmd,
batch_convert_cmd,
list_models_cmd,
list_languages_cmd,
)
runner = CliRunner()
class TestListLanguages:
"""Tests for list-languages command."""
def test_list_languages_cmd(self):
"""Test list-languages command executes without error."""
result = runner.invoke(app, ["list-languages"])
assert result.exit_code == 0
assert "Supported Languages" in result.output
def test_show_supported_languages(self):
"""Test show_supported_languages function."""
result = runner.invoke(app, ["list-languages"])
assert "JavaScript" in result.output
assert "TypeScript" in result.output
assert "Python" in result.output
assert "Java" in result.output
class TestListModels:
"""Tests for list-models command."""
@patch("codexchange.cli.commands.connect")
@patch("codexchange.cli.commands.list_models")
def test_list_models_success(self, mock_list, mock_connect):
"""Test list-models command with successful connection."""
from codexchange.models import ModelInfo
mock_list.return_value = [
ModelInfo(name="codellama", size="4GB", modified_at="2024-01-01"),
ModelInfo(name="llama2", size="7GB", modified_at="2024-01-02"),
]
result = runner.invoke(app, ["list-models"])
assert result.exit_code == 0
@patch("codexchange.cli.commands.connect")
def test_list_models_connection_error(self, mock_connect):
"""Test list-models command with connection error."""
mock_connect.side_effect = Exception("Connection failed")
result = runner.invoke(app, ["list-models"])
assert result.exit_code == 1
assert "Error" in result.output
class TestConvert:
"""Tests for convert command."""
@patch("codexchange.cli.commands.connect")
def test_convert_file_success(self, mock_connect, sample_python_code):
"""Test converting a file successfully."""
mock_ollama = MagicMock()
mock_ollama.generate.return_value = "console.log('Hello');"
mock_connect.return_value = mock_ollama
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write(sample_python_code)
input_file = f.name
try:
result = runner.invoke(app, [
"convert",
input_file,
"--from", "python",
"--to", "javascript",
"--model", "codellama"
])
assert result.exit_code == 0
assert "Hello" in result.output or "conversion" in result.output.lower()
finally:
Path(input_file).unlink()
def test_convert_file_not_found(self):
"""Test convert with non-existent file."""
result = runner.invoke(app, [
"convert",
"/nonexistent/file.py",
"--from", "python",
"--to", "javascript"
])
assert result.exit_code == 1
assert "not found" in result.output.lower()
def test_convert_invalid_source_language(self):
"""Test convert with invalid source language."""
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write("print('hello')")
input_file = f.name
try:
result = runner.invoke(app, [
"convert",
input_file,
"--from", "invalid-lang",
"--to", "javascript"
])
assert result.exit_code == 1
assert "Unsupported" in result.output
finally:
Path(input_file).unlink()
def test_convert_invalid_target_language(self):
"""Test convert with invalid target language."""
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write("print('hello')")
input_file = f.name
try:
result = runner.invoke(app, [
"convert",
input_file,
"--from", "python",
"--to", "invalid-lang"
])
assert result.exit_code == 1
assert "Unsupported" in result.output
finally:
Path(input_file).unlink()
class TestBatchConvert:
"""Tests for batch-convert command."""
@patch("codexchange.cli.commands.connect")
def test_batch_convert_directory(self, mock_connect, sample_python_code):
"""Test batch converting a directory."""
mock_ollama = MagicMock()
mock_ollama.generate.return_value = "console.log('Hello');"
mock_connect.return_value = mock_ollama
with tempfile.TemporaryDirectory() as tmpdir:
(Path(tmpdir) / "file1.py").write_text(sample_python_code)
(Path(tmpdir) / "file2.py").write_text(sample_python_code)
result = runner.invoke(app, [
"batch-convert",
tmpdir,
"--from", "python",
"--to", "javascript",
"--concurrency", "1"
])
assert result.exit_code == 0
assert "file1.py" in result.output or "Successfully" in result.output
def test_batch_convert_directory_not_found(self):
"""Test batch convert with non-existent directory."""
result = runner.invoke(app, [
"batch-convert",
"/nonexistent/dir",
"--from", "python",
"--to", "javascript"
])
assert result.exit_code == 1
assert "not found" in result.output.lower()
def test_batch_convert_no_files_found(self):
"""Test batch convert with directory having no matching files."""
with tempfile.TemporaryDirectory() as tmpdir:
(Path(tmpdir) / "readme.txt").write_text("README")
result = runner.invoke(app, [
"batch-convert",
tmpdir,
"--from", "python",
"--to", "javascript"
])
assert result.exit_code == 0
assert "No" in result.output or "found" in result.output.lower()
class TestMainApp:
"""Tests for main app entry point."""
def test_app_help(self):
"""Test app help command."""
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "CodeXchange" in result.output
assert "convert" in result.output
assert "batch-convert" in result.output
def test_app_no_args(self):
"""Test app with no arguments shows help or error."""
result = runner.invoke(app)
assert result.exit_code in [0, 2]