""" Tests for OPML 2.0 generation Tests OPML feed subscription list generation per v1.1.2 Phase 3. """ import pytest from xml.etree import ElementTree as ET from starpunk.feeds.opml import generate_opml def test_generate_opml_basic_structure(): """Test OPML has correct basic structure""" opml = generate_opml("https://example.com", "Test Blog") # Parse XML root = ET.fromstring(opml) # Check root element assert root.tag == "opml" assert root.get("version") == "2.0" # Check has head and body head = root.find("head") body = root.find("body") assert head is not None assert body is not None def test_generate_opml_head_content(): """Test OPML head contains required elements""" opml = generate_opml("https://example.com", "Test Blog") root = ET.fromstring(opml) head = root.find("head") # Check title title = head.find("title") assert title is not None assert title.text == "Test Blog Feeds" # Check dateCreated exists and is RFC 822 format date_created = head.find("dateCreated") assert date_created is not None assert date_created.text is not None # Should contain day, month, year (RFC 822 format) assert "GMT" in date_created.text def test_generate_opml_feed_outlines(): """Test OPML body contains all three feed formats""" opml = generate_opml("https://example.com", "Test Blog") root = ET.fromstring(opml) body = root.find("body") # Get all outline elements outlines = body.findall("outline") assert len(outlines) == 3 # Check RSS outline rss_outline = outlines[0] assert rss_outline.get("type") == "rss" assert rss_outline.get("text") == "Test Blog - RSS" assert rss_outline.get("xmlUrl") == "https://example.com/feed.rss" # Check ATOM outline atom_outline = outlines[1] assert atom_outline.get("type") == "rss" assert atom_outline.get("text") == "Test Blog - ATOM" assert atom_outline.get("xmlUrl") == "https://example.com/feed.atom" # Check JSON Feed outline json_outline = outlines[2] assert json_outline.get("type") == "rss" assert json_outline.get("text") == "Test Blog - JSON Feed" assert json_outline.get("xmlUrl") == "https://example.com/feed.json" def test_generate_opml_trailing_slash_removed(): """Test OPML removes trailing slash from site URL""" opml = generate_opml("https://example.com/", "Test Blog") root = ET.fromstring(opml) body = root.find("body") outlines = body.findall("outline") # URLs should not have double slashes assert outlines[0].get("xmlUrl") == "https://example.com/feed.rss" assert "example.com//feed" not in opml def test_generate_opml_xml_escaping(): """Test OPML properly escapes XML special characters""" opml = generate_opml("https://example.com", "Test & Blog ") root = ET.fromstring(opml) head = root.find("head") title = head.find("title") # Should be properly escaped assert title.text == "Test & Blog Feeds" def test_generate_opml_valid_xml(): """Test OPML generates valid XML""" opml = generate_opml("https://example.com", "Test Blog") # Should parse without errors try: ET.fromstring(opml) except ET.ParseError as e: pytest.fail(f"Generated invalid XML: {e}") def test_generate_opml_declaration(): """Test OPML starts with XML declaration""" opml = generate_opml("https://example.com", "Test Blog") # Should start with XML declaration assert opml.startswith('')