import { test, expect, type APIRequestContext } from '@playwright/test' const CHILD_NAME = 'RoutineNotifChild' const ROUTINE_NAME = 'RoutineNotifTest' const ROUTINE_POINTS = 8 // ── helpers ─────────────────────────────────────────────────────────────────── async function createChild(request: APIRequestContext, name: string): Promise { const pre = await request.get('/api/child/list') for (const c of (await pre.json()).children ?? []) { if (c.name === name) await request.delete(`/api/child/${c.id}`) } await request.put('/api/child/add', { data: { name, age: 8 } }) const list = await request.get('/api/child/list') return (await list.json()).children?.find((c: any) => c.name === name)?.id ?? '' } async function createRoutine( request: APIRequestContext, name: string, points: number, ): Promise { const pre = await request.get('/api/routine/list') for (const r of (await pre.json()).routines ?? []) { if (r.name === name) await request.delete(`/api/routine/${r.id}`) } const res = await request.put('/api/routine/add', { data: { name, points } }) return (await res.json()).routine?.id ?? '' } // ── suite ───────────────────────────────────────────────────────────────────── test.describe('Routine parent notification', () => { test.describe.configure({ mode: 'serial' }) let childId = '' let routineId = '' test.beforeAll(async ({ request }) => { childId = await createChild(request, CHILD_NAME) routineId = await createRoutine(request, ROUTINE_NAME, ROUTINE_POINTS) await request.post(`/api/child/${childId}/assign-routine`, { data: { routine_id: routineId }, }) // Simulate the child confirming the routine await request.post(`/api/child/${childId}/confirm-routine`, { data: { routine_id: routineId }, }) }) test.afterAll(async ({ request }) => { if (childId) await request.delete(`/api/child/${childId}`) if (routineId) await request.delete(`/api/routine/${routineId}`) }) // ── 1. Notification appears ─────────────────────────────────────────────── test('Confirmed routine appears in notification view', async ({ page }) => { await page.goto('/parent/notifications') const item = page.locator('.list-item').filter({ hasText: ROUTINE_NAME }) await expect(item).toBeVisible({ timeout: 5000 }) }) // ── 2. Notification shows "completed" ──────────────────────────────────── test('Notification shows "completed" for routine', async ({ page }) => { await page.goto('/parent/notifications') const item = page.locator('.list-item').filter({ hasText: ROUTINE_NAME }) await expect(item).toBeVisible({ timeout: 5000 }) await expect(item).toContainText('completed') }) // ── 3. Notification shows child name ───────────────────────────────────── test('Notification shows the child name', async ({ page }) => { await page.goto('/parent/notifications') const item = page.locator('.list-item').filter({ hasText: ROUTINE_NAME }) await expect(item).toBeVisible({ timeout: 5000 }) await expect(item).toContainText(CHILD_NAME) }) // ── 4. Clicking notification navigates to parent view ──────────────────── test('Clicking notification navigates to parent view for the child', async ({ page }) => { await page.goto('/parent/notifications') const item = page.locator('.list-item').filter({ hasText: ROUTINE_NAME }) await expect(item).toBeVisible({ timeout: 5000 }) await item.click() await page.waitForURL(`/parent/${childId}**`, { timeout: 5000 }) const url = new URL(page.url()) expect(url.searchParams.get('scrollTo')).toBe(routineId) expect(url.searchParams.get('entityType')).toBe('routine') }) })