// spec: e2e/plans/user-profile.plan.md import { test, expect } from '@playwright/test' import { E2E_EMAIL, E2E_PASSWORD } from '../../e2e-constants' const BACKEND = 'http://localhost:5000' test.describe('User Profile – Delete Account', () => { test.describe.configure({ mode: 'serial' }) test.afterAll(async ({ request }) => { // Re-seed the e2e database to restore the test user for any subsequent test suites await request.post(`${BACKEND}/auth/e2e-seed`) }) test('Delete My Account opens confirmation dialog', async ({ page }) => { await page.goto('/parent/profile') await page.getByRole('button', { name: 'Delete My Account' }).click() await expect(page.locator('.modal-title', { hasText: 'Delete Your Account?' })).toBeVisible() await expect(page.locator('#confirmEmail')).toBeVisible() await expect(page.locator('#confirmEmail')).toHaveValue('') await expect( page.locator('.modal-dialog').getByRole('button', { name: 'Delete', exact: true }), ).toBeDisabled() await expect( page.locator('.modal-dialog').getByRole('button', { name: 'Cancel' }), ).toBeVisible() }) test('Delete button stays disabled for incomplete email', async ({ page }) => { await page.goto('/parent/profile') await page.getByRole('button', { name: 'Delete My Account' }).click() await expect(page.locator('.modal-title', { hasText: 'Delete Your Account?' })).toBeVisible() await page.locator('#confirmEmail').fill('e2e@') await expect( page.locator('.modal-dialog').getByRole('button', { name: 'Delete', exact: true }), ).toBeDisabled() }) test('Delete button enables when matching email is entered', async ({ page }) => { await page.goto('/parent/profile') await page.getByRole('button', { name: 'Delete My Account' }).click() await expect(page.locator('.modal-title', { hasText: 'Delete Your Account?' })).toBeVisible() await page.locator('#confirmEmail').fill(E2E_EMAIL) await expect( page.locator('.modal-dialog').getByRole('button', { name: 'Delete', exact: true }), ).toBeEnabled() }) test('Cancel closes the dialog without deleting the account', async ({ page }) => { await page.goto('/parent/profile') await page.getByRole('button', { name: 'Delete My Account' }).click() await expect(page.locator('.modal-title', { hasText: 'Delete Your Account?' })).toBeVisible() await page.locator('.modal-dialog').getByRole('button', { name: 'Cancel' }).click() // Dialog is gone, still on profile page await expect( page.locator('.modal-title', { hasText: 'Delete Your Account?' }), ).not.toBeVisible() await expect(page.getByRole('heading', { name: 'User Profile' })).toBeVisible() await expect(page).toHaveURL(/\/parent\/profile/) }) test('Backdrop click does NOT close the delete dialog', async ({ page }) => { await page.goto('/parent/profile') await page.getByRole('button', { name: 'Delete My Account' }).click() await expect(page.locator('.modal-title', { hasText: 'Delete Your Account?' })).toBeVisible() // Click the backdrop (outside the modal-dialog box) await page.locator('.modal-backdrop').click({ position: { x: 10, y: 10 }, force: true }) // Dialog must still be visible – the delete warning has no backdrop-click listener await expect(page.locator('.modal-title', { hasText: 'Delete Your Account?' })).toBeVisible() }) test('Successful deletion: confirmation modal appears then redirects to landing page', async ({ page, }) => { await page.goto('/parent/profile') await page.getByRole('button', { name: 'Delete My Account' }).click() await expect(page.locator('.modal-title', { hasText: 'Delete Your Account?' })).toBeVisible() await page.locator('#confirmEmail').fill(E2E_EMAIL) await page.locator('.modal-dialog').getByRole('button', { name: 'Delete', exact: true }).click() // Confirmation modal appears await expect(page.locator('.modal-title', { hasText: 'Account Deleted' })).toBeVisible() await expect(page.getByText(/marked for deletion/i)).toBeVisible() await page.getByRole('button', { name: 'OK' }).click() // Redirect to landing page await expect(page).toHaveURL('/') await expect(page.getByRole('button', { name: 'Sign In' }).first()).toBeVisible() }) test('Login after deletion is blocked with an appropriate error', async ({ page }) => { await page.goto('/auth/login') await page.getByLabel('Email address').fill(E2E_EMAIL) await page.getByLabel('Password').fill(E2E_PASSWORD) await page.getByRole('button', { name: 'Sign in' }).click() // Login must fail with a deletion-related error message await expect(page.getByText(/marked for deletion/i)).toBeVisible({ timeout: 8000 }) // URL stays on the login page await expect(page).toHaveURL(/\/auth\/login/) }) })