- test_media_utils.py: 29 tests for check_media_files, get_media_file_paths, has_all_images, count_video_files, has_video_files, constants - test_nfo_factory.py: 11 tests for NFOServiceFactory.create, create_optional, get_nfo_factory singleton, create_nfo_service convenience - test_series_manager_service.py: 15 tests for init, from_settings, process_nfo_for_series, scan_and_process_nfo, close - test_templates_utils.py: 4 tests for TEMPLATES_DIR path resolution - test_error_controller.py: 7 tests for 404/500 handlers (API vs HTML)
190 lines
7.0 KiB
Python
190 lines
7.0 KiB
Python
"""Unit tests for NFO service factory module.
|
|
|
|
Tests factory instantiation, configuration precedence, singleton pattern,
|
|
and convenience functions for creating NFOService instances.
|
|
"""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from src.core.services.nfo_factory import (
|
|
NFOServiceFactory,
|
|
create_nfo_service,
|
|
get_nfo_factory,
|
|
)
|
|
|
|
|
|
class TestNFOServiceFactoryCreate:
|
|
"""Tests for NFOServiceFactory.create method."""
|
|
|
|
@patch("src.core.services.nfo_factory.NFOService")
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_create_with_explicit_api_key(self, mock_settings, mock_nfo_cls):
|
|
"""Explicit API key takes priority over settings."""
|
|
mock_settings.tmdb_api_key = "settings_key"
|
|
mock_settings.anime_directory = "/anime"
|
|
mock_settings.nfo_image_size = "original"
|
|
mock_settings.nfo_auto_create = False
|
|
|
|
factory = NFOServiceFactory()
|
|
factory.create(tmdb_api_key="explicit_key")
|
|
mock_nfo_cls.assert_called_once_with(
|
|
tmdb_api_key="explicit_key",
|
|
anime_directory="/anime",
|
|
image_size="original",
|
|
auto_create=False,
|
|
)
|
|
|
|
@patch("src.core.services.nfo_factory.NFOService")
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_create_falls_back_to_settings(self, mock_settings, mock_nfo_cls):
|
|
"""Falls back to settings when no explicit key provided."""
|
|
mock_settings.tmdb_api_key = "settings_key"
|
|
mock_settings.anime_directory = "/anime"
|
|
mock_settings.nfo_image_size = "w500"
|
|
mock_settings.nfo_auto_create = True
|
|
|
|
factory = NFOServiceFactory()
|
|
factory.create()
|
|
mock_nfo_cls.assert_called_once_with(
|
|
tmdb_api_key="settings_key",
|
|
anime_directory="/anime",
|
|
image_size="w500",
|
|
auto_create=True,
|
|
)
|
|
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_create_raises_without_api_key(self, mock_settings):
|
|
"""Raises ValueError when no API key available from any source."""
|
|
mock_settings.tmdb_api_key = None
|
|
factory = NFOServiceFactory()
|
|
factory._get_api_key_from_config = MagicMock(return_value=None)
|
|
with pytest.raises(ValueError, match="TMDB API key not configured"):
|
|
factory.create()
|
|
|
|
@patch("src.core.services.nfo_factory.NFOService")
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_create_with_all_custom_params(self, mock_settings, mock_nfo_cls):
|
|
"""All parameters can be overridden."""
|
|
mock_settings.tmdb_api_key = "default"
|
|
mock_settings.anime_directory = "/default"
|
|
mock_settings.nfo_image_size = "original"
|
|
mock_settings.nfo_auto_create = False
|
|
|
|
factory = NFOServiceFactory()
|
|
factory.create(
|
|
tmdb_api_key="custom",
|
|
anime_directory="/custom",
|
|
image_size="w300",
|
|
auto_create=True,
|
|
)
|
|
mock_nfo_cls.assert_called_once_with(
|
|
tmdb_api_key="custom",
|
|
anime_directory="/custom",
|
|
image_size="w300",
|
|
auto_create=True,
|
|
)
|
|
|
|
@patch("src.core.services.nfo_factory.NFOService")
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_create_uses_config_json_fallback(self, mock_settings, mock_nfo_cls):
|
|
"""Falls back to config.json when settings has no key."""
|
|
mock_settings.tmdb_api_key = None
|
|
mock_settings.anime_directory = "/anime"
|
|
mock_settings.nfo_image_size = "original"
|
|
mock_settings.nfo_auto_create = False
|
|
|
|
factory = NFOServiceFactory()
|
|
factory._get_api_key_from_config = MagicMock(return_value="config_key")
|
|
factory.create()
|
|
mock_nfo_cls.assert_called_once()
|
|
call_kwargs = mock_nfo_cls.call_args[1]
|
|
assert call_kwargs["tmdb_api_key"] == "config_key"
|
|
|
|
|
|
class TestNFOServiceFactoryCreateOptional:
|
|
"""Tests for NFOServiceFactory.create_optional method."""
|
|
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_returns_none_without_api_key(self, mock_settings):
|
|
"""Returns None instead of raising when no API key."""
|
|
mock_settings.tmdb_api_key = None
|
|
factory = NFOServiceFactory()
|
|
factory._get_api_key_from_config = MagicMock(return_value=None)
|
|
result = factory.create_optional()
|
|
assert result is None
|
|
|
|
@patch("src.core.services.nfo_factory.NFOService")
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_returns_service_when_configured(self, mock_settings, mock_nfo_cls):
|
|
"""Returns NFOService when configuration is available."""
|
|
mock_settings.tmdb_api_key = "key123"
|
|
mock_settings.anime_directory = "/anime"
|
|
mock_settings.nfo_image_size = "original"
|
|
mock_settings.nfo_auto_create = False
|
|
|
|
factory = NFOServiceFactory()
|
|
result = factory.create_optional()
|
|
assert result is not None
|
|
|
|
|
|
class TestGetNfoFactory:
|
|
"""Tests for get_nfo_factory singleton function."""
|
|
|
|
def test_returns_factory_instance(self):
|
|
"""Returns an NFOServiceFactory instance."""
|
|
import src.core.services.nfo_factory as mod
|
|
old = mod._factory_instance
|
|
try:
|
|
mod._factory_instance = None
|
|
factory = get_nfo_factory()
|
|
assert isinstance(factory, NFOServiceFactory)
|
|
finally:
|
|
mod._factory_instance = old
|
|
|
|
def test_returns_same_instance(self):
|
|
"""Repeated calls return the same singleton."""
|
|
import src.core.services.nfo_factory as mod
|
|
old = mod._factory_instance
|
|
try:
|
|
mod._factory_instance = None
|
|
f1 = get_nfo_factory()
|
|
f2 = get_nfo_factory()
|
|
assert f1 is f2
|
|
finally:
|
|
mod._factory_instance = old
|
|
|
|
|
|
class TestCreateNfoService:
|
|
"""Tests for create_nfo_service convenience function."""
|
|
|
|
@patch("src.core.services.nfo_factory.NFOService")
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_convenience_function_creates_service(
|
|
self, mock_settings, mock_nfo_cls
|
|
):
|
|
"""Convenience function delegates to factory.create()."""
|
|
mock_settings.tmdb_api_key = "key"
|
|
mock_settings.anime_directory = "/anime"
|
|
mock_settings.nfo_image_size = "original"
|
|
mock_settings.nfo_auto_create = False
|
|
|
|
result = create_nfo_service()
|
|
mock_nfo_cls.assert_called_once()
|
|
|
|
@patch("src.core.services.nfo_factory.settings")
|
|
def test_convenience_function_raises_without_key(self, mock_settings):
|
|
"""Convenience function raises ValueError without key."""
|
|
mock_settings.tmdb_api_key = None
|
|
import src.core.services.nfo_factory as mod
|
|
old = mod._factory_instance
|
|
try:
|
|
mod._factory_instance = None
|
|
factory = get_nfo_factory()
|
|
factory._get_api_key_from_config = MagicMock(return_value=None)
|
|
with pytest.raises(ValueError):
|
|
factory.create()
|
|
finally:
|
|
mod._factory_instance = old
|