Refactored frontend directory
Some checks failed
Chore App Build, Test, and Push Docker Images / build-and-push (push) Failing after 2m46s
Some checks failed
Chore App Build, Test, and Push Docker Images / build-and-push (push) Failing after 2m46s
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
// spec: e2e/plans/chore-scheduler.plan.md — Section 4: Schedule Enable/Disable Toggle
|
||||
|
||||
import { test, expect } from '@playwright/test'
|
||||
import {
|
||||
createChild,
|
||||
createChoreTask,
|
||||
assignChore,
|
||||
deleteSchedule,
|
||||
setDaysSchedule,
|
||||
choreCard,
|
||||
openScheduleModal,
|
||||
todayDayIndex,
|
||||
nonTodayDayIndex,
|
||||
goToChildView,
|
||||
} from './helpers'
|
||||
|
||||
const CHILD_NAME = 'ScheduleToggleChild'
|
||||
const CHORE_NAME = 'ScheduleToggleChore'
|
||||
|
||||
test.describe('Schedule Enable/Disable Toggle', () => {
|
||||
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('4.1 Toggle row is visible in the schedule modal', async ({ page, request }) => {
|
||||
// Seed a schedule so the modal has something to show
|
||||
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()])
|
||||
|
||||
await page.goto(`/parent/${childId}`)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
await card.waitFor()
|
||||
await openScheduleModal(page, card)
|
||||
|
||||
await expect(page.locator('.schedule-toggle-row')).toBeVisible()
|
||||
await expect(page.getByRole('switch')).toBeVisible()
|
||||
await expect(page.locator('.toggle-label')).toBeVisible()
|
||||
})
|
||||
|
||||
test('4.2 Toggling OFF shows "Paused" label and dims the form body', async ({
|
||||
page,
|
||||
request,
|
||||
}) => {
|
||||
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()])
|
||||
|
||||
await page.goto(`/parent/${childId}`)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
await card.waitFor()
|
||||
await openScheduleModal(page, card)
|
||||
|
||||
// Toggle is ON initially
|
||||
await expect(page.getByRole('switch')).toHaveAttribute('aria-checked', 'true')
|
||||
|
||||
// Toggle OFF
|
||||
await page.getByRole('switch').click()
|
||||
await expect(page.getByRole('switch')).toHaveAttribute('aria-checked', 'false')
|
||||
await expect(page.locator('.toggle-label')).toHaveText('Paused')
|
||||
|
||||
// Form body dims
|
||||
await expect(page.locator('.schedule-body')).toHaveClass(/disabled/)
|
||||
|
||||
// Cancel/Save buttons remain interactive
|
||||
await expect(page.getByRole('button', { name: 'Cancel' })).toBeEnabled()
|
||||
})
|
||||
|
||||
test('4.3 Toggling ON restores "Enabled" label and form body', async ({ page, request }) => {
|
||||
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()])
|
||||
|
||||
await page.goto(`/parent/${childId}`)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
await card.waitFor()
|
||||
await openScheduleModal(page, card)
|
||||
|
||||
// Toggle OFF then back ON
|
||||
await page.getByRole('switch').click()
|
||||
await expect(page.locator('.toggle-label')).toHaveText('Paused')
|
||||
await page.getByRole('switch').click()
|
||||
|
||||
await expect(page.getByRole('switch')).toHaveAttribute('aria-checked', 'true')
|
||||
await expect(page.locator('.toggle-label')).toHaveText('Enabled')
|
||||
await expect(page.locator('.schedule-body')).not.toHaveClass(/disabled/)
|
||||
})
|
||||
|
||||
test('4.4 Save paused state — persists on reopen', async ({ page, request }) => {
|
||||
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()])
|
||||
|
||||
await page.goto(`/parent/${childId}`)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
await card.waitFor()
|
||||
await openScheduleModal(page, card)
|
||||
|
||||
// Toggle OFF and save
|
||||
await page.getByRole('switch').click()
|
||||
await expect(page.locator('.toggle-label')).toHaveText('Paused')
|
||||
await page.getByRole('button', { name: 'Save' }).click()
|
||||
await expect(page.locator('.modal-title')).not.toBeVisible()
|
||||
|
||||
// Navigate fresh to reset card ready-state, then reopen to verify
|
||||
await page.goto(`/parent/${childId}`)
|
||||
await card.waitFor()
|
||||
await openScheduleModal(page, card)
|
||||
await expect(page.getByRole('switch')).toHaveAttribute('aria-checked', 'false')
|
||||
await expect(page.locator('.toggle-label')).toHaveText('Paused')
|
||||
await expect(page.locator('.schedule-body')).toHaveClass(/disabled/)
|
||||
})
|
||||
|
||||
test('4.5 Dirty detection — toggling enabled state enables/disables Save', async ({
|
||||
page,
|
||||
request,
|
||||
}) => {
|
||||
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()])
|
||||
|
||||
await page.goto(`/parent/${childId}`)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
await card.waitFor()
|
||||
await openScheduleModal(page, card)
|
||||
|
||||
// Save is disabled initially
|
||||
await expect(page.getByRole('button', { name: 'Save' })).toBeDisabled()
|
||||
|
||||
// Toggle OFF → dirty
|
||||
await page.getByRole('switch').click()
|
||||
await expect(page.getByRole('button', { name: 'Save' })).toBeEnabled()
|
||||
|
||||
// Toggle back ON → not dirty again
|
||||
await page.getByRole('switch').click()
|
||||
await expect(page.getByRole('button', { name: 'Save' })).toBeDisabled()
|
||||
})
|
||||
|
||||
test('4.6 Paused schedule in parent mode — chore is visible and not grayed out', async ({
|
||||
page,
|
||||
request,
|
||||
}) => {
|
||||
// Schedule for a non-today weekday, but paused (enabled=false)
|
||||
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()], { enabled: false })
|
||||
|
||||
await page.goto(`/parent/${childId}`)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
await card.waitFor()
|
||||
|
||||
// Chore is visible
|
||||
await expect(card).toBeVisible()
|
||||
// Paused = acts like unscheduled = not grayed out
|
||||
await expect(card).not.toHaveClass(/chore-inactive/)
|
||||
})
|
||||
|
||||
test('4.7 Paused schedule in child mode — chore is visible', async ({ page, request }) => {
|
||||
// Non-today schedule, paused
|
||||
await setDaysSchedule(request, childId, choreId, [nonTodayDayIndex()], { enabled: false })
|
||||
|
||||
await goToChildView(page, childId)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
// Paused = isScheduledToday returns true → chore is visible in child mode
|
||||
await expect(card).toBeVisible()
|
||||
})
|
||||
|
||||
test('4.8 Paused schedule shows no "Due by" label', async ({ page, request }) => {
|
||||
// Schedule for today with a deadline, but paused
|
||||
await setDaysSchedule(request, childId, choreId, [todayDayIndex()], {
|
||||
hour: 23,
|
||||
minute: 59,
|
||||
enabled: false,
|
||||
})
|
||||
|
||||
await page.goto(`/parent/${childId}`)
|
||||
const card = choreCard(page, CHORE_NAME)
|
||||
await card.waitFor()
|
||||
|
||||
// Paused = getDueTimeToday returns null → no "Due by" label
|
||||
await expect(card.locator('.due-label')).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user