"""Unit tests for NFO generator."""
import pytest
from lxml import etree
from src.core.entities.nfo_models import (
ActorInfo,
ImageInfo,
RatingInfo,
TVShowNFO,
UniqueID,
)
from src.core.utils.nfo_generator import generate_tvshow_nfo, validate_nfo_xml
class TestGenerateTVShowNFO:
"""Test generate_tvshow_nfo function."""
def test_generate_minimal_nfo(self):
"""Test generation with minimal required fields."""
nfo = TVShowNFO(
title="Test Show",
plot="A test show"
)
xml_string = generate_tvshow_nfo(nfo)
assert xml_string.startswith('')
assert "
Test Show" in xml_string
assert "A test show" in xml_string
def test_generate_complete_nfo(self):
"""Test generation with all fields populated."""
nfo = TVShowNFO(
title="Complete Show",
originaltitle="Original Title",
year=2020,
plot="Complete test",
runtime=45,
premiered="2020-01-15",
status="Continuing",
genre=["Action", "Drama"],
studio=["Studio 1"],
country=["USA"],
ratings=[RatingInfo(
name="themoviedb",
value=8.5,
votes=1000,
max_rating=10,
default=True
)],
actors=[ActorInfo(
name="Test Actor",
role="Main Character"
)],
thumb=[ImageInfo(url="https://test.com/poster.jpg")],
uniqueid=[UniqueID(type="tmdb", value="12345")]
)
xml_string = generate_tvshow_nfo(nfo)
# Verify all elements present
assert "Complete Show" in xml_string
assert "Original Title" in xml_string
assert "2020" in xml_string
assert "45" in xml_string
assert "2020-01-15" in xml_string
assert "Continuing" in xml_string
assert "Action" in xml_string
assert "Drama" in xml_string
assert "Studio 1" in xml_string
assert "USA" in xml_string
assert "Test Actor" in xml_string
assert "Main Character" in xml_string
def test_generate_nfo_with_ratings(self):
"""Test NFO with multiple ratings."""
nfo = TVShowNFO(
title="Rated Show",
plot="Test",
ratings=[
RatingInfo(
name="themoviedb",
value=8.5,
votes=1000,
max_rating=10,
default=True
),
RatingInfo(
name="imdb",
value=8.2,
votes=5000,
max_rating=10,
default=False
)
]
)
xml_string = generate_tvshow_nfo(nfo)
assert '' in xml_string
assert '' in xml_string
assert '8.5' in xml_string
assert '1000' in xml_string
assert '' in xml_string
def test_generate_nfo_with_actors(self):
"""Test NFO with multiple actors."""
nfo = TVShowNFO(
title="Cast Show",
plot="Test",
actors=[
ActorInfo(name="Actor 1", role="Hero"),
ActorInfo(name="Actor 2", role="Villain", thumb="https://test.com/actor2.jpg")
]
)
xml_string = generate_tvshow_nfo(nfo)
assert '' in xml_string
assert 'Actor 1' in xml_string
assert 'Hero' in xml_string
assert 'Actor 2' in xml_string
assert 'https://test.com/actor2.jpg' in xml_string
def test_generate_nfo_with_images(self):
"""Test NFO with various image types."""
nfo = TVShowNFO(
title="Image Show",
plot="Test",
thumb=[
ImageInfo(url="https://test.com/poster.jpg", aspect="poster"),
ImageInfo(url="https://test.com/logo.png", aspect="clearlogo")
],
fanart=[
ImageInfo(url="https://test.com/fanart.jpg")
]
)
xml_string = generate_tvshow_nfo(nfo)
assert 'https://test.com/poster.jpg' in xml_string
assert 'https://test.com/logo.png' in xml_string
assert '' in xml_string
assert 'https://test.com/fanart.jpg' in xml_string
def test_generate_nfo_with_unique_ids(self):
"""Test NFO with multiple unique IDs."""
nfo = TVShowNFO(
title="ID Show",
plot="Test",
uniqueid=[
UniqueID(type="tmdb", value="12345", default=False),
UniqueID(type="tvdb", value="67890", default=True),
UniqueID(type="imdb", value="tt1234567", default=False)
]
)
xml_string = generate_tvshow_nfo(nfo)
assert '12345' in xml_string
assert '67890' in xml_string
assert 'tt1234567' in xml_string
def test_generate_nfo_escapes_special_chars(self):
"""Test that special XML characters are escaped."""
nfo = TVShowNFO(
title="Show & special \"chars\"",
plot="Plot with & ampersand"
)
xml_string = generate_tvshow_nfo(nfo)
# XML should escape special characters
assert "<" in xml_string or "" in xml_string
assert "&" in xml_string or "&" in xml_string
def test_generate_nfo_valid_xml(self):
"""Test that generated XML is valid."""
nfo = TVShowNFO(
title="Valid Show",
plot="Test",
year=2020,
genre=["Action"],
ratings=[RatingInfo(name="test", value=8.0)]
)
xml_string = generate_tvshow_nfo(nfo)
# Should be parseable as XML
root = etree.fromstring(xml_string.encode('utf-8'))
assert root.tag == "tvshow"
def test_generate_nfo_none_values_omitted(self):
"""Test that None values are omitted from XML."""
nfo = TVShowNFO(
title="Sparse Show",
plot="Test",
year=None,
runtime=None,
premiered=None
)
xml_string = generate_tvshow_nfo(nfo)
# None values should not appear in XML
assert "" not in xml_string
assert "" not in xml_string
assert "" not in xml_string
class TestValidateNFOXML:
"""Test validate_nfo_xml function."""
def test_validate_valid_xml(self):
"""Test validation of valid XML."""
nfo = TVShowNFO(title="Test", plot="Test")
xml_string = generate_tvshow_nfo(nfo)
# Should not raise exception
validate_nfo_xml(xml_string)
def test_validate_invalid_xml(self):
"""Test validation of invalid XML."""
invalid_xml = "Unclosed"
with pytest.raises(ValueError, match="Invalid XML"):
validate_nfo_xml(invalid_xml)
def test_validate_missing_tvshow_root(self):
"""Test validation rejects non-tvshow root."""
invalid_xml = 'Test'
with pytest.raises(ValueError, match="root element must be"):
validate_nfo_xml(invalid_xml)
def test_validate_empty_string(self):
"""Test validation rejects empty string."""
with pytest.raises(ValueError):
validate_nfo_xml("")
def test_validate_well_formed_structure(self):
"""Test validation accepts well-formed structure."""
xml = """
Test Show
Test plot
2020
"""
validate_nfo_xml(xml)
class TestNFOGeneratorEdgeCases:
"""Test edge cases in NFO generation."""
def test_empty_lists(self):
"""Test generation with empty lists."""
nfo = TVShowNFO(
title="Empty Lists",
plot="Test",
genre=[],
studio=[],
actors=[]
)
xml_string = generate_tvshow_nfo(nfo)
# Should generate valid XML even with empty lists
root = etree.fromstring(xml_string.encode('utf-8'))
assert root.tag == "tvshow"
def test_unicode_characters(self):
"""Test handling of Unicode characters."""
nfo = TVShowNFO(
title="アニメ Show 中文",
plot="Plot with émojis 🎬 and spëcial çhars"
)
xml_string = generate_tvshow_nfo(nfo)
# Should encode Unicode properly
assert "アニメ" in xml_string
assert "中文" in xml_string
assert "émojis" in xml_string
def test_very_long_plot(self):
"""Test handling of very long plot text."""
long_plot = "A" * 10000
nfo = TVShowNFO(
title="Long Plot",
plot=long_plot
)
xml_string = generate_tvshow_nfo(nfo)
assert long_plot in xml_string
def test_multiple_studios(self):
"""Test handling multiple studios."""
nfo = TVShowNFO(
title="Multi Studio",
plot="Test",
studio=["Studio A", "Studio B", "Studio C"]
)
xml_string = generate_tvshow_nfo(nfo)
assert xml_string.count("") == 3
assert "Studio A" in xml_string
assert "Studio B" in xml_string
assert "Studio C" in xml_string
def test_special_date_formats(self):
"""Test various date format inputs."""
nfo = TVShowNFO(
title="Date Test",
plot="Test",
premiered="2020-01-01"
)
xml_string = generate_tvshow_nfo(nfo)
assert "2020-01-01" in xml_string