/** * Cohorts (Phase 1 PR 2) — smoke + happy-path coverage. * * Exercises the /admin/cohorts surface end-to-end: * 1. List page mounts (admin) * 2. Create new cohort via /admin/cohorts/new * 3. Detail page shows tabs + counts * 4. Add a student (modal pick) and verify the count increments * 5. Link a class (modal pick) and verify it appears * 6. Unlink class (admin) * 7. Soft-delete the cohort via the list * 8. Read-only access: principal sees the list but no New / Add buttons * 9. RBAC: teacher is denied 403 on the list API * * Skips cleanly if the demo seed lacks the principal user (the seed is * still being filled in). The smoke tests run against a fresh * `npm run db:init` so a clean state is assumed (no leftover cohorts). */ import { test, expect, request as pwRequest } from '@playwright/test'; import { loginAs, isRoleAvailable, apiLogin, DEMO_ACCOUNTS } from './helpers/auth'; import { captureConsoleErrors, expectNoConsoleErrors, expectPageMounted } from './helpers/assertions'; const BASE = 'http://localhost:3000'; const API = 'http://localhost:3001'; test.describe('Cohorts — admin happy path @flow', () => { test.beforeEach(async ({ page }) => { await loginAs(page, 'school_admin'); }); test('list page mounts and renders header', async ({ page }) => { const cap = captureConsoleErrors(page); try { await page.goto(`${BASE}/admin/cohorts`); await expectPageMounted(page, '/admin/cohorts', ['Student Cohorts']); } finally { cap.dispose(); expectNoConsoleErrors(cap.errors); } }); test('create new cohort end-to-end via the form', async ({ page }) => { const cap = captureConsoleErrors(page); try { const cohortName = `E2E Cohort ${Date.now()}`; await page.goto(`${BASE}/admin/cohorts/new`); // Fill the form. The label is "Name"; the programme select is // the first