"""Hermetic fixtures for the EPUB -> PDF converter suite. Isolation contract ------------------ - ``DATA_DIR`` is redirected to a fresh temp dir BEFORE ``app`` is imported (app.py reads the env var at import time, app.py:36). - The Flask test client is used: no live server, no port conflicts, while conversion worker threads still run in-process. - The module-global ``JOBS`` registry is cleared before and after every test. """ import io import os import sys import tempfile from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) # Must happen before importing app — app.py bakes DATA_DIR in at import time. os.environ["DATA_DIR"] = tempfile.mkdtemp(prefix="epub2pdf-tests-") import app # noqa: E402 FIXTURE_EBOOK = ROOT / "test_book.epub" @pytest.fixture(scope="module") def client(): """Flask test client for the module-level app instance.""" app.app.config["TESTING"] = True with app.app.test_client() as c: yield c @pytest.fixture(autouse=True) def _isolate_jobs(): """Every test starts with (and leaves) an empty job registry.""" app.JOBS.clear() yield app.JOBS.clear() @pytest.fixture(scope="module") def fixture_epub_bytes(): """Raw bytes of the checked-in test book (em dashes + CJK).""" return FIXTURE_EBOOK.read_bytes() @pytest.fixture(scope="module") def submit_epub(client, fixture_epub_bytes): """Factory: POST an upload to /api/convert; returns the response.""" def _submit(filename="book.epub", content=None): if content is None: content = fixture_epub_bytes files = {"file": (io.BytesIO(content), filename)} return client.post( "/api/convert", data=files, content_type="multipart/form-data" ) return _submit