/** * DEL-series: /settings → Delete account (Fase 10.5). * * The full "delete + re-login fails" path needs an ephemeral Keycloak user * because deleting a seed user would break every downstream suite that * assumes Ana/Borja/etc. exist. That round-trip is heavy and brittle; the * pgTAP suite (supabase/tests/013_delete_account.sql) already proves the * DB-side contract exhaustively (cascade, role auto-promote, P0003 guard). * * This suite focuses on the UI contract that the pgTAP can't observe: * * the button is only enabled when the user types the exact word * ("DELETE") into the confirmation input * * the danger-zone block is visible on /settings * * Cleanup: no state changes, no afterAll needed. */ import { test, expect } from '@playwright/test'; import { USERS } from '../fixtures/users.js'; import { loginAs } from '../fixtures/login.js'; import { closePool } from '@colectivo/test-utils'; test.describe.configure({ mode: 'serial' }); test.describe('Account deletion UI (CU §6.3)', () => { test.afterAll(async () => { await closePool(); }); test('DEL-01: confirm button is disabled until the exact word is typed', async ({ page }) => { await loginAs(page, USERS.ana); await page.goto('/settings'); // Danger zone surface. const opener = page.getByTestId('delete-account-open'); await expect(opener).toBeVisible({ timeout: 15_000 }); await opener.click(); const confirm = page.getByTestId('confirm-delete-account'); const input = page.getByTestId('delete-account-confirm-input'); await expect(confirm).toBeDisabled(); await input.fill('delete'); // lowercase — must be case-sensitive await expect(confirm).toBeDisabled(); await input.fill('DELETE'); await expect(confirm).toBeEnabled(); }); });