library.py hält die Regeln der Web-Bibliothek (53-library.js) als reine Funktionen: Status Angefangen/Ungelesen/Gelesen, Ordner (mehrere je Buch, Reihenfolge aus den verschlüsselten Bibliothekseinstellungen, "Ohne Ordner"), Suche ohne Akzente, sechs Sortierungen mit natürlicher Zahlenordnung, Weiterlesen-Karte aus den zuletzt gelesenen, Bücher/Zeitschriften. library_screen.py zeigt sie an (Tasten 1-4, o, /, s, m, c; Chips und Karte klickbar). Metadaten (Ordner, Seitenzahl, Zeitschrift) und die Ordnerreihenfolge kommen beim Abgleich; fehlt die Länge, rechnet die TUI sie für geladene Bücher aus dem Text (1800 Zeichen je Seite). crypto.encrypt für Stufe 3. 54 Tests, Smoke prüft Ordner/Länge/Prefs gegen den lokalen Server. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
55 lines
2.4 KiB
Python
55 lines
2.4 KiB
Python
"""Tests run against a throwaway home: progress, config and caches are module-level
|
|
paths from platformdirs, read at import time, so the environment is set before anything
|
|
from diora_tui is imported."""
|
|
import os
|
|
import tempfile
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
_HOME = tempfile.mkdtemp(prefix="diora-tui-test-")
|
|
for var in ("LOCALAPPDATA", "APPDATA", "XDG_DATA_HOME", "XDG_CONFIG_HOME", "XDG_CACHE_HOME"):
|
|
os.environ[var] = _HOME
|
|
os.environ["HOME"] = _HOME
|
|
os.environ["DIORA_TUI_HOME"] = _HOME # platformdirs ignores the variables above on Windows
|
|
|
|
import pytest # noqa: E402
|
|
|
|
CONTAINER = """<?xml version="1.0"?>
|
|
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
|
<rootfiles><rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/></rootfiles>
|
|
</container>"""
|
|
|
|
|
|
def make_epub(path: Path, chapters: list[str], title: str = "Testbuch") -> Path:
|
|
"""A minimal EPUB whose spine is `chapters` (each one the full XHTML of a document)."""
|
|
items = "".join(f'<item id="c{i}" href="c{i}.xhtml" media-type="application/xhtml+xml"/>' for i in range(len(chapters)))
|
|
spine = "".join(f'<itemref idref="c{i}"/>' for i in range(len(chapters)))
|
|
opf = f"""<?xml version="1.0"?>
|
|
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="id">
|
|
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:title>{title}</dc:title><dc:creator>Autor</dc:creator>
|
|
<dc:identifier id="id">test-{title}</dc:identifier><dc:language>de</dc:language></metadata>
|
|
<manifest>{items}</manifest><spine>{spine}</spine></package>"""
|
|
with zipfile.ZipFile(path, "w") as z:
|
|
z.writestr("mimetype", "application/epub+zip")
|
|
z.writestr("META-INF/container.xml", CONTAINER)
|
|
z.writestr("OEBPS/content.opf", opf)
|
|
for i, body in enumerate(chapters):
|
|
z.writestr(f"OEBPS/c{i}.xhtml", f'<?xml version="1.0"?><html xmlns="http://www.w3.org/1999/xhtml"><head><title>x</title></head><body>{body}</body></html>')
|
|
return path
|
|
|
|
|
|
@pytest.fixture
|
|
def epub(tmp_path):
|
|
def build(chapters, title="Testbuch"):
|
|
return make_epub(tmp_path / f"{title}.epub", chapters, title)
|
|
return build
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def clean_library_meta():
|
|
"""library.json is one file in the shared test home: every test starts without it."""
|
|
from diora_tui import library_meta
|
|
|
|
library_meta._META_FILE.unlink(missing_ok=True)
|
|
yield
|
|
library_meta._META_FILE.unlink(missing_ok=True)
|