"""Unit test for NFOService.update_tvshow_nfo() - tests XML parsing logic.""" import asyncio import shutil import tempfile from pathlib import Path import pytest from lxml import etree from src.core.services.nfo_service import NFOService from src.core.services.tmdb_client import TMDBAPIError def create_sample_nfo(tmdb_id: int = 1429) -> str: """Create a sample NFO XML with TMDB ID.""" return f''' Attack on Titan Shingeki no Kyojin 2013 Several hundred years ago, humans were nearly exterminated by Titans. {tmdb_id} 267440 {tmdb_id} 267440 ''' def test_parse_nfo_with_uniqueid(): """Test parsing NFO with uniqueid elements.""" # Create temporary directory structure temp_dir = Path(tempfile.mkdtemp()) serie_folder = temp_dir / "test_series" serie_folder.mkdir() nfo_path = serie_folder / "tvshow.nfo" try: # Write sample NFO nfo_path.write_text(create_sample_nfo(1429), encoding="utf-8") # Parse it (same logic as in update_tvshow_nfo) tree = etree.parse(str(nfo_path)) root = tree.getroot() # Extract TMDB ID tmdb_id = None for uniqueid in root.findall(".//uniqueid"): if uniqueid.get("type") == "tmdb": tmdb_id = int(uniqueid.text) break assert tmdb_id == 1429, f"Expected TMDB ID 1429, got {tmdb_id}" print(f"✓ Successfully parsed TMDB ID from uniqueid: {tmdb_id}") finally: shutil.rmtree(temp_dir) def test_parse_nfo_with_tmdbid_element(): """Test parsing NFO with tmdbid element (fallback).""" # Create NFO without uniqueid but with tmdbid element nfo_content = ''' Test Show 12345 ''' temp_dir = Path(tempfile.mkdtemp()) serie_folder = temp_dir / "test_series" serie_folder.mkdir() nfo_path = serie_folder / "tvshow.nfo" try: nfo_path.write_text(nfo_content, encoding="utf-8") # Parse it tree = etree.parse(str(nfo_path)) root = tree.getroot() # Try uniqueid first (should fail) tmdb_id = None for uniqueid in root.findall(".//uniqueid"): if uniqueid.get("type") == "tmdb": tmdb_id = int(uniqueid.text) break # Fallback to tmdbid element if tmdb_id is None: tmdbid_elem = root.find(".//tmdbid") if tmdbid_elem is not None and tmdbid_elem.text: tmdb_id = int(tmdbid_elem.text) assert tmdb_id == 12345, f"Expected TMDB ID 12345, got {tmdb_id}" print(f"✓ Successfully parsed TMDB ID from tmdbid element: {tmdb_id}") finally: shutil.rmtree(temp_dir) def test_parse_nfo_without_tmdb_id(): """Test parsing NFO without TMDB ID raises appropriate error.""" # Create NFO without any TMDB ID nfo_content = ''' Test Show ''' temp_dir = Path(tempfile.mkdtemp()) serie_folder = temp_dir / "test_series" serie_folder.mkdir() nfo_path = serie_folder / "tvshow.nfo" try: nfo_path.write_text(nfo_content, encoding="utf-8") # Parse it tree = etree.parse(str(nfo_path)) root = tree.getroot() # Try to extract TMDB ID tmdb_id = None for uniqueid in root.findall(".//uniqueid"): if uniqueid.get("type") == "tmdb": tmdb_id = int(uniqueid.text) break if tmdb_id is None: tmdbid_elem = root.find(".//tmdbid") if tmdbid_elem is not None and tmdbid_elem.text: tmdb_id = int(tmdbid_elem.text) assert tmdb_id is None, "Should not have found TMDB ID" print("✓ Correctly identified NFO without TMDB ID") finally: shutil.rmtree(temp_dir) def test_parse_invalid_xml(): """Test parsing invalid XML raises appropriate error.""" nfo_content = ''' Unclosed tag </tvshow>''' temp_dir = Path(tempfile.mkdtemp()) serie_folder = temp_dir / "test_series" serie_folder.mkdir() nfo_path = serie_folder / "tvshow.nfo" try: nfo_path.write_text(nfo_content, encoding="utf-8") # Try to parse - should raise XMLSyntaxError try: tree = etree.parse(str(nfo_path)) assert False, "Should have raised XMLSyntaxError" except etree.XMLSyntaxError: print("✓ Correctly raised XMLSyntaxError for invalid XML") finally: shutil.rmtree(temp_dir) if __name__ == "__main__": print("Testing NFO XML parsing logic...") print() test_parse_nfo_with_uniqueid() test_parse_nfo_with_tmdbid_element() test_parse_nfo_without_tmdb_id() test_parse_invalid_xml() print() print("=" * 60) print("✓ ALL TESTS PASSED") print("=" * 60)