// @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 = `