All checks were successful
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 2m39s
- Introduced a toggle button to enable or disable chores in the scheduler. - The toggle will be available in both types of schedulers. - Added UI design proposal and considerations for mobile dimensions. - Included E2E tests to ensure toggle state persistence and correct behavior in child view.
98 lines
3.0 KiB
TypeScript
98 lines
3.0 KiB
TypeScript
// spec: e2e/plans/chore-scheduler.plan.md — Section 10: SSE Real-Time Updates
|
|
|
|
import { test, expect } from '@playwright/test'
|
|
import {
|
|
createChild,
|
|
createChoreTask,
|
|
assignChore,
|
|
setDaysSchedule,
|
|
deleteSchedule,
|
|
choreCard,
|
|
todayDayIndex,
|
|
nonTodayDayIndex,
|
|
todayISO,
|
|
} from './helpers'
|
|
|
|
const CHILD_NAME = 'SSEScheduleChild'
|
|
const CHORE_NAME = 'SSEScheduleChore'
|
|
|
|
test.describe('SSE Real-Time Updates', () => {
|
|
test.describe.configure({ mode: 'serial' })
|
|
|
|
let childId = ''
|
|
let choreId = ''
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
childId = await createChild(request, CHILD_NAME)
|
|
choreId = await createChoreTask(request, CHORE_NAME)
|
|
await assignChore(request, childId, [choreId])
|
|
})
|
|
|
|
test.afterAll(async ({ request }) => {
|
|
if (childId) await request.delete(`/api/child/${childId}`)
|
|
if (choreId) await request.delete(`/api/task/${choreId}`)
|
|
})
|
|
|
|
test.beforeEach(async ({ request }) => {
|
|
await deleteSchedule(request, childId, choreId)
|
|
})
|
|
|
|
test('10.1 Setting a schedule via API reflects in an already-open parent view', async ({
|
|
page,
|
|
request,
|
|
}) => {
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, CHORE_NAME)
|
|
await card.waitFor()
|
|
|
|
// No schedule: card should be visible and not grayed out
|
|
await expect(card).not.toHaveClass(/chore-inactive/)
|
|
|
|
// Set a non-today schedule via API (triggers SSE chore_schedule_modified)
|
|
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()], { hour: 8, minute: 0 })
|
|
|
|
// SSE fires → card should become grayed out (chore-inactive)
|
|
await expect(card).toHaveClass(/chore-inactive/, { timeout: 5000 })
|
|
})
|
|
|
|
test('10.2 Deleting a schedule via API un-grays the chore in parent view', async ({
|
|
page,
|
|
request,
|
|
}) => {
|
|
// Seed a non-today schedule first
|
|
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()], { hour: 8, minute: 0 })
|
|
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, CHORE_NAME)
|
|
await card.waitFor()
|
|
await expect(card).toHaveClass(/chore-inactive/)
|
|
|
|
// Delete schedule via API
|
|
await request.delete(`/api/child/${childId}/task/${choreId}/schedule`)
|
|
|
|
// SSE fires → card returns to normal
|
|
await expect(card).not.toHaveClass(/chore-inactive/, { timeout: 5000 })
|
|
})
|
|
|
|
test('10.3 Extending time via API reflects in an already-open parent view', async ({
|
|
page,
|
|
request,
|
|
}) => {
|
|
// Set today schedule with past deadline (chore starts expired)
|
|
await setDaysSchedule(request, childId, choreId, [todayDayIndex()], { hour: 0, minute: 1 })
|
|
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, CHORE_NAME)
|
|
await card.waitFor()
|
|
await expect(card.getByText('TOO LATE')).toBeVisible()
|
|
|
|
// Extend via API
|
|
await request.post(`/api/child/${childId}/task/${choreId}/extend`, {
|
|
data: { date: todayISO() },
|
|
})
|
|
|
|
// SSE chore_time_extended fires → TOO LATE badge disappears
|
|
await expect(card.getByText('TOO LATE')).not.toBeVisible({ timeout: 5000 })
|
|
})
|
|
})
|