// @ts-check // Hotspot: Bankimport-Vorschau. // // Die Vorschau wird vollständig im Browser aufgebaut: Die Datei geht per fetch() // an /bank/detect-format, das Ergebnis wird per innerHTML in die Seite geschrieben // (src/Views/bank/upload.php). Genau hier saß das DOM-XSS aus Issue #133 — ein // serverseitiger Test kann diesen Pfad grundsätzlich nicht erreichen. // // Diese Tests brechen bewusst VOR dem Bestätigen ab: Die Vorschau allein legt // keine Banktransaktionen an, der Datenbestand bleibt unangetastet. const { test, expect } = require('@playwright/test') const { uniqueTag, gotoOk } = require('../helpers/app') /** CSV im Comdirect-Format: 4 zu überspringende Zeilen, dann Header, dann Daten. */ function comdirectCsv(buchungstext, betrag = '-119,00') { return [ 'Umsätze Girokonto;', '"Zeitraum:";"30 Tage";', '"Neuer Kontostand";"1.234,56 EUR";', '', '"Buchungstag";"Wertstellung (Valuta)";"Vorgang";"Buchungstext";"Umsatz in EUR";', `"15.05.2026";"15.05.2026";"Lastschrift";"${buchungstext}";"${betrag}";`, '"14.05.2026";"14.05.2026";"Gutschrift";"Zahlungseingang Kunde";"500,00";', '', ].join('\n') } /** Datei in die Upload-Fläche legen und auf die fertige Formaterkennung warten. */ async function datenVorschauLaden(page, csvInhalt, dateiname = 'e2e-bank.csv') { await gotoOk(page, '/bank/upload') await page.setInputFiles('#bank-dnd-input', { name: dateiname, mimeType: 'text/csv', buffer: Buffer.from(csvInhalt, 'utf-8'), }) // Die Vorschau erscheint erst, wenn der fetch auf /bank/detect-format durch ist. await expect(page.locator('#preview-firstrow')).toBeVisible({ timeout: 15000 }) } test.describe('Bankimport-Vorschau', () => { test('Vorschau zeigt die erste Datenzeile und aktiviert den Import-Button', async ({ page }) => { const tag = uniqueTag() await datenVorschauLaden(page, comdirectCsv(`Lieferant ${tag}`)) await expect(page.locator('#preview-firstrow')).toContainText(tag) await expect(page.locator('#preview-firstrow')).toContainText('15.05.2026') await expect(page.locator('#map-wert')).toContainText('-119,00') // Erkanntes Format muss gesetzt und der Import damit möglich sein. await expect(page.locator('#bank-upload-btn')).toBeEnabled() expect(await page.locator('#format_id').inputValue()).not.toBe('') }) test('Skriptcode im Buchungstext wird nicht ausgeführt (Regression #133)', async ({ page }) => { const marker = uniqueTag('XSS') // Zwei Vektoren: ein Element mit Error-Handler und ein direktes Script-Tag. const payload = `