// @ts-check // Hotspot: Detailansichten hinter den Dashboard-Kacheln (Issue #167). // // Die Kachelzahlen sind Links auf /dashboard/buchungen/{gruppe}/{jahr}[/{monat}]. // Ob die verlinkte Liste tatsächlich auf den angezeigten Kachelwert summiert, // lässt sich nur am gerenderten Dashboard prüfen — die Summenlogik selbst deckt // tests/80_DashboardEuerAbgleichTest.php ab. // // Die Tests lesen ausschließlich; es werden keine Daten angelegt oder verändert. const { test, expect } = require('@playwright/test') const { gotoOk, parseMoney } = require('../helpers/app') /** Liest Kachelwert und Ziel-URL der Jahreszahl einer Kachel. */ async function kachel(page, ueberschrift) { const karte = page.locator('.stat-card', { hasText: ueberschrift }).first() await expect(karte, `Kachel "${ueberschrift}" nicht gefunden`).toHaveCount(1) const link = karte.locator('.stat-value a').first() return { wert: parseMoney(await link.textContent()), url: await link.getAttribute('href'), } } test.describe('Detailansichten der Dashboard-Kacheln', () => { for (const [ueberschrift, gruppe] of [ ['Umsatz', 'einnahmen'], ['Ausgaben', 'ausgaben'], ['Gewinn / Verlust', 'ergebnis'], ]) { test(`Kachel "${ueberschrift}" führt auf die Buchungen, die sie aufsummiert`, async ({ page }) => { await gotoOk(page, '/dashboard') const { wert, url } = await kachel(page, ueberschrift) expect(url).toContain(`/dashboard/buchungen/${gruppe}/`) expect(Number.isNaN(wert)).toBe(false) await gotoOk(page, url) // Ohne Buchungen im laufenden Jahr gibt es nichts zu vergleichen. const leer = await page.locator('text=Keine Buchungen in diesem Zeitraum.').count() if (leer > 0) { expect(wert).toBeCloseTo(0, 2) return } const summe = parseMoney(await page.locator('tfoot tr td').last().textContent()) expect(summe, `Listensumme weicht vom Kachelwert ab (${ueberschrift})`).toBeCloseTo(wert, 2) }) } test('Monatszahlen verlinken auf denselben Monat', async ({ page }) => { await gotoOk(page, '/dashboard') const karte = page.locator('.stat-card', { hasText: 'Umsatz' }).first() const monatsLinks = karte.locator('.stat-meta a') await expect(monatsLinks).toHaveCount(2) for (let i = 0; i < 2; i++) { const url = await monatsLinks.nth(i).getAttribute('href') // Vormonat und laufender Monat: /…/{jahr}/{monat} expect(url).toMatch(/\/dashboard\/buchungen\/einnahmen\/\d{4}\/\d{1,2}$/) const erwartet = parseMoney(await monatsLinks.nth(i).textContent()) await gotoOk(page, url) const leer = await page.locator('text=Keine Buchungen in diesem Zeitraum.').count() if (leer > 0) { expect(erwartet).toBeCloseTo(0, 2) } else { const summe = parseMoney(await page.locator('tfoot tr td').last().textContent()) expect(summe).toBeCloseTo(erwartet, 2) } await gotoOk(page, '/dashboard') } }) test('Unbekannte Gruppe führt zurück aufs Dashboard', async ({ page }) => { await page.goto('/dashboard/buchungen/unsinn/2026') expect(new URL(page.url()).pathname).toBe('/dashboard') await expect(page.locator('body')).toContainText('Unbekannte Auswertung.') }) test('Ungültiger Monat führt zurück aufs Dashboard', async ({ page }) => { await page.goto('/dashboard/buchungen/einnahmen/2026/13') expect(new URL(page.url()).pathname).toBe('/dashboard') await expect(page.locator('body')).toContainText('Ungültiger Monat.') }) })