// spec: frontend/vue-app/e2e/plans/parent-item-management.plan.md // seed: e2e/seed.spec.ts import { test, expect } from '@playwright/test' test.describe('Kindness act management', () => { test.beforeEach(async ({ page }, testInfo) => { test.skip(testInfo.project.name === 'chromium-no-pin', 'Requires parent-authenticated mode') }) // avoid parallel execution within this file; shared backend state and SSE events test.describe.configure({ mode: 'serial' }) test('Create a new kindness act (parent mode)', async ({ page }) => { // use a unique name so repeated runs don't collide const suffix = Date.now() const name = `Share toys ${suffix}` // 1. navigate once and switch to kindness tab await page.goto('/parent/tasks/chores') await page.click('text=Kindness Acts') await expect(page.locator('text=Kindness Acts')).toBeVisible() // 2. open form await page.getByRole('button', { name: 'Create Kindness Act' }).click() await expect(page.locator('text=Name')).toBeVisible() // 3‑4. fill using evaluate helper await page.evaluate((name) => { const setVal = (sel, val) => { const el = document.querySelector(sel) if (el) { el.value = val el.dispatchEvent(new Event('input', { bubbles: true })) el.dispatchEvent(new Event('change', { bubbles: true })) } } setVal('#name', name) setVal('#points', '5') }, name) await expect(page.getByRole('button', { name: 'Create' })).toBeEnabled() // 5. submit and assert the new row is visible await page.getByRole('button', { name: 'Create' }).click() await expect(page.locator('.error')).toHaveCount(0) await expect(page.locator(`text=${name}`).first()).toBeVisible() }) test('Edit an existing kindness act', async ({ page }) => { const suffix = Date.now() const original = `Share toys ${suffix}` const updated = `Help with homework ${suffix}` // navigate and create fresh item await page.goto('/parent/tasks/chores') await page.click('text=Kindness Acts') await page.getByRole('button', { name: 'Create Kindness Act' }).click() await page.evaluate((name) => { const setVal = (sel, val) => { const el = document.querySelector(sel) if (el) { el.value = val el.dispatchEvent(new Event('input', { bubbles: true })) el.dispatchEvent(new Event('change', { bubbles: true })) } } setVal('#name', name) setVal('#points', '5') }, original) await page.getByRole('button', { name: 'Create' }).click() await expect(page.locator(`text=${original}`).first()).toBeVisible() // 2. open edit by clicking first matching row await page.locator(`text=${original}`).first().click() // wait for edit form to appear await expect(page.locator('text=Name')).toBeVisible() await expect(page.getByRole('button', { name: 'Save' })).toBeVisible() // 3. update values once form is ready await page.evaluate((name) => { const setVal = (sel, val) => { const el = document.querySelector(sel) if (el) { el.value = val el.dispatchEvent(new Event('input', { bubbles: true })) el.dispatchEvent(new Event('change', { bubbles: true })) } } setVal('#name', name) setVal('#points', '8') }, updated) // 4. save and verify (wait until button is enabled) await expect(page.getByRole('button', { name: 'Save' })).toBeEnabled() await page.getByRole('button', { name: 'Save' }).click() await expect(page.locator(`text=${updated}`).first()).toBeVisible() }) test('Delete a kindness act', async ({ page }) => { const suffix = Date.now() const name = `Help with homework ${suffix}` await page.goto('/parent/tasks/chores') await page.click('text=Kindness Acts') // create fresh item await page.getByRole('button', { name: 'Create Kindness Act' }).click() await page.evaluate((name) => { const setVal = (sel, val) => { const el = document.querySelector(sel) if (el) { el.value = val el.dispatchEvent(new Event('input', { bubbles: true })) el.dispatchEvent(new Event('change', { bubbles: true })) } } setVal('#name', name) setVal('#points', '8') }, name) await page.getByRole('button', { name: 'Create' }).click() await expect(page.locator(`text=${name}`).first()).toBeVisible() // click the delete button on the first matching row await page .locator(`text=${name}`) .first() .locator('..') .getByRole('button', { name: 'Delete' }) .click() // confirmation modal should appear await expect( page.locator('text=Are you sure you want to delete this kindness act?'), ).toBeVisible() // click the red danger button inside the modal await page.locator('button.btn-danger:has-text("Delete")').click() await expect(page.locator(`text=${name}`)).toHaveCount(0) }) })