@@ -0,0 +1,138 @@
|
||||
import { expect, test, type Page } from '@playwright/test';
|
||||
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
|
||||
import {
|
||||
createEncryptedPdf,
|
||||
createPdf,
|
||||
dropFiles,
|
||||
expectPdfDownload,
|
||||
pdfDropzone,
|
||||
trackPageErrors
|
||||
} from './helpers';
|
||||
|
||||
const createPdfWithMetadata = async () => {
|
||||
const document = await PDFDocument.create();
|
||||
const font = await document.embedFont(StandardFonts.Helvetica);
|
||||
for (let pageNumber = 1; pageNumber <= 2; pageNumber += 1) {
|
||||
const page = document.addPage([420, 594]);
|
||||
page.drawText(`Vertraulich – Seite ${pageNumber}`, {
|
||||
x: 40,
|
||||
y: 520,
|
||||
size: 20,
|
||||
font,
|
||||
color: rgb(0.1, 0.2, 0.4)
|
||||
});
|
||||
}
|
||||
document.setTitle('Schriftsatz 12. Kammer');
|
||||
document.setAuthor('Dr. Echte Anwältin');
|
||||
document.setSubject('Klageerwiderung');
|
||||
document.setKeywords(['vertraulich, Mandat 4711']);
|
||||
document.setCreator('Anwaltssoftware Pro');
|
||||
document.setProducer('PDF-Fabrik 3.2');
|
||||
document.setCreationDate(new Date('2024-05-06T09:12:00Z'));
|
||||
document.setModificationDate(new Date('2024-05-07T16:40:00Z'));
|
||||
return Buffer.from(await document.save());
|
||||
};
|
||||
|
||||
const metadataValue = (page: Page, label: string) =>
|
||||
page.locator(`[data-metadata-value="${label}"]`);
|
||||
|
||||
test('metadata tool shows document properties of a dropped PDF', async ({ page }) => {
|
||||
const pageErrors = trackPageErrors(page);
|
||||
await page.goto('/tools/metadata');
|
||||
await dropFiles(page, pdfDropzone(page), [
|
||||
{
|
||||
name: 'schriftsatz.pdf',
|
||||
mimeType: 'application/pdf',
|
||||
buffer: await createPdfWithMetadata()
|
||||
}
|
||||
]);
|
||||
|
||||
await expect(metadataValue(page, 'Titel')).toHaveText('Schriftsatz 12. Kammer');
|
||||
await expect(metadataValue(page, 'Autor')).toHaveText('Dr. Echte Anwältin');
|
||||
await expect(metadataValue(page, 'Betreff')).toHaveText('Klageerwiderung');
|
||||
await expect(metadataValue(page, 'Schlüsselwörter')).toHaveText('vertraulich, Mandat 4711');
|
||||
await expect(metadataValue(page, 'Erstellt mit')).toHaveText('Anwaltssoftware Pro');
|
||||
await expect(metadataValue(page, 'PDF-Erzeuger')).toHaveText('PDF-Fabrik 3.2');
|
||||
await expect(metadataValue(page, 'Erstellt am')).toContainText('2024');
|
||||
await expect(metadataValue(page, 'Geändert am')).toContainText('2024');
|
||||
await expect(metadataValue(page, 'Seiten')).toHaveText('2');
|
||||
await expect(metadataValue(page, 'Verschlüsselung')).toHaveText('Nein');
|
||||
expect(pageErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test('metadata tool shows a dash for empty fields', async ({ page }) => {
|
||||
const pageErrors = trackPageErrors(page);
|
||||
await page.goto('/tools/metadata');
|
||||
await dropFiles(page, pdfDropzone(page), [
|
||||
{ name: 'nackt.pdf', mimeType: 'application/pdf', buffer: await createPdf(1, 'Nackt') }
|
||||
]);
|
||||
|
||||
await expect(metadataValue(page, 'Titel')).toHaveText('–');
|
||||
await expect(metadataValue(page, 'Autor')).toHaveText('–');
|
||||
await expect(metadataValue(page, 'Schlüsselwörter')).toHaveText('–');
|
||||
expect(pageErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test('metadata tool downloads a cleaned PDF with empty document properties', async ({ page }) => {
|
||||
const pageErrors = trackPageErrors(page);
|
||||
await page.goto('/tools/metadata');
|
||||
await dropFiles(page, pdfDropzone(page), [
|
||||
{
|
||||
name: 'schriftsatz.pdf',
|
||||
mimeType: 'application/pdf',
|
||||
buffer: await createPdfWithMetadata()
|
||||
}
|
||||
]);
|
||||
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
await page.getByRole('button', { name: 'Bereinigt herunterladen' }).click();
|
||||
const bytes = await expectPdfDownload(await downloadPromise, /^schriftsatz_bereinigt\.pdf$/);
|
||||
|
||||
const document = await PDFDocument.load(bytes, { updateMetadata: false });
|
||||
expect((document.getTitle() ?? '').trim()).toBe('');
|
||||
expect((document.getAuthor() ?? '').trim()).toBe('');
|
||||
expect((document.getSubject() ?? '').trim()).toBe('');
|
||||
expect((document.getKeywords() ?? '').trim()).toBe('');
|
||||
expect(document.getProducer()).toBe('beA-Edit');
|
||||
expect(document.getPageCount()).toBe(2);
|
||||
expect(pageErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test('metadata tool rejects encrypted PDFs with a decrypt hint', async ({ page }) => {
|
||||
const pageErrors = trackPageErrors(page);
|
||||
await page.goto('/tools/metadata');
|
||||
await dropFiles(page, pdfDropzone(page), [
|
||||
{
|
||||
name: 'geheim.pdf',
|
||||
mimeType: 'application/pdf',
|
||||
buffer: await createEncryptedPdf(1, 'Geheim', 'test-passwort')
|
||||
}
|
||||
]);
|
||||
|
||||
await expect(page.getByText('Dieses PDF ist verschlüsselt')).toBeVisible();
|
||||
await expect(page.getByRole('link', { name: 'Passwort entfernen' })).toHaveAttribute(
|
||||
'href',
|
||||
'/tools/decrypt'
|
||||
);
|
||||
await expect(page.getByRole('button', { name: 'Bereinigt herunterladen' })).toBeDisabled();
|
||||
expect(pageErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test('metadata tool warns when embedded files are suspected', async ({ page }) => {
|
||||
const pageErrors = trackPageErrors(page);
|
||||
const pdf = await createPdf(1, 'Anlage');
|
||||
const withMarker = Buffer.concat([pdf, Buffer.from('\n% /EmbeddedFile\n')]);
|
||||
|
||||
await page.goto('/tools/metadata');
|
||||
await dropFiles(page, pdfDropzone(page), [
|
||||
{ name: 'mit-anlage.pdf', mimeType: 'application/pdf', buffer: withMarker }
|
||||
]);
|
||||
|
||||
await expect(
|
||||
page.getByText(
|
||||
'Die Datei enthält möglicherweise eingebettete Anlagen. Diese werden beim Bereinigen nicht entfernt.'
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Bereinigt herunterladen' })).toBeEnabled();
|
||||
expect(pageErrors).toEqual([]);
|
||||
});
|
||||
Reference in New Issue
Block a user