Files
codexchange-cli/tests/test_cli.py
7000pctAUTO 218c29d65c
Some checks failed
CI / test (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled
Add test suite (68 tests)
2026-01-30 19:00:44 +00:00

216 lines
7.0 KiB
Python

"""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]