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.
122 lines
4.3 KiB
TypeScript
122 lines
4.3 KiB
TypeScript
// spec: e2e/plans/chore-scheduler.plan.md — Section 8: Extend Time
|
|
|
|
import { test, expect } from '@playwright/test'
|
|
import {
|
|
createChild,
|
|
createChoreTask,
|
|
assignChore,
|
|
setDaysSchedule,
|
|
choreCard,
|
|
openChoreOptions,
|
|
todayDayIndex,
|
|
todayISO,
|
|
goToChildView,
|
|
} from './helpers'
|
|
|
|
const CHILD_NAME = 'ExtendTimeChild'
|
|
const EXPIRED_NAME = 'ExtendTimeChore'
|
|
const FUTURE_NAME = 'FutureDeadlineChore'
|
|
|
|
test.describe('Extend Time', () => {
|
|
test.describe.configure({ mode: 'serial' })
|
|
|
|
let childId = ''
|
|
let expiredId = ''
|
|
let futureId = ''
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
childId = await createChild(request, CHILD_NAME)
|
|
expiredId = await createChoreTask(request, EXPIRED_NAME)
|
|
futureId = await createChoreTask(request, FUTURE_NAME)
|
|
|
|
await assignChore(request, childId, [expiredId, futureId])
|
|
|
|
const today = todayDayIndex()
|
|
|
|
// ExpiredChore: scheduled for today, deadline at 00:01 (guaranteed past)
|
|
await setDaysSchedule(request, childId, expiredId, [today], { hour: 0, minute: 1 })
|
|
|
|
// FutureChore: scheduled for today, deadline at 23:59 (not expired)
|
|
await setDaysSchedule(request, childId, futureId, [today], { hour: 23, minute: 59 })
|
|
})
|
|
|
|
test.afterAll(async ({ request }) => {
|
|
if (childId) await request.delete(`/api/child/${childId}`)
|
|
if (expiredId) await request.delete(`/api/task/${expiredId}`)
|
|
if (futureId) await request.delete(`/api/task/${futureId}`)
|
|
})
|
|
|
|
test('8.1 "Extend Time" appears in kebab menu only when chore is expired', async ({ page }) => {
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, EXPIRED_NAME)
|
|
await card.waitFor()
|
|
|
|
// Expired chore shows TOO LATE badge
|
|
await expect(card.getByText('TOO LATE')).toBeVisible()
|
|
|
|
await openChoreOptions(page, card)
|
|
await expect(page.getByRole('button', { name: 'Extend Time' })).toBeVisible()
|
|
})
|
|
|
|
test('8.2 "Extend Time" is absent when chore is not expired', async ({ page }) => {
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, FUTURE_NAME)
|
|
await card.waitFor()
|
|
|
|
await openChoreOptions(page, card)
|
|
await expect(page.getByRole('button', { name: 'Extend Time' })).not.toBeVisible()
|
|
})
|
|
|
|
test('8.3 Clicking "Extend Time" removes the TOO LATE badge', async ({ page }) => {
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, EXPIRED_NAME)
|
|
await card.waitFor()
|
|
await expect(card.getByText('TOO LATE')).toBeVisible()
|
|
|
|
await openChoreOptions(page, card)
|
|
await page.getByRole('button', { name: 'Extend Time' }).click()
|
|
|
|
// After extension the badge disappears and card is no longer grayed out
|
|
await expect(card.getByText('TOO LATE')).not.toBeVisible()
|
|
await expect(card).not.toHaveClass(/chore-inactive/)
|
|
})
|
|
|
|
test('8.4 Extended chore no longer shows "Due by" label', async ({ page }) => {
|
|
// Card was extended in 8.3 so this verifies the extension persists
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, EXPIRED_NAME)
|
|
await card.waitFor()
|
|
|
|
await expect(card.getByText('TOO LATE')).not.toBeVisible()
|
|
await expect(card.locator('.due-label')).not.toBeVisible()
|
|
})
|
|
|
|
test('8.5 "Extend Time" disappears from kebab after extension', async ({ page }) => {
|
|
await page.goto(`/parent/${childId}`)
|
|
const card = choreCard(page, EXPIRED_NAME)
|
|
await card.waitFor()
|
|
|
|
// Chore was extended in 8.3 — should no longer be expired
|
|
await openChoreOptions(page, card)
|
|
await expect(page.getByRole('button', { name: 'Extend Time' })).not.toBeVisible()
|
|
})
|
|
|
|
test('8.6 Extension effect visible in child mode', async ({ page }) => {
|
|
// After extending in parent mode (done in 8.3), verify child view
|
|
await goToChildView(page, childId)
|
|
const card = choreCard(page, EXPIRED_NAME)
|
|
|
|
// Chore is still visible (was scheduled for today + extended) and no TOO LATE badge
|
|
await expect(card).toBeVisible()
|
|
await expect(card.getByText('TOO LATE')).not.toBeVisible()
|
|
})
|
|
|
|
test('8.6b Extending same chore twice via API returns 409', async ({ request }) => {
|
|
// The chore was already extended in 8.3; a second API extension should fail
|
|
const res = await request.post(`/api/child/${childId}/task/${expiredId}/extend`, {
|
|
data: { date: todayISO() },
|
|
})
|
|
expect(res.status()).toBe(409)
|
|
})
|
|
})
|