Files
stack/apps/web/e2e/chat.spec.ts
Jason Woltje a7804e689d
Some checks failed
ci/woodpecker/push/ci Pipeline failed
feat(web): add Playwright E2E test suite for critical paths (#55)
Sets up @playwright/test in apps/web with playwright.config.ts
targeting localhost:3000. Adds E2E test coverage for all critical paths:
auth (login/register/validation), chat (page load, new conversation),
projects (list, empty state), settings (4 tab switches), admin (tab
switching, role guard), and navigation (sidebar links, route transitions).

Includes auth helper, separate tsconfig.e2e.json, and allowDefaultProject
ESLint config so e2e files pass the pre-commit hook. Adds pnpm test:e2e script.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 14:34:31 -05:00

51 lines
2.1 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { loginAs, TEST_USER } from './helpers/auth.js';
test.describe('Chat page', () => {
test.beforeEach(async ({ page }) => {
await loginAs(page, TEST_USER.email, TEST_USER.password);
// If login failed (no seeded user in env) we may be on /login — skip
const url = page.url();
test.skip(!url.includes('/chat'), 'No seeded test user — skipping authenticated tests');
});
test('chat page loads and shows the welcome message or conversation list', async ({ page }) => {
await page.goto('/chat');
// Either there are conversations listed or the welcome empty-state is shown
const hasWelcome = await page
.getByRole('heading', { name: /welcome to mosaic chat/i })
.isVisible()
.catch(() => false);
const hasConversationPanel = await page
.locator('[data-testid="conversation-list"], nav, aside')
.first()
.isVisible()
.catch(() => false);
expect(hasWelcome || hasConversationPanel).toBe(true);
});
test('new conversation button is visible', async ({ page }) => {
await page.goto('/chat');
// "Start new conversation" button or a "+" button in the sidebar
const newConvButton = page.getByRole('button', { name: /new conversation|start new/i }).first();
await expect(newConvButton).toBeVisible({ timeout: 10_000 });
});
test('clicking new conversation shows a chat input area', async ({ page }) => {
await page.goto('/chat');
// Find any button that creates a new conversation
const newBtn = page.getByRole('button', { name: /new conversation|start new/i }).first();
await newBtn.click();
// After creating, a text input for sending messages should appear
const chatInput = page.getByRole('textbox').or(page.locator('textarea')).first();
await expect(chatInput).toBeVisible({ timeout: 10_000 });
});
test('sidebar navigation is present on chat page', async ({ page }) => {
await page.goto('/chat');
// The app-shell sidebar should be visible
await expect(page.getByRole('link', { name: /chat/i }).first()).toBeVisible();
});
});