276 lines
8.5 KiB
Python
276 lines
8.5 KiB
Python
"""Tests for CLI commands."""
|
|
import json
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
from click.testing import CliRunner
|
|
|
|
from i18n_key_sync.cli import main
|
|
|
|
|
|
class TestCLIExtract:
|
|
"""Tests for extract command."""
|
|
|
|
def test_extract_from_python_file(self, sample_python_code):
|
|
"""Test extracting keys from Python file."""
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
|
|
f.write(sample_python_code)
|
|
f.flush()
|
|
f_path = f.name
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["extract", f_path])
|
|
|
|
assert result.exit_code == 0
|
|
assert "hello" in result.output or "hello" in result.output.lower()
|
|
assert "goodbye" in result.output or "goodbye" in result.output.lower()
|
|
|
|
Path(f_path).unlink()
|
|
|
|
def test_extract_json_output(self, sample_python_code):
|
|
"""Test extract with JSON output format."""
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
|
|
f.write('_("test_key")')
|
|
f.flush()
|
|
f_path = f.name
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--output-format", "json", "extract", f_path])
|
|
|
|
assert result.exit_code == 0
|
|
data = json.loads(result.output)
|
|
assert "test_key" in data
|
|
|
|
Path(f_path).unlink()
|
|
|
|
def test_extract_with_patterns(self, sample_python_code):
|
|
"""Test extract with custom patterns."""
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
|
|
f.write('t("custom_key")')
|
|
f.flush()
|
|
f_path = f.name
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["extract", f_path, "--patterns", "t"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "custom_key" in result.output
|
|
|
|
Path(f_path).unlink()
|
|
|
|
|
|
class TestCLIValidate:
|
|
"""Tests for validate command."""
|
|
|
|
def test_validate_valid_keys(self, temp_project_dir, temp_locale_dir):
|
|
"""Test validation with all keys present."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"validate",
|
|
str(temp_project_dir / "src"),
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
assert "valid" in result.output.lower() or "matching" in result.output.lower()
|
|
|
|
def test_validate_missing_keys(self, tmp_path, temp_locale_dir):
|
|
"""Test validation with missing keys."""
|
|
src_dir = tmp_path / "src"
|
|
src_dir.mkdir()
|
|
|
|
code_file = src_dir / "main.py"
|
|
code_file.write_text('_("nonexistent_key")')
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"validate",
|
|
str(src_dir),
|
|
])
|
|
|
|
assert result.exit_code in [0, 1]
|
|
assert "missing" in result.output.lower() or "nonexistent_key" in result.output
|
|
|
|
def test_validate_strict_mode(self, tmp_path, temp_locale_dir):
|
|
"""Test validation in strict mode."""
|
|
src_dir = tmp_path / "src"
|
|
src_dir.mkdir()
|
|
|
|
code_file = src_dir / "main.py"
|
|
code_file.write_text('_("missing_key")\n_("unused_in_locale")')
|
|
|
|
locale_file = temp_locale_dir / "en.json"
|
|
locale_data = json.loads(locale_file.read_text())
|
|
locale_data["unused_in_locale"] = "Unused"
|
|
locale_file.write_text(json.dumps(locale_data, indent=2))
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"validate",
|
|
str(src_dir),
|
|
"--strict",
|
|
])
|
|
|
|
assert result.exit_code == 3
|
|
|
|
def test_validate_json_output(self, temp_project_dir, temp_locale_dir):
|
|
"""Test validate with JSON output."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--output-format", "json",
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"validate",
|
|
str(temp_project_dir / "src"),
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
data = json.loads(result.output)
|
|
assert "missing_keys" in data
|
|
assert "unused_keys" in data
|
|
assert "matching_keys" in data
|
|
|
|
|
|
class TestCLISync:
|
|
"""Tests for sync command."""
|
|
|
|
def test_sync_dry_run(self, tmp_path, temp_locale_dir):
|
|
"""Test sync in dry run mode."""
|
|
src_dir = tmp_path / "src"
|
|
src_dir.mkdir()
|
|
|
|
code_file = src_dir / "main.py"
|
|
code_file.write_text('_("new_key")')
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"sync",
|
|
str(src_dir),
|
|
"--dry-run",
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
assert "DRY RUN" in result.output or "dry" in result.output.lower()
|
|
|
|
locale_file = temp_locale_dir / "en.json"
|
|
locale_data = json.loads(locale_file.read_text())
|
|
assert "new_key" not in locale_data
|
|
|
|
def test_sync_actual(self, tmp_path, temp_locale_dir):
|
|
"""Test actual sync modifies files."""
|
|
src_dir = tmp_path / "src"
|
|
src_dir.mkdir()
|
|
|
|
code_file = src_dir / "main.py"
|
|
code_file.write_text('_("new_sync_key")')
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"sync",
|
|
str(src_dir),
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
locale_file = temp_locale_dir / "en.json"
|
|
locale_data = json.loads(locale_file.read_text())
|
|
assert "new_sync_key" in locale_data
|
|
|
|
def test_sync_custom_placeholder(self, tmp_path, temp_locale_dir):
|
|
"""Test sync with custom placeholder value."""
|
|
src_dir = tmp_path / "src"
|
|
src_dir.mkdir()
|
|
|
|
code_file = src_dir / "main.py"
|
|
code_file.write_text('_("placeholder_key")')
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"sync",
|
|
str(src_dir),
|
|
"--value", "TRANSLATE_ME",
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
locale_file = temp_locale_dir / "en.json"
|
|
locale_data = json.loads(locale_file.read_text())
|
|
assert locale_data["placeholder_key"] == "TRANSLATE_ME"
|
|
|
|
|
|
class TestCLIReport:
|
|
"""Tests for report command."""
|
|
|
|
def test_report_generates_output(self, temp_project_dir, temp_locale_dir):
|
|
"""Test report command generates output."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"report",
|
|
str(temp_project_dir / "src"),
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
assert len(result.output) > 0
|
|
|
|
def test_report_json_format(self, temp_project_dir, temp_locale_dir):
|
|
"""Test report with JSON format."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"report",
|
|
str(temp_project_dir / "src"),
|
|
"--format", "json",
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
data = json.loads(result.output)
|
|
assert "summary" in data
|
|
|
|
def test_report_markdown_format(self, temp_project_dir, temp_locale_dir):
|
|
"""Test report with markdown format."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"report",
|
|
str(temp_project_dir / "src"),
|
|
"--format", "markdown",
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
assert "# i18n Key Report" in result.output
|
|
|
|
def test_report_to_file(self, temp_project_dir, temp_locale_dir, tmp_path):
|
|
"""Test report output to file."""
|
|
output_file = tmp_path / "report.md"
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [
|
|
"--locale-dir", str(temp_locale_dir),
|
|
"report",
|
|
str(temp_project_dir / "src"),
|
|
"--output", str(output_file),
|
|
"--format", "markdown",
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
assert output_file.exists()
|
|
content = output_file.read_text()
|
|
assert "# i18n Key Report" in content
|
|
|
|
|
|
class TestCLIVersion:
|
|
"""Tests for version flag."""
|
|
|
|
def test_version_flag(self):
|
|
"""Test --version flag displays version."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--version"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "i18n-key-sync" in result.output
|