from pathlib import Path import pytest from ebooklib import epub from backend.epub import EpubConfig, parse_epub def _write_sample_epub(target: Path, chapter_count: int = 2) -> Path: book = epub.EpubBook() book.set_identifier("sample-id") book.set_title("Sample Book") book.set_language("en") book.add_author("Example Author") chapters = [] for idx in range(chapter_count): chapter = epub.EpubHtml( title=f"Chapter {idx + 1}", file_name=f"chap_{idx + 1}.xhtml", lang="en", ) chapter.content = ( f"
This is chapter {idx + 1}. It has enough words to estimate audio.
" ) book.add_item(chapter) chapters.append(chapter) book.toc = tuple(chapters) book.spine = ["nav", *chapters] book.add_item(epub.EpubNcx()) book.add_item(epub.EpubNav()) epub.write_epub(str(target), book) return target def test_parse_epub_extracts_metadata_and_chapters(tmp_path: Path) -> None: epub_path = _write_sample_epub(tmp_path / "sample.epub", chapter_count=3) payload = parse_epub(epub_path, config=EpubConfig(max_file_bytes=2_000_000)) assert payload["title"] == "Sample Book" assert payload["author"] == "Example Author" assert len(payload["chapters"]) == 3 assert payload["chapters"][0]["title"] == "Chapter 1" assert payload["chapters"][0]["included"] is True assert payload["chapters"][0]["text"] def test_parse_epub_rejects_oversized_upload(tmp_path: Path) -> None: epub_path = _write_sample_epub(tmp_path / "sample.epub", chapter_count=1) with pytest.raises(ValueError, match="too large"): parse_epub(epub_path, config=EpubConfig(max_file_bytes=32)) def test_parse_epub_rejects_malformed_file(tmp_path: Path) -> None: bad_path = tmp_path / "bad.epub" bad_path.write_text("not really an epub", encoding="utf-8") with pytest.raises(ValueError, match="Invalid EPUB"): parse_epub(bad_path, config=EpubConfig(max_file_bytes=2_000_000)) def test_parse_epub_accepts_valid_epub_without_epub_suffix(tmp_path: Path) -> None: epub_path = _write_sample_epub(tmp_path / "sample.epub", chapter_count=1) no_suffix_path = tmp_path / "upload-cache-file" no_suffix_path.write_bytes(epub_path.read_bytes()) payload = parse_epub(no_suffix_path, config=EpubConfig(max_file_bytes=2_000_000)) assert payload["title"] == "Sample Book" assert len(payload["chapters"]) == 1