## Task 6: Playwright Smoke Flow **Files:** - Modify: `apps/web/e2e/project-workbench.spec.ts` **Interfaces:** - Consumes: login form labels from Task 1. - Consumes: project/channel labels from Tasks 2-4. - Produces: smoke coverage for login, dynamic project switching, channel template switching, custom URL channel. - [ ] **Step 1: Replace Playwright smoke tests** Update `apps/web/e2e/project-workbench.spec.ts`: ```ts import { expect, test } from '@playwright/test'; test('login and project channel workbench flow', async ({ page }) => { await page.goto('/'); await expect(page.getByLabel('Server IP or domain')).toBeVisible(); await page.getByLabel('Server IP or domain').fill('localhost:8080'); await page.getByLabel('Email or username').fill('david@example.com'); await page.getByLabel('Password').fill('secret'); await page.getByRole('button', { name: 'Log in' }).click(); await expect(page.getByLabel('Project list')).toBeVisible(); await expect(page.getByRole('button', { name: 'Project A1' })).toHaveAttribute('aria-pressed', 'true'); await expect(page.getByRole('button', { name: 'Message Flow 36' })).toBeVisible(); await page.getByRole('button', { name: 'Work Plan 8' }).click(); await expect(page.getByText('Tasks')).toBeVisible(); await expect(page.getByRole('button', { name: 'Inspect Confirm homepage information architecture' })).toBeVisible(); await page.getByRole('button', { name: 'Project A2' }).click(); await expect(page.getByRole('button', { name: 'Project A2' })).toHaveAttribute('aria-pressed', 'true'); await expect(page.getByText('Ops Dashboard')).toBeVisible(); await page.getByRole('button', { name: 'Ops Dashboard' }).click(); await expect(page.getByText('Open external channel')).toBeVisible(); }); ``` - [ ] **Step 2: Run Playwright test** Run: ```powershell Set-Location D:\work\senlinai\agent\apps\web npx playwright test ``` Expected: PASS. - [ ] **Step 3: Run full web verification** Run: ```powershell Set-Location D:\work\senlinai\agent\apps\web npm test -- --run npm run build npx playwright test ``` Expected: all PASS. - [ ] **Step 4: Commit** Run: ```powershell Set-Location D:\work\senlinai\agent git add apps\web\e2e\project-workbench.spec.ts git commit -m "test: cover project channel workbench flow" ``` --- ## Self-Review Spec coverage: - Login page with server IP/domain, account, password, status, and errors: Task 1. - Dynamic project rail and project-scoped channel refresh: Tasks 2 and 3. - System channels with different page templates: Task 4. - Message flow similar to email: Task 4. - Work plan Todo card style with complete/incomplete state: Task 4. - AI sessions with session list and details: Task 4. - Notes and sources file/attachment management style: Task 4. - Cron plan/reminder management without autonomous Agent execution: Task 4 and Global Constraints. - Custom channel with title, icon, URL: Tasks 2 and 4. - Right inspector with Discussion, Properties, More: Task 4. - shadcn/ui-inspired visual system without React/shadcn dependency: Task 5. - Playwright workflow coverage: Task 6. Completeness scan: - The plan avoids unresolved markers, deferred-work wording, and vague validation instructions. - Each code-writing step includes concrete file content or concrete implementation shape with exact paths. Type consistency: - `ChannelType`, `WorkbenchChannel`, `ProjectWorkspace`, and `InspectorItem` are introduced in Task 2 and consumed consistently in Tasks 3 and 4. - `onInspect(item: InspectorItem): void` is the only inspector selection interface. - `onLogin({ apiBase, account })` is the only login completion interface.