- Fix XML declaration check to match 'standalone=yes' - Fix rating element checks to include max attribute - Fix uniqueid checks (default only present when true) - Fix validation tests (returns bool, doesn't raise) - Update validation test expectations to match actual behavior All test_nfo_generator.py tests now passing
179 lines
5.3 KiB
Python
179 lines
5.3 KiB
Python
"""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'''<?xml version="1.0" encoding="UTF-8"?>
|
|
<tvshow>
|
|
<title>Attack on Titan</title>
|
|
<originaltitle>Shingeki no Kyojin</originaltitle>
|
|
<year>2013</year>
|
|
<plot>Several hundred years ago, humans were nearly exterminated by Titans.</plot>
|
|
<uniqueid type="tmdb" default="false">{tmdb_id}</uniqueid>
|
|
<uniqueid type="tvdb" default="true">267440</uniqueid>
|
|
<tmdbid>{tmdb_id}</tmdbid>
|
|
<tvdbid>267440</tvdbid>
|
|
</tvshow>'''
|
|
|
|
|
|
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 = '''<?xml version="1.0" encoding="UTF-8"?>
|
|
<tvshow>
|
|
<title>Test Show</title>
|
|
<tmdbid>12345</tmdbid>
|
|
</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")
|
|
|
|
# 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 = '''<?xml version="1.0" encoding="UTF-8"?>
|
|
<tvshow>
|
|
<title>Test Show</title>
|
|
</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")
|
|
|
|
# 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 = '''<?xml version="1.0" encoding="UTF-8"?>
|
|
<tvshow>
|
|
<title>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)
|