Über der Tabelle der Bankverbindungen ruft ein neuer Knopf jede aktive Bankverbindung einzeln nacheinander ab. Die Warteschlange (Services\Sammelabruf) übersteht TAN-Runden in der Sitzung; nach der Freigabe geht es mit der nächsten Bank weiter. Die TAN-Maske zeigt den Stand und erlaubt, eine Bank zu überspringen. Am Ende steht je Bankverbindung eine eigene Meldung. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
178 lines
7 KiB
JavaScript
178 lines
7 KiB
JavaScript
// @ts-check
|
||
const { test, expect } = require('@playwright/test')
|
||
|
||
const BENUTZER = process.env.E2E_USER || 'e2e'
|
||
const PASSWORT = process.env.E2E_PASSWORD || 'e2e-testpasswort'
|
||
|
||
// Eindeutige Namen je Lauf: die Tests arbeiten auf einer bestehenden Instanz
|
||
// und dürfen sich nicht an Resten eines früheren Laufs stoßen.
|
||
const MARKE = Date.now().toString().slice(-6)
|
||
|
||
async function anmelden(page) {
|
||
await page.goto('/login')
|
||
|
||
if (page.url().includes('/einrichtung')) {
|
||
throw new Error(
|
||
'Instanz ist noch nicht eingerichtet. Zuerst einen Benutzer anlegen: ' +
|
||
'docker compose exec -u www-data php php scripts/e2e-benutzer.php'
|
||
)
|
||
}
|
||
|
||
await page.fill('#benutzername', BENUTZER)
|
||
await page.fill('#passwort', PASSWORT)
|
||
await page.click('button[type="submit"]')
|
||
await expect(page).toHaveURL(/\/$/)
|
||
}
|
||
|
||
test.describe('Bankverbindungen', () => {
|
||
test.beforeEach(async ({ page }) => {
|
||
await anmelden(page)
|
||
})
|
||
|
||
test('„Bankverbindung anlegen“ führt zur Wahl zwischen HBCI/FinTS und PayPal', async ({ page }) => {
|
||
await page.goto('/banking')
|
||
await page.click('a[href="/banking/neu"]')
|
||
|
||
await expect(page.locator('h2')).toContainText('Wie wird abgerufen?')
|
||
|
||
const karten = page.locator('.formatwahl .formatkarte')
|
||
await expect(karten).toHaveCount(2)
|
||
await expect(karten.nth(0)).toContainText('HBCI/FinTS')
|
||
await expect(karten.nth(1)).toContainText('PayPal')
|
||
})
|
||
|
||
test('Die erste Wahl führt in die bisherige Bankenmaske', async ({ page }) => {
|
||
await page.goto('/banking/neu')
|
||
await page.click('.formatkarte:has-text("HBCI/FinTS")')
|
||
|
||
await expect(page).toHaveURL(/\/banking\/neu\/fints$/)
|
||
await expect(page.locator('.schrittmarke')).toContainText('Schritt 1 von 3')
|
||
await expect(page.locator('#fints_url')).toBeVisible()
|
||
await expect(page.locator('#pin')).toBeVisible()
|
||
})
|
||
|
||
test('Die zweite Wahl führt in die PayPal-Maske mit allen Angaben für die Abfrage', async ({ page }) => {
|
||
await page.goto('/banking/neu')
|
||
await page.click('.formatkarte:has-text("PayPal")')
|
||
|
||
await expect(page).toHaveURL(/\/banking\/neu\/paypal$/)
|
||
|
||
// Die drei Angaben der NVP-Schnittstelle und der Endpunkt-Schalter.
|
||
await expect(page.locator('#api_benutzer')).toBeVisible()
|
||
await expect(page.locator('#api_kennwort')).toBeVisible()
|
||
await expect(page.locator('#api_signatur')).toBeVisible()
|
||
await expect(page.locator('input[name="sandbox"]')).toBeAttached()
|
||
|
||
// Die Kontenzuordnung steht hier im Formular, nicht auf einer eigenen Seite.
|
||
await expect(page.locator('#konto_id')).toBeVisible()
|
||
await expect(page.locator('#konto_id option[value="neu"]')).toHaveCount(1)
|
||
})
|
||
|
||
test('PayPal-Verbindung anlegen, dabei ein neues Konto anlegen und wiederfinden', async ({ page }) => {
|
||
const name = `E2E PayPal ${MARKE}`
|
||
const konto = `E2E PayPal-Guthaben ${MARKE}`
|
||
|
||
await page.goto('/banking/neu/paypal')
|
||
await page.fill('#name', name)
|
||
await page.fill('#api_benutzer', `e2e_api1.example.org`)
|
||
await page.fill('#api_kennwort', 'e2e-kennwort')
|
||
await page.fill('#api_signatur', 'e2e-signatur')
|
||
await page.check('input[name="sandbox"]')
|
||
|
||
// Die Felder des neuen Kontos sind erst nach dieser Wahl sichtbar.
|
||
await expect(page.locator('#neuer_name')).toBeHidden()
|
||
await page.selectOption('#konto_id', 'neu')
|
||
await expect(page.locator('#neuer_name')).toBeVisible()
|
||
|
||
await page.fill('#neuer_name', konto)
|
||
await page.fill('#anfangssaldo', '25,00')
|
||
await page.click('.formular button[type="submit"]')
|
||
|
||
await expect(page.locator('.meldung-erfolg')).toBeVisible()
|
||
await expect(page).toHaveURL(/\/banking$/)
|
||
|
||
// In der Übersicht steht die Verbindung mit ihrer Art.
|
||
const zeile = page.locator('table.liste tr', { hasText: name })
|
||
await expect(zeile).toContainText('PayPal')
|
||
|
||
// Und beim Öffnen steht das eben angelegte Konto zugeordnet da; die
|
||
// Geheimnisse werden nicht wieder angezeigt.
|
||
await zeile.locator('a').first().click()
|
||
await expect(page.locator('#api_benutzer')).toHaveValue('e2e_api1.example.org')
|
||
await expect(page.locator('#api_kennwort')).toHaveValue('')
|
||
await expect(page.locator('#konto_id option:checked')).toHaveText(konto)
|
||
await expect(page.locator('input[name="sandbox"]')).toBeChecked()
|
||
})
|
||
|
||
test('„nicht zugeordnet“ löst eine bestehende Zuordnung wieder', async ({ page }) => {
|
||
const name = `E2E PayPal Zuordnung ${MARKE}`
|
||
const konto = `E2E PayPal-Konto ${MARKE}`
|
||
|
||
await page.goto('/banking/neu/paypal')
|
||
await page.fill('#name', name)
|
||
await page.fill('#api_benutzer', 'e2e_api1.example.org')
|
||
await page.fill('#api_kennwort', 'e2e-kennwort')
|
||
await page.fill('#api_signatur', 'e2e-signatur')
|
||
await page.selectOption('#konto_id', 'neu')
|
||
await page.fill('#neuer_name', konto)
|
||
await page.click('.formular button[type="submit"]')
|
||
await expect(page).toHaveURL(/\/banking$/)
|
||
|
||
await page.locator('table.liste tr', { hasText: name }).locator('a').first().click()
|
||
await expect(page.locator('#konto_id option:checked')).toHaveText(konto)
|
||
|
||
// Die leere Wahl heißt hier ausdrücklich „Zuordnung lösen“ – sie darf
|
||
// nicht als „nichts geändert“ durchrutschen.
|
||
await page.selectOption('#konto_id', '')
|
||
await page.click('.formular button[type="submit"]')
|
||
|
||
await expect(page.locator('.meldung-erfolg')).toBeVisible()
|
||
await expect(page.locator('#konto_id option:checked')).toHaveText('– nicht zugeordnet –')
|
||
})
|
||
|
||
test('„Alle Umsätze abrufen“ steht über der Tabelle der Bankverbindungen', async ({ page }) => {
|
||
const name = `E2E PayPal Sammelabruf ${MARKE}`
|
||
|
||
await page.goto('/banking/neu/paypal')
|
||
await page.fill('#name', name)
|
||
await page.fill('#api_benutzer', 'e2e_api1.example.org')
|
||
await page.fill('#api_kennwort', 'e2e-kennwort')
|
||
await page.fill('#api_signatur', 'e2e-signatur')
|
||
await page.click('.formular button[type="submit"]')
|
||
await expect(page).toHaveURL(/\/banking$/)
|
||
|
||
// Abgeschickt wird hier nicht: Der Lauf ginge an echte Gegenstellen.
|
||
const form = page.locator('.seitenaktionen form#alle-abrufen')
|
||
await expect(form).toHaveAttribute('method', 'post')
|
||
await expect(form).toHaveAttribute('action', '/banking/alle-abrufen')
|
||
await expect(form.locator('button[type="submit"]')).toHaveText('Alle Umsätze abrufen')
|
||
|
||
// Der Knopf steht über der Tabelle, nicht in einer ihrer Zeilen.
|
||
const knopf = await form.boundingBox()
|
||
const tabelle = await page.locator('table.liste').first().boundingBox()
|
||
expect(knopf.y).toBeLessThan(tabelle.y)
|
||
})
|
||
|
||
test('Ein PayPal-Zugang kennt kein TAN-Verfahren', async ({ page }) => {
|
||
const name = `E2E PayPal ohne TAN ${MARKE}`
|
||
|
||
await page.goto('/banking/neu/paypal')
|
||
await page.fill('#name', name)
|
||
await page.fill('#api_benutzer', 'e2e_api1.example.org')
|
||
await page.fill('#api_kennwort', 'e2e-kennwort')
|
||
await page.fill('#api_signatur', 'e2e-signatur')
|
||
await page.click('.formular button[type="submit"]')
|
||
await expect(page).toHaveURL(/\/banking$/)
|
||
|
||
const ziel = await page
|
||
.locator('table.liste tr', { hasText: name })
|
||
.locator('a')
|
||
.first()
|
||
.getAttribute('href')
|
||
|
||
await page.goto(`${ziel}/verfahren`)
|
||
|
||
await expect(page.locator('.meldung-warnung')).toContainText('kein TAN-Verfahren')
|
||
await expect(page).toHaveURL(new RegExp(`${ziel}$`))
|
||
})
|
||
})
|