Finanzmanager/tests/e2e/specs/bargeld.spec.js
fds2610-bot 5491bb69f6 Fix #62: E2E-Tests an den Typeahead im Kontoblatt angepasst
Zwölf Tests standen auf Rot, ohne dass die Anwendung etwas falsch machte – die
Specs prüften den Stand vor dem Umbau. Vier Ursachen lagen darunter:

Die Kombobox lässt ihr <select> zwar im Formular stehen, setzt es aber auf
hidden; selectOption() wartet darauf vergeblich. Der neue Helfer
tests/e2e/specs/hilfen.js bedient das Eingabefeld, tippt die Beschriftung ein
und klickt den genau passenden Treffer an – exakt, weil [Depot] sonst auch das
[Depot] … des Wertpapiergeschäfts träfe.

Seit dem Schnellspeichern ohne Neuladen stehen zwei Erfolgsmeldungen
übereinander; gemeint ist die neue, also .last().

Die Adressliste ist seit der Adressverwaltung eine Bearbeitungstabelle: Die
Namen stehen in Eingabefeldern, wo toContainText nicht hinsieht. Geprüft wird
jetzt der Feldwert – gespeichert wurde die Adresse die ganze Zeit korrekt.

Die beiden übrigen Fehlschläge waren Folgefehler: Playwright startet nach jedem
Fehlschlag einen frischen Worker, das Spec-Modul wird neu geladen, seine Marke
neu gezogen und beforeAll legt leere Konten an. Sie brauchten keine Änderung.

87 Tests grün, und ohne die Timeouts in 2,7 statt 7,1 Minuten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQ57wQWZ4xKHcKmp26bzgr
2026-09-04 12:39:29 +02:00

