feat: Implement user profile and parent profile button tests
All checks were successful
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 2m38s
All checks were successful
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 2m38s
- Added tests for user profile editing, including name changes, image uploads, and password changes. - Implemented tests for changing the parent PIN with verification code handling. - Created tests for account deletion with confirmation dialog and email validation. - Introduced parent profile button tests for both temporary and permanent modes, verifying badge visibility and menu options. - Updated Playwright configuration to include new test buckets for user profile and parent profile button scenarios. - Added e2e plans documentation for user profile and parent profile button tests.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
// 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/)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user