from __future__ import annotations import zipfile from abogen.epub3.exporter import build_epub3_package from abogen.text_extractor import ExtractedChapter, ExtractionResult def _make_sample_extraction() -> ExtractionResult: return ExtractionResult( chapters=[ ExtractedChapter(title="Chapter 1", text="Hello world."), ExtractedChapter(title="Chapter 2", text="Another passage."), ], metadata={"title": "Sample Book", "artist": "Test Author", "language": "en"}, ) def test_build_epub3_package_creates_expected_structure(tmp_path) -> None: extraction = _make_sample_extraction() chunks = [ { "id": "chap0000_p0000", "chapter_index": 0, "chunk_index": 0, "text": "Hello world.", "speaker_id": "narrator", }, { "id": "chap0001_p0000", "chapter_index": 1, "chunk_index": 0, "text": "Another passage.", "speaker_id": "narrator", }, ] chunk_markers = [ {"id": "chap0000_p0000", "chapter_index": 0, "chunk_index": 0, "start": 0.0, "end": 1.2}, {"id": "chap0001_p0000", "chapter_index": 1, "chunk_index": 0, "start": 1.2, "end": 2.4}, ] chapter_markers = [ {"index": 1, "title": "Chapter 1", "start": 0.0, "end": 1.2}, {"index": 2, "title": "Chapter 2", "start": 1.2, "end": 2.4}, ] metadata_tags = {"title": "Sample Book", "artist": "Test Author", "language": "en"} audio_path = tmp_path / "sample.mp3" audio_path.write_bytes(b"ID3 test audio") output_path = tmp_path / "output.epub" result_path = build_epub3_package( output_path=output_path, book_id="job-123", extraction=extraction, metadata_tags=metadata_tags, chapter_markers=chapter_markers, chunk_markers=chunk_markers, chunks=chunks, audio_path=audio_path, speaker_mode="single", ) assert result_path == output_path assert output_path.exists() with zipfile.ZipFile(output_path) as archive: names = set(archive.namelist()) assert "mimetype" in names assert archive.read("mimetype") == b"application/epub+zip" assert "META-INF/container.xml" in names assert "OEBPS/content.opf" in names assert "OEBPS/nav.xhtml" in names assert "OEBPS/audio/sample.mp3" in names chapter_doc = archive.read("OEBPS/text/chapter_0001.xhtml").decode("utf-8") assert "Hello world." in chapter_doc smil_doc = archive.read("OEBPS/smil/chapter_0001.smil").decode("utf-8") assert "clipBegin=\"00:00:00.000\"" in smil_doc opf_doc = archive.read("OEBPS/content.opf").decode("utf-8") assert "media-overlay" in opf_doc assert "media:duration" in opf_doc assert "abogen:speakerMode" in opf_doc def test_build_epub3_package_handles_missing_markers(tmp_path) -> None: extraction = _make_sample_extraction() metadata_tags = {"title": "Sample Book", "artist": "Test Author", "language": "en"} audio_path = tmp_path / "audio.mp3" audio_path.write_bytes(b"ID3 audio") output_path = tmp_path / "output.epub" result_path = build_epub3_package( output_path=output_path, book_id="job-456", extraction=extraction, metadata_tags=metadata_tags, chapter_markers=[], chunk_markers=[], chunks=[], audio_path=audio_path, speaker_mode="single", ) with zipfile.ZipFile(result_path) as archive: nav_doc = archive.read("OEBPS/nav.xhtml").decode("utf-8") assert "Chapter 1" in nav_doc chapter_doc = archive.read("OEBPS/text/chapter_0001.xhtml").decode("utf-8") assert "Hello world." in chapter_doc