182 lines
7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @ts-check
const { test, expect } = require('@playwright/test')
const { komboboxWaehlen } = require('./hilfen')
/*
* Der Abgleich mit dem Bargeld-Tool im Browser: die Kachel in der Verwaltung,
* das Formular dahinter und die Wirkung im Kontoblatt.
*
* Als Gegenstelle dient eine Adresse, die es nicht gibt. Das genügt: Der Abruf
* selbst steckt in der PHP-Suite, wo ein Testserver antwortet – hier geht es um
* den Weg und darum, dass ein gescheiterter Abruf die Zuordnung nicht aufhält.
*/
const BENUTZER = process.env.E2E_USER || 'e2e'
const PASSWORT = process.env.E2E_PASSWORD || 'e2e-testpasswort'
const MARKE = Date.now().toString().slice(-6)
const GIRO = `E2E Bargeld Giro ${MARKE}`
const KATEGORIE = `E2E Bargeld Haushalt ${MARKE}`
const ADRESSE = 'https://kasse.beispiel.invalid'
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(/\/$/)
}
/** Adresse und Kategorienauswahl zurücksetzen – die Instanz gehört nicht dem Test. */
async function zuruecksetzen(page) {
await page.goto('/verwaltung/bargeld')
await page.fill('#bargeld_url', '')
for (const feld of await page.locator('input[name="kategorien[]"]:checked').all()) {
await feld.uncheck()
}
await page.getByRole('button', { name: 'Speichern' }).click()
await expect(page.locator('.meldung')).toContainText('gespeichert')
}
test.describe('Bargeld-Tool', () => {
let giroId = null
test.beforeAll(async ({ browser }) => {
const page = await browser.newPage()
await anmelden(page)
await page.goto('/konten/neu')
await page.fill('#name', GIRO)
await page.selectOption('#kontoart', 'bank')
await page.fill('#anfangssaldo', '1.000,00')
await page.click('.formular button[type="submit"]')
await expect(page).toHaveURL(/\/konten\/\d+\/bearbeiten/)
const treffer = page.url().match(/\/konten\/(\d+)\//)
giroId = treffer ? treffer[1] : null
await page.goto('/verwaltung/kategorien/neu')
await page.fill('#name', KATEGORIE)
await page.selectOption('#art', 'ausgabe')
await page.click('.formular button[type="submit"]')
await page.close()
})
test.beforeEach(async ({ page }) => {
await anmelden(page)
})
test.afterEach(async ({ page }) => {
await zuruecksetzen(page)
})
test('Die Verwaltung führt zur Konfiguration', async ({ page }) => {
await page.goto('/verwaltung')
const kachel = page.locator('.kachel', { hasText: 'Bargeld-Tool' })
await kachel.getByRole('link', { name: /einrichten/ }).click()
await expect(page).toHaveURL(/\/verwaltung\/bargeld$/)
await expect(page.locator('h1')).toContainText('Bargeld-Tool')
await expect(page.locator('#bargeld_url')).toBeVisible()
await expect(page.locator('#bargeld_benutzer')).toBeVisible()
await expect(page.locator('#bargeld_passwort')).toHaveAttribute('type', 'password')
await expect(page.getByRole('checkbox', { name: KATEGORIE })).not.toBeChecked()
})
test('Eine Adresse ohne Schema wird abgewiesen', async ({ page }) => {
await page.goto('/verwaltung/bargeld')
await page.fill('#bargeld_url', 'kasse.beispiel.invalid')
await page.getByRole('button', { name: 'Speichern' }).click()
await expect(page.locator('.meldung')).toContainText('http://')
await expect(page.locator('#bargeld_url')).toHaveValue('')
})
test('Der Verbindungstest meldet eine unerreichbare Gegenstelle', async ({ page }) => {
await page.goto('/verwaltung/bargeld')
await page.fill('#bargeld_url', ADRESSE)
await page.getByRole('button', { name: 'Speichern' }).click()
await expect(page.locator('.meldung')).toContainText('gespeichert')
await page.getByRole('button', { name: 'Verbindung testen' }).click()
await expect(page.locator('.meldung-fehler')).toContainText('nicht erreichbar')
})
test('Erst mit Adresse zeigt das Kontoblatt die Abgleichspalte', async ({ page }) => {
const empfaenger = `Ohne Bargeld ${MARKE}`
await page.goto(`/konten/${giroId}/buchung`)
await page.selectOption('#art', 'ausgabe')
await page.fill('#datum', '2026-04-03')
await page.fill('#betrag', '12,30')
await page.fill('#empfaenger', empfaenger)
await page.click('.buchungsmaske button[type="submit"]')
await expect(page.locator('.meldung-erfolg')).toBeVisible()
// Ohne Adresse gibt es die Spalte nicht – sie zeigte nur graue Kreise.
await expect(page.locator('th.bargeldspalte')).toHaveCount(0)
await page.goto('/verwaltung/bargeld')
await page.fill('#bargeld_url', ADRESSE)
await page.fill('#bargeld_tage', '10')
await page.getByRole('button', { name: 'Speichern' }).click()
await expect(page.locator('.meldung')).toContainText('gespeichert')
await page.goto(`/konten/${giroId}`)
await expect(page.locator('th.bargeldspalte')).toHaveCount(1)
// Die Spalte steht zwischen Klasse und Betrag.
const spalten = await page.locator('table.kontoblatt thead th').allTextContents()
expect(spalten.indexOf('Bar')).toBe(spalten.indexOf('Klasse') + 1)
expect(spalten.indexOf('Betrag')).toBe(spalten.indexOf('Bar') + 1)
// Ohne vorgemerkte Kategorie steht dort der graue Kreis.
const zeile = page.locator('tr', { hasText: empfaenger })
await expect(zeile.locator('td.bargeldspalte .bargeld-neutral')).toBeVisible()
})
test('Eine vorgemerkte Kategorie wird beim Zuordnen geprüft', async ({ page }) => {
// Der Abruf läuft ins Leere; genau das soll das Ausrufezeichen zeigen –
// und die Zuordnung muss trotzdem stehen.
test.setTimeout(60_000)
const empfaenger = `Bargeldabhebung ${MARKE}`
await page.goto('/verwaltung/bargeld')
await page.fill('#bargeld_url', ADRESSE)
await page.getByRole('checkbox', { name: KATEGORIE }).check()
await page.getByRole('button', { name: 'Speichern' }).click()
await expect(page.locator('.meldung')).toContainText('gespeichert')
await page.goto(`/konten/${giroId}/buchung`)
await page.selectOption('#art', 'ausgabe')
await page.fill('#datum', '2026-04-04')
await page.fill('#betrag', '50,00')
await page.fill('#empfaenger', empfaenger)
await page.click('.buchungsmaske button[type="submit"]')
await expect(page.locator('.meldung-erfolg')).toBeVisible()
const zeile = page.locator('tr', { hasText: empfaenger })
await zeile.locator('a.zuordnungsfeld').click()
await komboboxWaehlen(zeile.locator('#zuordnungsauswahl select'), KATEGORIE)
// Die Zuordnung steht, der gescheiterte Abruf hat sie nicht aufgehalten.
// Über der Meldung steht noch die des Anlegens – gemeint ist die neue.
await expect(page.locator('.meldung-erfolg').last()).toContainText('Zuordnung gespeichert')
await expect(page.locator('.meldung-erfolg').last()).toContainText('fehlgeschlagen')
const danach = page.locator('tr', { hasText: empfaenger })
await expect(danach).toContainText(KATEGORIE)
await expect(danach.locator('td.bargeldspalte .bargeld-fehler')).toBeVisible()
})
})