// spec: e2e/plans/chore-scheduler.plan.md — Section 6: Child Mode Chore Visibility & States import { test, expect } from '@playwright/test' import { createChild, createChoreTask, assignChore, setDaysSchedule, choreCard, choreSection, todayDayIndex, nonTodayDayIndex, goToChildView, } from './helpers' const CHILD_NAME = 'ChildCardChild' const CHILD_ALWAYS = 'ChildAlwaysChore' const CHILD_TODAY = 'ChildTodayChore' const CHILD_NOT_TODAY = 'ChildNotTodayChore' const CHILD_EXPIRED = 'ChildExpiredChore' const CHILD_ANYTIME = 'ChildAnytimeChore' test.describe('Child Mode — Chore Visibility and Schedule States', () => { test.describe.configure({ mode: 'serial' }) let childId = '' let alwaysId = '' let todayId = '' let notTodayId = '' let expiredId = '' let anytimeId = '' test.beforeAll(async ({ request }) => { childId = await createChild(request, CHILD_NAME) alwaysId = await createChoreTask(request, CHILD_ALWAYS) todayId = await createChoreTask(request, CHILD_TODAY) notTodayId = await createChoreTask(request, CHILD_NOT_TODAY) expiredId = await createChoreTask(request, CHILD_EXPIRED) anytimeId = await createChoreTask(request, CHILD_ANYTIME) await assignChore(request, childId, [alwaysId, todayId, notTodayId, expiredId, anytimeId]) const today = todayDayIndex() const nonToday = nonTodayDayIndex() // ChildTodayChore: scheduled for today, deadline 23:59 await setDaysSchedule(request, childId, todayId, [today], { hour: 23, minute: 59 }) // ChildNotTodayChore: scheduled for a non-today day await setDaysSchedule(request, childId, notTodayId, [nonToday], { hour: 8, minute: 0 }) // ChildExpiredChore: scheduled for today, deadline 00:01 (guaranteed expired) await setDaysSchedule(request, childId, expiredId, [today], { hour: 0, minute: 1 }) // ChildAnytimeChore: scheduled for today, no deadline await setDaysSchedule(request, childId, anytimeId, [today], { hasDeadline: false }) // ChildAlwaysChore: no schedule }) test.afterAll(async ({ request }) => { if (childId) await request.delete(`/api/child/${childId}`) for (const id of [alwaysId, todayId, notTodayId, expiredId, anytimeId]) { if (id) await request.delete(`/api/task/${id}`) } }) test('6.1 Chore with no schedule — visible normally in child mode', async ({ page }) => { await goToChildView(page, childId) const card = choreCard(page, CHILD_ALWAYS) await expect(card).toBeVisible() await expect(card).not.toHaveClass(/chore-inactive/) }) test('6.2 Chore scheduled for today — visible with "Due by" label', async ({ page }) => { await goToChildView(page, childId) const card = choreCard(page, CHILD_TODAY) await expect(card).toBeVisible() await expect(card).not.toHaveClass(/chore-inactive/) await expect(card.locator('.due-label')).toHaveText('Due by 11:59 PM') }) test('6.3 Chore not scheduled for today — HIDDEN in child mode', async ({ page }) => { await goToChildView(page, childId) // Wait for the chores section to fully load (uses other cards as anchor) const alwaysCard = choreCard(page, CHILD_ALWAYS) await expect(alwaysCard).toBeVisible() // Off-day chore must not appear at all await expect( choreSection(page).locator('.item-card').filter({ hasText: CHILD_NOT_TODAY }), ).toHaveCount(0) }) test('6.4 Chore with expired deadline — grayed out with TOO LATE badge (not hidden)', async ({ page, }) => { await goToChildView(page, childId) const card = choreCard(page, CHILD_EXPIRED) // Expired chore is still visible (was scheduled for today) await expect(card).toBeVisible() await expect(card).toHaveClass(/chore-inactive/) await expect(card.getByText('TOO LATE')).toBeVisible() }) test('6.5 Chore with "Anytime" — visible, no badge, no "Due by"', async ({ page }) => { await goToChildView(page, childId) const card = choreCard(page, CHILD_ANYTIME) await expect(card).toBeVisible() await expect(card).not.toHaveClass(/chore-inactive/) await expect(card.locator('.due-label')).not.toBeVisible() await expect(card.getByText('TOO LATE')).not.toBeVisible() }) test('6.6 No kebab menu or schedule controls in child mode', async ({ page }) => { await goToChildView(page, childId) const card = choreCard(page, CHILD_TODAY) await expect(card).toBeVisible() // Click the card — no Options button should appear await card.click() await page.waitForTimeout(500) await expect(card.getByRole('button', { name: 'Options' })).not.toBeVisible() await expect(page.getByRole('button', { name: 'Schedule' })).not.toBeVisible() }) })