import { expect, test } from '@playwright/test'; import { unzipSync } from 'fflate'; import { readFile } from 'node:fs/promises'; import { createPdf, dropFiles, expectPdfDownload, pdfDropzone, trackPageErrors } from './helpers'; test('watermark accepts numeric controls and downloads text and image watermarks', async ({ page }) => { const pageErrors = trackPageErrors(page); await page.goto('/tools/watermark'); await dropFiles(page, pdfDropzone(page), [ { name: 'marke.pdf', mimeType: 'application/pdf', buffer: await createPdf(1, 'Marke') } ]); await expect(page.getByRole('heading', { name: 'Wasserzeichen-Einstellungen' })).toBeVisible(); await page.locator('#watermark-color').fill('#00ff00'); await page.locator('#watermark-opacity').fill('0.45'); await page.getByRole('button', { name: 'Wasserzeichen anwenden', exact: true }).click(); await expect(page.getByText('Fertig ✓')).toBeVisible({ timeout: 15_000 }); const downloadPromise = page.waitForEvent('download'); await page.getByRole('button', { name: 'marke.pdf herunterladen' }).click(); await expectPdfDownload(await downloadPromise, /^marke_wasserzeichen\.pdf$/); await page.getByLabel('Bild', { exact: true }).check(); await dropFiles(page, page.getByRole('button', { name: 'Wasserzeichenbild hinzufügen' }), [ { name: 'logo.png', mimeType: 'image/png', buffer: Buffer.from( 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9Y9Z5rAAAAAASUVORK5CYII=', 'base64' ) } ]); // The file is already done, so reset it to pending by removing and re-adding it. await page.getByRole('button', { name: 'marke.pdf entfernen' }).click(); await dropFiles(page, pdfDropzone(page), [ { name: 'marke.pdf', mimeType: 'application/pdf', buffer: await createPdf(1, 'Marke') } ]); await page.getByRole('button', { name: 'Wasserzeichen anwenden', exact: true }).click(); await expect(page.getByText('Fertig ✓')).toBeVisible({ timeout: 15_000 }); const imageDownloadPromise = page.waitForEvent('download'); await page.getByRole('button', { name: 'marke.pdf herunterladen' }).click(); await expectPdfDownload(await imageDownloadPromise, /^marke_wasserzeichen\.pdf$/); expect(pageErrors).toEqual([]); }); test('watermark batch applies to every file and bundles results in one ZIP', async ({ page }) => { const pageErrors = trackPageErrors(page); await page.goto('/tools/watermark'); 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') } ]); await expect(page.getByText('Dateien (3)')).toBeVisible(); await page.getByRole('button', { name: 'Wasserzeichen anwenden', exact: true }).click(); await expect(page.getByText('Fertig ✓')).toHaveCount(2, { timeout: 15_000 }); await expect(page.getByText('Fehler')).toBeVisible(); // With several files the per-file page selection is replaced by all pages. await expect(page.getByRole('checkbox', { name: 'Auf alle Seiten anwenden' })).toHaveCount(0); const downloadPromise = page.waitForEvent('download'); await page.getByRole('button', { name: 'Alle herunterladen' }).click(); const download = await downloadPromise; expect(download.suggestedFilename()).toMatch(/^wasserzeichen_\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_wasserzeichen.pdf', 'zwei_wasserzeichen.pdf']); expect(pageErrors).toEqual([]); });