from abogen.integrations.calibre_opds import CalibreOPDSClient, feed_to_dict
def test_calibre_opds_feed_exposes_series_metadata() -> None:
client = CalibreOPDSClient("http://example.com/catalog")
xml_payload = """
catalog
Example Catalog
book-1
Sample Book
The Expanse
4
"""
feed = client._parse_feed(xml_payload, base_url="http://example.com/catalog")
assert feed.entries, "Expected at least one entry in parsed feed"
entry = feed.entries[0]
assert entry.series == "The Expanse"
assert entry.series_index == 4.0
feed_dict = feed_to_dict(feed)
assert feed_dict["entries"][0]["series"] == "The Expanse"
assert feed_dict["entries"][0]["series_index"] == 4.0
def test_calibre_opds_feed_extracts_series_from_categories() -> None:
client = CalibreOPDSClient("http://example.com/catalog")
xml_payload = """
catalog
Example Catalog
book-2
Network Effect
"""
feed = client._parse_feed(xml_payload, base_url="http://example.com/catalog")
assert feed.entries, "Expected at least one entry in parsed feed"
entry = feed.entries[0]
assert entry.series == "The Murderbot Diaries"
assert entry.series_index == 5.0
def test_calibre_opds_extracts_tags_and_rating_from_summary() -> None:
client = CalibreOPDSClient("http://example.com/catalog")
xml_payload = """
catalog
Example Catalog
book-3
Summary Sample
2024-01-15T00:00:00+00:00
RATING: ★★★½
TAGS: Science Fiction; Adventure
SERIES: Saga [3]
This is the detailed summary text.
"""
feed = client._parse_feed(xml_payload, base_url="http://example.com/catalog")
entry = feed.entries[0]
assert entry.series == "Saga"
assert entry.series_index == 3.0
assert entry.tags == ["Science Fiction", "Adventure"]
assert entry.rating == 3.5
assert entry.rating_max == 5.0
assert entry.summary == "This is the detailed summary text."
assert entry.published == "2024-01-15T00:00:00+00:00"
def test_calibre_opds_relative_urls_keep_catalog_prefix() -> None:
client = CalibreOPDSClient("http://example.com/opds/")
assert client._make_url("search") == "http://example.com/opds/search"
assert client._make_url("books/sample.epub") == "http://example.com/opds/books/sample.epub"
assert client._make_url("/cover/1") == "http://example.com/cover/1"
assert client._make_url("?page=2") == "http://example.com/opds/?page=2"
def test_calibre_opds_filters_out_unsupported_formats() -> None:
client = CalibreOPDSClient("http://example.com/catalog")
xml_payload = """
catalog
Example Catalog
audio-book
Unsupported Audio
pdf-book
Allowed PDF
epub-book
Allowed EPUB
"""
feed = client._parse_feed(xml_payload, base_url="http://example.com/catalog")
identifiers = {entry.id for entry in feed.entries}
assert identifiers == {"pdf-book", "epub-book"}
for entry in feed.entries:
assert entry.download is not None
assert entry.download.href.endswith((".pdf", ".epub"))