Files
teig-terminal/tests/pdf-download.test.js
Hermes Agent 07e7bf25c6
CI and Deploy / test-build-deploy (push) Successful in 4s
style: redesign PDF as full-page cyberpunk dashboard
2026-08-03 14:44:34 +00:00

83 lines
3.3 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const vm = require('node:vm');
const html = fs.readFileSync(path.join(__dirname, '..', 'index.html'), 'utf8');
assert.match(html, /id="downloadPdf"[^>]*>PDF herunterladen<\/button>/, 'PDF-Download-Button fehlt');
const start = html.indexOf('/* PDF-DOWNLOAD */');
const end = html.indexOf('/* PDF = Druckdialog', start);
assert.ok(start >= 0 && end > start, 'PDF-Download-Implementierung fehlt');
const sandbox = { Uint8Array, TextEncoder, Blob };
vm.createContext(sandbox);
vm.runInContext(`${html.slice(start, end)}\nglobalThis.api={pdfFilename,parsePdfRecipe,buildPdfBytes};`, sandbox);
const { pdfFilename, parsePdfRecipe, buildPdfBytes } = sandbox.api;
assert.equal(
pdfFilename('Napoletana', 4, 250, '24 Stunden'),
'Pizzateig-Napoletana-4x250g-24-Stunden.pdf'
);
assert.equal(
pdfFilename('Frei/Test', 2, 199.6, 'Same:Day'),
'Pizzateig-Frei-Test-2x200g-Same-Day.pdf'
);
assert.equal(
pdfFilename('Römisch tonda', 4, 200, 'Über Nacht'),
'Pizzateig-Romisch-tonda-4x200g-Uber-Nacht.pdf'
);
const recipeLines = [
'PIZZATEIG — Napoletana',
'4 Teiglinge à 250 g · 1.000 g Teig',
'Mehl: Caputo Pizzeria · Hydration 62 %',
'',
'ZUTATEN',
' Mehl 605 g',
' Wasser 375 g',
' Frischhefe 2,3 g',
' Salz 17 g',
'',
'ZEITPLAN',
' 19:00 Mo — Teig kneten und ruhen lassen (30 Min.)',
' 19:30 Mo — Ballen formen und bei Raumtemperatur reifen lassen',
' 23:00 Mo — Ballen in den Kühlschrank stellen',
' 15:00 Di — Ballen aus dem Kühlschrank nehmen',
' 19:00 Di — Pizza backen',
'',
'https://teig.deploybar.de/#style=napo&balls=4&ball=250&plan=d24',
];
const parsed = JSON.parse(JSON.stringify(parsePdfRecipe(recipeLines)));
assert.equal(parsed.title, 'PIZZATEIG — Napoletana');
assert.deepEqual(parsed.overview, ['4 Teiglinge à 250 g', '1.000 g Teig', 'Mehl: Caputo Pizzeria', 'Hydration 62 %']);
assert.deepEqual(parsed.sections.map(section => section.title), ['ZUTATEN', 'ZEITPLAN']);
assert.equal(parsed.sections[0].items.length, 4);
assert.equal(parsed.sections[1].items.length, 5);
assert.match(parsed.link, /^https:\/\/teig\.deploybar\.de\//);
const bytes = buildPdfBytes(recipeLines);
assert.ok(bytes instanceof Uint8Array);
const ascii = Buffer.from(bytes).toString('latin1');
assert.ok(ascii.startsWith('%PDF-1.4'));
assert.match(ascii, /\/Type \/Catalog/);
assert.match(ascii, /\/Type \/Page\b/);
assert.match(ascii, /\/Encoding \/WinAnsiEncoding/);
assert.match(ascii, /0\.027 0\.031 0\.043 rg/); // dunkler Cyberpunk-Hintergrund
assert.match(ascii, /0 0\.941 1 rg/); // Cyan-Akzent
assert.match(ascii, /1 0\.176 0\.471 rg/); // Magenta-Akzent
assert.match(ascii, /xref\n0 \d+/);
assert.match(ascii, /%%EOF\n$/);
assert.match(ascii, /\/Count 1\b/);
const longPdf = Buffer.from(buildPdfBytes([
'PIZZATEIG — Belastungstest',
...Array.from({ length: 120 }, (_, i) => `ZEILE ${i + 1} — Rezeptinformation`),
])).toString('latin1');
assert.match(longPdf, /\/Count 1\b/, 'PDF muss auf genau eine Seite begrenzt bleiben');
assert.equal((longPdf.match(/\/Type \/Page\b/g) || []).length, 1, 'PDF enthält mehr als eine A4-Seite');
fs.writeFileSync('/tmp/teig-terminal-download-test.pdf', Buffer.from(bytes));
console.log('pdf download tests: OK');