""" Unit tests for Serie class to verify key validation and identifier usage. """ import json import os import tempfile import pytest from src.core.entities.series import Serie class TestSerieValidation: """Test Serie class validation logic.""" def test_serie_creation_with_valid_key(self): """Test creating Serie with valid key.""" serie = Serie( key="attack-on-titan", name="Attack on Titan", site="https://aniworld.to/anime/stream/attack-on-titan", folder="Attack on Titan (2013)", episodeDict={1: [1, 2, 3], 2: [1, 2]} ) assert serie.key == "attack-on-titan" assert serie.name == "Attack on Titan" assert serie.site == "https://aniworld.to/anime/stream/attack-on-titan" assert serie.folder == "Attack on Titan (2013)" assert serie.episodeDict == {1: [1, 2, 3], 2: [1, 2]} def test_serie_creation_with_empty_key_raises_error(self): """Test that creating Serie with empty key raises ValueError.""" with pytest.raises(ValueError, match="key cannot be None or empty"): Serie( key="", name="Test Series", site="https://example.com", folder="Test Folder", episodeDict={1: [1]} ) def test_serie_creation_with_whitespace_key_raises_error(self): """Test that creating Serie with whitespace-only key raises error.""" with pytest.raises(ValueError, match="key cannot be None or empty"): Serie( key=" ", name="Test Series", site="https://example.com", folder="Test Folder", episodeDict={1: [1]} ) def test_serie_key_is_stripped(self): """Test that Serie key is stripped of whitespace.""" serie = Serie( key=" attack-on-titan ", name="Attack on Titan", site="https://example.com", folder="Attack on Titan (2013)", episodeDict={1: [1]} ) assert serie.key == "attack-on-titan" def test_serie_key_setter_with_valid_value(self): """Test setting key property with valid value.""" serie = Serie( key="initial-key", name="Test", site="https://example.com", folder="Test Folder", episodeDict={1: [1]} ) serie.key = "new-key" assert serie.key == "new-key" def test_serie_key_setter_with_empty_value_raises_error(self): """Test that setting key to empty string raises ValueError.""" serie = Serie( key="initial-key", name="Test", site="https://example.com", folder="Test Folder", episodeDict={1: [1]} ) with pytest.raises(ValueError, match="key cannot be None or empty"): serie.key = "" def test_serie_key_setter_with_whitespace_raises_error(self): """Test that setting key to whitespace raises ValueError.""" serie = Serie( key="initial-key", name="Test", site="https://example.com", folder="Test Folder", episodeDict={1: [1]} ) with pytest.raises(ValueError, match="key cannot be None or empty"): serie.key = " " def test_serie_key_setter_strips_whitespace(self): """Test that key setter strips whitespace.""" serie = Serie( key="initial-key", name="Test", site="https://example.com", folder="Test Folder", episodeDict={1: [1]} ) serie.key = " new-key " assert serie.key == "new-key" class TestSerieProperties: """Test Serie class properties and methods.""" def test_serie_str_representation(self): """Test string representation of Serie.""" serie = Serie( key="test-key", name="Test Series", site="https://example.com", folder="Test Folder", episodeDict={1: [1, 2]} ) str_repr = str(serie) assert "key='test-key'" in str_repr assert "name='Test Series'" in str_repr assert "folder='Test Folder'" in str_repr def test_serie_to_dict(self): """Test conversion of Serie to dictionary.""" serie = Serie( key="test-key", name="Test Series", site="https://example.com", folder="Test Folder", episodeDict={1: [1, 2], 2: [1, 2, 3]} ) data = serie.to_dict() assert data["key"] == "test-key" assert data["name"] == "Test Series" assert data["site"] == "https://example.com" assert data["folder"] == "Test Folder" assert "1" in data["episodeDict"] assert data["episodeDict"]["1"] == [1, 2] def test_serie_from_dict(self): """Test creating Serie from dictionary.""" data = { "key": "test-key", "name": "Test Series", "site": "https://example.com", "folder": "Test Folder", "episodeDict": {"1": [1, 2], "2": [1, 2, 3]} } serie = Serie.from_dict(data) assert serie.key == "test-key" assert serie.name == "Test Series" assert serie.folder == "Test Folder" assert serie.episodeDict == {1: [1, 2], 2: [1, 2, 3]} def test_serie_save_and_load_from_file(self): """Test saving and loading Serie from file.""" import warnings serie = Serie( key="test-key", name="Test Series", site="https://example.com", folder="Test Folder", episodeDict={1: [1, 2, 3]} ) # Create temporary file with tempfile.NamedTemporaryFile( mode='w', delete=False, suffix='.json' ) as f: temp_filename = f.name try: # Suppress deprecation warnings for this test with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) # Save to file serie.save_to_file(temp_filename) # Load from file loaded_serie = Serie.load_from_file(temp_filename) # Verify all properties match assert loaded_serie.key == serie.key assert loaded_serie.name == serie.name assert loaded_serie.site == serie.site assert loaded_serie.folder == serie.folder assert loaded_serie.episodeDict == serie.episodeDict finally: # Cleanup if os.path.exists(temp_filename): os.remove(temp_filename) def test_serie_folder_is_mutable(self): """Test that folder property can be changed (it's metadata only).""" serie = Serie( key="test-key", name="Test", site="https://example.com", folder="Old Folder", episodeDict={1: [1]} ) serie.folder = "New Folder" assert serie.folder == "New Folder" # Key should remain unchanged assert serie.key == "test-key" class TestSerieDocumentation: """Test that Serie class has proper documentation.""" def test_serie_class_has_docstring(self): """Test that Serie class has a docstring.""" assert Serie.__doc__ is not None assert "unique identifier" in Serie.__doc__.lower() def test_key_property_has_docstring(self): """Test that key property has descriptive docstring.""" assert Serie.key.fget.__doc__ is not None assert "unique" in Serie.key.fget.__doc__.lower() assert "identifier" in Serie.key.fget.__doc__.lower() def test_folder_property_has_docstring(self): """Test that folder property documents it's metadata only.""" assert Serie.folder.fget.__doc__ is not None assert "metadata" in Serie.folder.fget.__doc__.lower() assert "not used for lookups" in Serie.folder.fget.__doc__.lower() class TestSerieDeprecationWarnings: """Test deprecation warnings for file-based methods.""" def test_save_to_file_raises_deprecation_warning(self): """Test save_to_file() raises deprecation warning.""" import warnings serie = Serie( key="test-key", name="Test Series", site="https://example.com", folder="Test Folder", episodeDict={1: [1, 2, 3]} ) with tempfile.NamedTemporaryFile( mode='w', suffix='.json', delete=False ) as temp_file: temp_filename = temp_file.name try: with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") serie.save_to_file(temp_filename) # Check deprecation warning was raised assert len(w) == 1 assert issubclass(w[0].category, DeprecationWarning) assert "deprecated" in str(w[0].message).lower() assert "save_to_file" in str(w[0].message) finally: if os.path.exists(temp_filename): os.remove(temp_filename) def test_load_from_file_raises_deprecation_warning(self): """Test load_from_file() raises deprecation warning.""" import warnings serie = Serie( key="test-key", name="Test Series", site="https://example.com", folder="Test Folder", episodeDict={1: [1, 2, 3]} ) with tempfile.NamedTemporaryFile( mode='w', suffix='.json', delete=False ) as temp_file: temp_filename = temp_file.name try: # Save first (suppress warning for this) with warnings.catch_warnings(): warnings.simplefilter("ignore") serie.save_to_file(temp_filename) # Now test loading with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") Serie.load_from_file(temp_filename) # Check deprecation warning was raised assert len(w) == 1 assert issubclass(w[0].category, DeprecationWarning) assert "deprecated" in str(w[0].message).lower() assert "load_from_file" in str(w[0].message) finally: if os.path.exists(temp_filename): os.remove(temp_filename)