epub2pdf: title-based export names, .pdf download headers, security hardening (68 tests green)
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"""Unit tests for EPUB structure parsing (no rendering involved)."""
|
||||
import pytest
|
||||
|
||||
import app
|
||||
from tests.helpers import build_epub_tree
|
||||
|
||||
|
||||
def test_missing_container_xml_raises(tmp_path):
|
||||
(tmp_path / "META-INF").mkdir()
|
||||
with pytest.raises(ValueError, match="missing META-INF/container.xml"):
|
||||
app.parse_opf(tmp_path)
|
||||
|
||||
|
||||
def test_container_xml_without_rootfile_raises(tmp_path):
|
||||
(tmp_path / "META-INF").mkdir()
|
||||
(tmp_path / "META-INF" / "container.xml").write_text(
|
||||
'<?xml version="1.0"?><container version="1.0"><rootfiles/></container>',
|
||||
encoding="utf-8",
|
||||
)
|
||||
with pytest.raises(ValueError, match="no rootfile"):
|
||||
app.parse_opf(tmp_path)
|
||||
|
||||
|
||||
def test_parse_opf_returns_meta_spine_and_pdir_ltr(tmp_path):
|
||||
build_epub_tree(tmp_path)
|
||||
meta, opf_dir, spine, pdir = app.parse_opf(tmp_path)
|
||||
assert meta["title"] == "Tree Book"
|
||||
assert meta["creator"] == "Tree Author"
|
||||
assert meta["language"] == "en"
|
||||
assert str(opf_dir).endswith("OEBPS")
|
||||
assert [i["href"] for i in spine] == ["chapter1.xhtml", "chapter2.xhtml"] # img filtered out
|
||||
assert pdir == "ltr" # unset defaults to ltr
|
||||
|
||||
|
||||
def test_parse_opf_rtl_page_progression(tmp_path):
|
||||
build_epub_tree(tmp_path, pdir="rtl")
|
||||
_, _, _, pdir = app.parse_opf(tmp_path)
|
||||
assert pdir == "rtl"
|
||||
|
||||
|
||||
def test_nonlinear_spine_items_are_skipped(tmp_path):
|
||||
items = [
|
||||
("front", "front.xhtml", "application/xhtml+xml", ""),
|
||||
("ch1", "chapter1.xhtml", "application/xhtml+xml", ""),
|
||||
]
|
||||
build_epub_tree(tmp_path, items=items, spine_ids=["ch1"])
|
||||
# Add a non-linear itemref for 'front' via raw OPF edit
|
||||
opf_path = tmp_path / "OEBPS" / "book.opf"
|
||||
text = opf_path.read_text(encoding="utf-8")
|
||||
text = text.replace(
|
||||
'<spine><itemref idref="ch1"/></spine>',
|
||||
'<spine><itemref idref="front" linear="no"/>'
|
||||
'<itemref idref="ch1"/></spine>',
|
||||
)
|
||||
opf_path.write_text(text, encoding="utf-8")
|
||||
_, _, spine, _ = app.parse_opf(tmp_path)
|
||||
assert [i["href"] for i in spine] == ["chapter1.xhtml"]
|
||||
|
||||
|
||||
def test_empty_spine_falls_back_to_non_nav_html(tmp_path):
|
||||
items = [
|
||||
("nav", "nav.xhtml", "application/xhtml+xml", "nav"),
|
||||
("ch1", "chapter1.xhtml", "application/xhtml+xml", ""),
|
||||
("img1", "img.png", "image/png", ""),
|
||||
]
|
||||
build_epub_tree(tmp_path, items=items, spine_ids=[]) # spine refs: none
|
||||
_, _, spine, _ = app.parse_opf(tmp_path)
|
||||
assert [i["href"] for i in spine] == ["chapter1.xhtml"] # nav + image excluded
|
||||
|
||||
|
||||
def test_no_readable_content_raises(tmp_path):
|
||||
items = [("img1", "img.png", "image/png", "")]
|
||||
build_epub_tree(tmp_path, items=items, spine_ids=["img1"])
|
||||
with pytest.raises(ValueError, match="No readable content"):
|
||||
app.parse_opf(tmp_path)
|
||||
Reference in New Issue
Block a user