- e2e/reader.spec.js: ein Test-EPUB (e2e/make_epub.py) hochladen, öffnen ohne zu senden, lesen und Lesestand nach Neuladen, Fußnote, Markierung und Notizleiste, Hell/Dunkel samt Reader, alle Tabs ohne Seitenfehler. - e2e/env.js: E2E_PORT und E2E_PYTHON; nie einen laufenden Server wiederverwenden (dahinter läge eine echte Datenbank). - CI: eigener Job e2e (Playwright + Chromium); blockiert den Docker-Build nicht. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
58 lines
2.9 KiB
Python
58 lines
2.9 KiB
Python
"""A small EPUB for the e2e tests: 12 chapters of numbered paragraphs (long enough
|
|
to scroll and to have a reading position), one footnote. Written to the path in
|
|
argv[1]; e2e/global-setup.js calls it for every run."""
|
|
import sys
|
|
import zipfile
|
|
|
|
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 chapter(n):
|
|
paras = []
|
|
for p in range(1, 41):
|
|
text = f'Kapitel {n}, Absatz {p}. ' + ' '.join(
|
|
f'Wort{w} im Absatz {p} des Kapitels {n} steht hier, damit der Absatz einige Zeilen lang wird.'
|
|
for w in range(1, 6))
|
|
if n == 1 and p == 3:
|
|
text += ' Mit Fußnote<a href="ch12.xhtml#fn1" epub:type="noteref"><sup>1</sup></a>.'
|
|
paras.append(f'<p id="c{n}p{p}">{text}</p>')
|
|
notes = ''
|
|
if n == 12:
|
|
notes = '<aside epub:type="footnote" id="fn1"><p>1 Der Text der Fußnote.</p></aside>'
|
|
return f"""<?xml version="1.0" encoding="utf-8"?>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
|
|
<head><title>Kapitel {n}</title></head>
|
|
<body><h1>Kapitel {n}</h1>{''.join(paras)}{notes}</body></html>"""
|
|
|
|
|
|
def main(path):
|
|
chapters = range(1, 13)
|
|
manifest = ''.join(f'<item id="c{n}" href="ch{n}.xhtml" media-type="application/xhtml+xml"/>' for n in chapters)
|
|
spine = ''.join(f'<itemref idref="c{n}"/>' for n in chapters)
|
|
nav_items = ''.join(f'<li><a href="ch{n}.xhtml">Kapitel {n}</a></li>' for n in chapters)
|
|
opf = f"""<?xml version="1.0" encoding="utf-8"?>
|
|
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="id">
|
|
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
<dc:identifier id="id">diora-e2e-book</dc:identifier>
|
|
<dc:title>E2E Testbuch</dc:title><dc:creator>diora</dc:creator><dc:language>de</dc:language>
|
|
</metadata>
|
|
<manifest><item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>{manifest}</manifest>
|
|
<spine>{spine}</spine>
|
|
</package>"""
|
|
nav = f"""<?xml version="1.0" encoding="utf-8"?>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
|
|
<head><title>Inhalt</title></head><body><nav epub:type="toc"><ol>{nav_items}</ol></nav></body></html>"""
|
|
with zipfile.ZipFile(path, 'w') as z:
|
|
z.writestr(zipfile.ZipInfo('mimetype'), 'application/epub+zip', compress_type=zipfile.ZIP_STORED)
|
|
z.writestr('META-INF/container.xml', CONTAINER, compress_type=zipfile.ZIP_DEFLATED)
|
|
z.writestr('OEBPS/content.opf', opf, compress_type=zipfile.ZIP_DEFLATED)
|
|
z.writestr('OEBPS/nav.xhtml', nav, compress_type=zipfile.ZIP_DEFLATED)
|
|
for n in chapters:
|
|
z.writestr(f'OEBPS/ch{n}.xhtml', chapter(n), compress_type=zipfile.ZIP_DEFLATED)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv[1])
|