File size: 2,536 Bytes
af4851b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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"<h1>Chapter {idx + 1}</h1>"
            f"<p>This is chapter {idx + 1}. It has enough words to estimate audio.</p>"
        )
        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