import { expect, test } from '@playwright/test' import { PrismaClient } from '@prisma/client' import { anmelden } from './hilfen' /** * Verweise über Aktengrenzen hinweg — gegen die echte Anwendung. * * Die Auswahllisten im Browser zeigen nur die eigene Akte. Darauf darf * sich der Server nicht verlassen: Wer das Formular verändert, schickt * jede beliebige Id. * * Genau das wird hier nachgestellt — nicht als nachgebauter Aufruf, * sondern indem dem echten Auswahlfeld ein Eintrag mit einer fremden Id * untergeschoben und das Formular ganz normal abgeschickt wird. Nur so * beweist der Test etwas: Er liefe rot, wenn die Prüfung fehlte. * * Solange nur eine betreute Person angelegt ist, wäre der Fehler * folgenlos. Er bliebe es nicht — ein fremder Name stünde im Briefkopf. */ const KENNUNG = 'Prüfhausen Fremdakte' async function mitDb(arbeit: (db: PrismaClient) => Promise): Promise { const db = new PrismaClient() try { return await arbeit(db) } finally { await db.$disconnect() } } async function aufraeumen(): Promise { await mitDb(async (db) => { await db.betreute.deleteMany({ where: { nachname: { contains: 'Fremdakte' } } }) }) } test.describe('Verweise auf eine fremde Akte', () => { test.beforeAll(async () => { await aufraeumen() }) test.afterAll(async () => { await aufraeumen() }) test('weist einen Kontakt aus einer anderen Akte ab', async ({ page }) => { // Zweite Akte mit einem Kontakt darin — der angemeldete Benutzer hat // auf sie keinen Zugriff. const fremderKontakt = await mitDb(async (db) => { const fremde = await db.betreute.create({ data: { vorname: 'Otto', nachname: `${KENNUNG} Fremdakte`, geburtsdatum: new Date(Date.UTC(1940, 0, 1)), }, }) const kontakt = await db.kontakt.create({ data: { betreuteId: fremde.id, name: `${KENNUNG} Fremder Sachbearbeiter`, rolle: 'SACHBEARBEITER_BEZIRK', }, }) return kontakt.id }) await anmelden(page) // Irgendeinen Vorgang der eigenen Akte öffnen. const vorgangId = await mitDb(async (db) => { const vorgang = await db.vorgang.findFirst({ where: { geloeschtAm: null, betreute: { vorname: 'Erika' } }, select: { id: true }, }) return vorgang?.id ?? '' }) test.skip(vorgangId === '', 'Kein Vorgang in der eigenen Akte.') await page.goto(`/vorgaenge/${vorgangId}`) const auswahl = page.locator('select[name="ansprechpartnerId"]') await auswahl.waitFor() // Dem echten Auswahlfeld die fremde Id unterschieben und ganz normal // abschicken — so, wie es ein verändertes Formular täte. await auswahl.evaluate((feld, id) => { const eintrag = document.createElement('option') eintrag.value = id eintrag.textContent = 'untergeschoben' ;(feld as HTMLSelectElement).append(eintrag) ;(feld as HTMLSelectElement).value = id }, fremderKontakt) await page.getByRole('button', { name: 'Speichern' }).click() // Der Server lehnt ab, mit einer Meldung, die den Grund nennt. // Grosszuegige Frist: Im Entwicklungsmodus wird die Server Action beim // ersten Aufruf uebersetzt, und das dauert laenger als die Vorgabe. await expect(page.getByText(/gehört nicht zu dieser betreuten Person/).first()).toBeVisible({ timeout: 45_000, }) // Und vor allem: Die Verknüpfung ist nicht entstanden. const verknuepft = await mitDb((db) => db.vorgang.count({ where: { ansprechpartnerId: fremderKontakt } }), ) expect(verknuepft).toBe(0) }) test('die Auswahlliste zeigt den fremden Kontakt gar nicht erst', async ({ page }) => { await anmelden(page) await page.goto('/vorgaenge') const inhalt = await page.locator('body').innerText() expect(inhalt).not.toContain('Fremder Sachbearbeiter') }) })