Commit 941d2242 authored by Jan Reimes's avatar Jan Reimes
Browse files

test(cli): enhance tests with type hints and improve readability

* Added type hints to monkeypatch parameters in CLI tests.
* Refactored mock functions to include type annotations for better clarity.
* Updated test functions to ensure consistency in parameter types.
* Improved organization of imports in test files for better structure.
parent 93698625
Loading
Loading
Loading
Loading
+58 −26
Original line number Diff line number Diff line
@@ -5,25 +5,34 @@ from __future__ import annotations
from pathlib import Path
from typing import Never

import pytest
from conftest import MockProvider
from typer.testing import CliRunner

from pdf_remote_converter.cli.app import app
from pdf_remote_converter.config import ProviderSettings
from pdf_remote_converter.exceptions import AuthenticationError
from pdf_remote_converter.providers.base import ProviderBackend
from pdf_remote_converter.providers.models import ConversionResult

runner = CliRunner()


def test_cli_convert_success(tmp_path: Path, monkeypatch) -> None:
def test_cli_convert_success(tmp_path: Path, monkeypatch: pytest.Monkeypatch) -> None:
    """Test successful CLI conversion with configured provider."""
    input_file = tmp_path / "sample.docx"
    input_file.write_text("test content", encoding="utf-8")
    output_file = tmp_path / "output.pdf"

    def mock_get_configured(settings):
    def mock_get_configured(settings: ProviderSettings) -> list[ProviderBackend]:
        return [MockProvider()]

    def mock_convert_with_failover(input_path, output_path, providers, force=False):
    def mock_convert_with_failover(
        input_path: Path,
        output_path: Path,
        providers: list[ProviderBackend],
        force: bool = False,
    ) -> ConversionResult:
        output_path.write_bytes(b"%PDF-1.4")
        return ConversionResult(
            output_path=output_path,
@@ -50,7 +59,7 @@ def test_cli_convert_success(tmp_path: Path, monkeypatch) -> None:
    assert output_file.exists()


def test_cli_no_provider_configured(tmp_path: Path, monkeypatch) -> None:
def test_cli_no_provider_configured(tmp_path: Path, monkeypatch: pytest.Monkeypatch) -> None:
    """Test CLI error when no providers are configured."""
    input_file = tmp_path / "sample.docx"
    input_file.write_text("test", encoding="utf-8")
@@ -70,18 +79,21 @@ def test_cli_no_provider_configured(tmp_path: Path, monkeypatch) -> None:
    assert "Error" in output


def test_cli_provider_auth_error(tmp_path: Path, monkeypatch) -> None:
def test_cli_provider_auth_error(tmp_path: Path, monkeypatch: pytest.Monkeypatch) -> None:
    """Test CLI error handling for authentication failures."""
    input_file = tmp_path / "sample.docx"
    input_file.write_text("test", encoding="utf-8")
    output_file = tmp_path / "output.pdf"

    def mock_get_configured(settings):
    def mock_get_configured(settings: ProviderSettings) -> list[ProviderBackend]:
        return [MockProvider()]

    def mock_convert_fail(input_path, output_path, providers, force=False) -> Never:
        from pdf_remote_converter.exceptions import AuthenticationError

    def mock_convert_fail(
        input_path: Path,
        output_path: Path,
        providers: list[ProviderBackend],
        force: bool = False,
    ) -> Never:
        raise AuthenticationError("Mock auth failed")

    monkeypatch.setenv("CLOUDCONVERT_API_KEY", "bad-key")
@@ -102,16 +114,21 @@ def test_cli_provider_auth_error(tmp_path: Path, monkeypatch) -> None:
    assert "Error" in output


def test_cli_cache_hit(tmp_path: Path, monkeypatch) -> None:
def test_cli_cache_hit(tmp_path: Path, monkeypatch: pytest.Monkeypatch) -> None:
    """Test CLI reports cache hit when applicable."""
    input_file = tmp_path / "sample.docx"
    input_file.write_text("cached content", encoding="utf-8")
    output_file = tmp_path / "output.pdf"

    def mock_get_configured(settings):
    def mock_get_configured(settings: ProviderSettings) -> list[ProviderBackend]:
        return [MockProvider()]

    def mock_convert_cached(input_path, output_path, providers, force=False):
    def mock_convert_cached(
        input_path: Path,
        output_path: Path,
        providers: list[ProviderBackend],
        force: bool = False,
    ) -> ConversionResult:
        output_path.write_bytes(b"%PDF-cached")
        return ConversionResult(
            output_path=output_path,
@@ -136,7 +153,7 @@ def test_cli_cache_hit(tmp_path: Path, monkeypatch) -> None:
    assert "from cache" in result.stdout


def test_cli_verbose_logging(tmp_path: Path, monkeypatch) -> None:
def test_cli_verbose_logging(tmp_path: Path, monkeypatch: pytest.Monkeypatch) -> None:
    """Test CLI --verbose flag enables debug logging."""
    input_file = tmp_path / "sample.docx"
    input_file.write_text("test", encoding="utf-8")
@@ -144,14 +161,19 @@ def test_cli_verbose_logging(tmp_path: Path, monkeypatch) -> None:

    verbose_called = False

    def mock_setup_logging(verbose) -> None:
    def mock_setup_logging(verbose: bool) -> None:
        nonlocal verbose_called
        verbose_called = verbose

    def mock_get_configured(settings):
    def mock_get_configured(settings: ProviderSettings) -> list[ProviderBackend]:
        return [MockProvider()]

    def mock_convert_with_failover(input_path, output_path, providers, force=False):
    def mock_convert_with_failover(
        input_path: Path,
        output_path: Path,
        providers: list[ProviderBackend],
        force: bool = False,
    ) -> ConversionResult:
        output_path.write_bytes(b"%PDF")
        return ConversionResult(
            output_path=output_path,
@@ -183,7 +205,7 @@ def test_cli_verbose_logging(tmp_path: Path, monkeypatch) -> None:
    assert verbose_called is True


def test_cli_force_flag(tmp_path: Path, monkeypatch) -> None:
def test_cli_force_flag(tmp_path: Path, monkeypatch: pytest.Monkeypatch) -> None:
    """Test CLI --force flag bypasses cache."""
    input_file = tmp_path / "sample.docx"
    input_file.write_text("test", encoding="utf-8")
@@ -191,10 +213,15 @@ def test_cli_force_flag(tmp_path: Path, monkeypatch) -> None:

    force_flag_received = False

    def mock_get_configured(settings):
    def mock_get_configured(settings: ProviderSettings) -> list[ProviderBackend]:
        return [MockProvider()]

    def mock_convert_with_failover(input_path, output_path, providers, force=False):
    def mock_convert_with_failover(
        input_path: Path,
        output_path: Path,
        providers: list[ProviderBackend],
        force: bool = False,
    ) -> ConversionResult:
        nonlocal force_flag_received
        force_flag_received = force
        output_path.write_bytes(b"%PDF")
@@ -224,23 +251,28 @@ def test_cli_force_flag(tmp_path: Path, monkeypatch) -> None:
    assert force_flag_received is True


def test_cli_explicit_provider(tmp_path: Path, monkeypatch) -> None:
def test_cli_explicit_provider(tmp_path: Path, monkeypatch: pytest.Monkeypatch) -> None:
    """Test CLI --provider flag selects specific provider."""
    input_file = tmp_path / "sample.docx"
    input_file.write_text("test", encoding="utf-8")
    output_file = tmp_path / "output.pdf"

    selected_provider = None
    selected_provider: str | None = None

    def mock_get_configured(settings):
    def mock_get_configured(settings: ProviderSettings) -> list[ProviderBackend]:
        return [MockProvider(name="cloudconvert"), MockProvider(name="adobe")]

    def mock_select_provider(preferred, settings):
    def mock_select_provider(preferred: str | None, settings: ProviderSettings) -> ProviderBackend:
        nonlocal selected_provider
        selected_provider = preferred
        return MockProvider(name=preferred)

    def mock_convert_with_failover(input_path, output_path, providers, force=False):
        return MockProvider(name=preferred)  # type: ignore[arg-type]

    def mock_convert_with_failover(
        input_path: Path,
        output_path: Path,
        providers: list[ProviderBackend],
        force: bool = False,
    ) -> ConversionResult:
        output_path.write_bytes(b"%PDF")
        return ConversionResult(
            output_path=output_path,
+2 −2
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ def test_config_with_zamzar_key() -> None:
    assert settings.get_api_key("zamzar") == "zm-key"


def test_config_fallback_api_key(monkeypatch) -> None:
def test_config_fallback_api_key(monkeypatch: pytest.Monkeypatch) -> None:
    """Test fallback to generic API key when provider-specific not set."""
    monkeypatch.setenv("PDF_REMOTE_CONVERTER_API_KEY", "generic-key")
    settings = ProviderSettings()
@@ -66,7 +66,7 @@ def test_config_cache_dir_default() -> None:
    assert "pdf-remote-converter" in str(settings.cache_dir)


def test_config_cache_dir_custom(monkeypatch) -> None:
def test_config_cache_dir_custom(monkeypatch: pytest.Monkeypatch) -> None:
    """Test custom cache directory path."""
    monkeypatch.setenv("PDF_REMOTE_CONVERTER_CACHE_DIR", "/tmp/test-cache")  # noqa: S108
    settings = ProviderSettings()
+4 −2
Original line number Diff line number Diff line
@@ -4,10 +4,12 @@ from __future__ import annotations

import logging

import pytest

from pdf_remote_converter.logging import setup_logging


def test_setup_logging_info_level(caplog) -> None:
def test_setup_logging_info_level(caplog: pytest.LogCaptureFixture) -> None:
    """Test logging setup with INFO level."""
    setup_logging(verbose=False)

@@ -19,7 +21,7 @@ def test_setup_logging_info_level(caplog) -> None:
    assert len(caplog.records) > 0


def test_setup_logging_debug_level(caplog) -> None:
def test_setup_logging_debug_level(caplog: pytest.LogCaptureFixture) -> None:
    """Test logging setup with DEBUG level."""
    setup_logging(verbose=True)

+12 −14
Original line number Diff line number Diff line
@@ -2,9 +2,6 @@

from __future__ import annotations


def test_package_exports() -> None:
    """Test that main classes are exported from package root."""
from pdf_remote_converter import (
    AdobeProvider,
    CloudConvertProvider,
@@ -15,6 +12,9 @@ def test_package_exports() -> None:
    get_provider,
)


def test_package_exports() -> None:
    """Test that main classes are exported from package root."""
    assert AdobeProvider is not None
    assert CloudConvertProvider is not None
    assert ZamzarProvider is not None
@@ -26,9 +26,7 @@ def test_package_exports() -> None:

def test_version_works() -> None:
    """Test __version__ is accessible and is a string."""
    import pdf_remote_converter

    # Should either be actual version or 0.0.0 (dev fallback)
    assert isinstance(pdf_remote_converter.__version__, str)
    assert isinstance(__version__, str)
    # Version should look reasonable
    assert len(pdf_remote_converter.__version__) > 0
    assert len(__version__) > 0