implements page-numbers-plan

This commit is contained in:
rehlert committed 2026-10-28 09:25:15 +01:00
1 parent 39da8dac4d
commit b5279434b2
19 files changed
+1823 -339

No files matched your search

+61 -4
View File
@@ -1,4 +1,6 @@
import { expect, test } from '@playwright/test';
import { unzipSync } from 'fflate';
import { readFile } from 'node:fs/promises';
import { PDFDocument } from 'pdf-lib';
import {
createEncryptedPdf,
@@ -29,8 +31,10 @@ test('stamp presets fill the editable text and EILT is applied to every page', a
await expect(page.getByTestId('stamp-preview')).toContainText('EILT');
await expect(page.getByTestId('stamp-preview')).not.toHaveCSS('transform', 'none');
await page.getByRole('button', { name: 'Stempel anwenden', exact: true }).click();
await expect(page.getByText('Fertig ✓')).toBeVisible({ timeout: 20_000 });
const downloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: 'Stempel anwenden & herunterladen' }).click();
await page.getByRole('button', { name: 'akte.pdf herunterladen' }).click();
const outputBytes = await expectPdfDownload(await downloadPromise, /^akte_stempel\.pdf$/);
const output = await PDFDocument.load(outputBytes);
expect(output.getPageCount()).toBe(3);
@@ -58,8 +62,10 @@ test('stamp custom text adds a German date and only changes selected pages', asy
await page.getByRole('checkbox', { name: 'Auf alle Seiten anwenden' }).uncheck();
await page.getByRole('button', { name: /Seite 2/ }).click();
await page.getByRole('button', { name: 'Stempel anwenden', exact: true }).click();
await expect(page.getByText('Fertig ✓')).toBeVisible({ timeout: 20_000 });
const downloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: 'Stempel anwenden & herunterladen' }).click();
await page.getByRole('button', { name: 'auswahl.pdf herunterladen' }).click();
const outputBytes = await expectPdfDownload(await downloadPromise, /^auswahl_stempel\.pdf$/);
const output = await PDFDocument.load(outputBytes);
expect(output.getPageCount()).toBe(3);
@@ -89,8 +95,10 @@ test('stamp uses an image instead of text and makes the border optional', async
page.getByRole('checkbox', { name: 'Rahmen um das Bild anzeigen' })
).not.toBeChecked();
await page.getByRole('button', { name: 'Stempel anwenden', exact: true }).click();
await expect(page.getByText('Fertig ✓')).toBeVisible({ timeout: 20_000 });
const downloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: 'Stempel anwenden & herunterladen' }).click();
await page.getByRole('button', { name: 'bildakte.pdf herunterladen' }).click();
const outputBytes = await expectPdfDownload(await downloadPromise, /^bildakte_stempel\.pdf$/);
const output = await PDFDocument.load(outputBytes);
expect(output.getPageCount()).toBe(2);
@@ -103,8 +111,18 @@ test('stamp uses an image instead of text and makes the border optional', async
await page.getByRole('checkbox', { name: 'Rahmen um das Bild anzeigen' }).check();
await expect(page.getByTestId('stamp-preview')).toHaveCSS('border-style', 'solid');
// Re-add the file so the changed option applies to a fresh pending row.
await page.getByRole('button', { name: 'bildakte.pdf entfernen' }).click();
await dropFiles(page, pdfDropzone(page), [
{ name: 'bildakte.pdf', mimeType: 'application/pdf', buffer: await createPdf(2, 'Bild') }
]);
await expect(page.getByTestId('stamp-preview').locator('img')).toBeVisible();
await page.getByRole('button', { name: 'Stempel anwenden', exact: true }).click();
await expect(page.getByText('Fertig ✓')).toBeVisible({ timeout: 20_000 });
const borderedDownloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: 'Stempel anwenden & herunterladen' }).click();
await page.getByRole('button', { name: 'bildakte.pdf herunterladen' }).click();
const borderedBytes = await expectPdfDownload(
await borderedDownloadPromise,
/^bildakte_stempel\.pdf$/
@@ -120,6 +138,45 @@ test('stamp uses an image instead of text and makes the border optional', async
expect(pageErrors).toEqual([]);
});
test('stamp batch applies to every file and bundles results in one ZIP', async ({ page }) => {
const pageErrors = trackPageErrors(page);
await page.goto('/tools/stamp');
await dropFiles(page, pdfDropzone(page), [
{ name: 'eins.pdf', mimeType: 'application/pdf', buffer: await createPdf(1, 'Eins') },
{ name: 'zwei.pdf', mimeType: 'application/pdf', buffer: await createPdf(2, 'Zwei') },
{
name: 'kaputt.pdf',
mimeType: 'application/pdf',
buffer: Buffer.from('kein gueltiges PDF')
},
{
name: 'geschuetzt.pdf',
mimeType: 'application/pdf',
buffer: await createEncryptedPdf(1, 'Geschützt', 'test-passwort')
}
]);
await expect(page.getByText('Dateien (4)')).toBeVisible();
// With several files the stamp is applied to every page and no preview is loaded.
await expect(page.getByRole('checkbox', { name: 'Auf alle Seiten anwenden' })).toHaveCount(0);
await expect(page.getByRole('heading', { name: 'Vorschau' })).toHaveCount(0);
await page.getByRole('button', { name: 'Stempel anwenden', exact: true }).click();
await expect(page.getByText('Fertig ✓')).toHaveCount(2, { timeout: 30_000 });
await expect(page.getByText('Fehler')).toHaveCount(2);
await expect(page.getByText('Dieses PDF ist passwortgeschützt')).toBeVisible();
const downloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: 'Alle herunterladen' }).click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toMatch(/^stempel_\d{4}-\d{2}-\d{2}\.zip$/);
const zipPath = await download.path();
expect(zipPath).not.toBeNull();
const entries = Object.keys(unzipSync(new Uint8Array(await readFile(zipPath!))));
expect(entries.sort()).toEqual(['eins_stempel.pdf', 'zwei_stempel.pdf']);
expect(pageErrors).toEqual([]);
});
test('stamp explains how to handle a password-protected PDF', async ({ page }) => {
const pageErrors = trackPageErrors(page);
await page.goto('/tools/stamp');