// @ts-check const { test, expect } = require('@playwright/test') /* * Vom Namen in der Depotübersicht zur Detailseite des Wertpapiers: Stammdaten, * Kennzahlen und darunter die Buchungen eines Zeitraums – voreingestellt das * laufende Jahr. */ const BENUTZER = process.env.E2E_USER || 'e2e' const PASSWORT = process.env.E2E_PASSWORD || 'e2e-testpasswort' const MARKE = Date.now().toString().slice(-6) const DEPOT = `E2E Detaildepot ${MARKE}` const GIRO = `E2E Detailgiro ${MARKE}` const PAPIER = `E2E Detailaktie ${MARKE}` // Wie im Test des Wertpapiergeschäfts: Ein Papier wird über seine Kennung // wiedergefunden, feste Kennungen hingen den zweiten Lauf an den ersten. const ISIN = `DE0007${MARKE}` // Die Zeiträume rechnen mit dem Tagesdatum, nicht mit festen Jahreszahlen – // sonst liefe der Test am 1. Januar ins Leere. const HEUTE = new Date() const JAHR = HEUTE.getFullYear() const DIESES_JAHR = `${JAHR}-03-04` const VORJAHR = `${JAHR - 1}-03-04` async function anmelden(page) { await page.goto('/login') if (page.url().includes('/einrichtung')) { throw new Error( 'Instanz ist noch nicht eingerichtet: ' + '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(/\/$/) } async function kontoAnlegen(page, name, kontoart, anfangssaldo) { await page.goto('/konten/neu') await page.fill('#name', name) await page.selectOption('#kontoart', kontoart) await page.fill('#anfangssaldo', anfangssaldo) await page.click('.formular button[type="submit"]') await expect(page).toHaveURL(/\/konten\/\d+\/bearbeiten/) } /** Ein Kauf über die Maske unter *Wertpapiere*. */ async function kaufErfassen(page, datum, stueck, kurs, neuesPapier) { await page.goto('/wertpapiere/buchungen/neu') await page.selectOption('#konto_id', { label: DEPOT }) await page.selectOption('#vorgang', 'kauf') await page.fill('#datum', datum) if (neuesPapier) { await page.fill('#wertpapier_name', PAPIER) await page.fill('#isin', ISIN) } else { await page.selectOption('#wertpapier_id', { label: `${PAPIER} (${ISIN})` }) } await page.fill('#stueck', stueck) await page.fill('#kurs', kurs) await page.selectOption('#verrechnungskonto_id', { label: GIRO }) await page.click('.formular button[type="submit"]') await expect(page.locator('.meldung-erfolg')).toBeVisible() } test.describe('Detailseite eines Wertpapiers', () => { test.beforeAll(async ({ browser }) => { const page = await browser.newPage() await anmelden(page) await kontoAnlegen(page, GIRO, 'bank', '10.000,00') await kontoAnlegen(page, DEPOT, 'depot', '0,00') // Zwei Käufe in zwei Jahren – der Zeitraumfilter muss sie trennen. await kaufErfassen(page, VORJAHR, '4', '50', true) await kaufErfassen(page, DIESES_JAHR, '6', '100', false) // Ohne Kurs bliebe die Bewertung offen; der Kurs kommt von Hand. Der // Name steht in der Stammdatenliste in einem Eingabefeld und nicht als // Text – die Zeile wird deshalb über den Feldwert gesucht. await page.goto('/wertpapiere/stammdaten') const zeile = page.locator('tr').filter({ has: page.locator(`input[value="${PAPIER}"]`) }) await zeile.locator('input[name="kurs"]').fill('120') await zeile.getByRole('button', { name: 'Setzen' }).click() await expect(page.locator('.meldung-erfolg')).toBeVisible() await page.close() }) test.beforeEach(async ({ page }) => { await anmelden(page) }) test('Der Name in der Übersicht führt zu den Details', async ({ page }) => { await page.goto('/wertpapiere') await page.locator('tr', { hasText: PAPIER }).getByRole('link', { name: PAPIER }).click() await expect(page).toHaveURL(/\/wertpapiere\/papier\/\d+/) await expect(page.locator('h1')).toHaveText(PAPIER) // Stammdaten und Kurs stehen in je einer Kachel. await expect(page.locator('.kachel', { hasText: 'Stammdaten' }).locator('.merkmale')) .toContainText(ISIN) await expect(page.locator('.kachel', { hasText: 'Letzter Kurs' }).locator('.merkmale')) .toContainText('120,00') // Zehn Stück für 800 €, bewertet mit 1.200,00 €. const kennzahlen = page.locator('.kennzahlenleiste') await expect(kennzahlen).toContainText('10') await expect(kennzahlen).toContainText('1.200,00') await expect(kennzahlen).toContainText('800,00') // Der Bestand steht je Depot – hier liegt alles in einem. const bestand = page.locator('.kachel', { hasText: 'Bestand je Depot' }) await expect(bestand).toContainText(DEPOT) await expect(bestand).toContainText('800,00') }) test('Die Buchungen folgen dem gewählten Zeitraum', async ({ page }) => { await page.goto('/wertpapiere') await page.locator('tr', { hasText: PAPIER }).getByRole('link', { name: PAPIER }).click() const liste = page.locator('table.liste').last() // Voreingestellt ist das laufende Jahr: nur der Kauf von diesem Jahr. await expect(page.locator('#zeitraum')).toHaveValue('aktuelles_jahr') await expect(liste).toContainText(`04.03.${JAHR}`) await expect(liste).not.toContainText(`04.03.${JAHR - 1}`) await page.selectOption('#zeitraum', 'letztes_jahr') await page.click('.filterleiste button[type="submit"]') await expect(page.locator('table.liste').last()).toContainText(`04.03.${JAHR - 1}`) await expect(page.locator('table.liste').last()).not.toContainText(`04.03.${JAHR}`) // Die Kennzahlen oben gelten weiter für die ganze Historie. await expect(page.locator('.kennzahlenleiste')).toContainText('800,00') }) })