import { test, expect } from '@playwright/test'; import { loginAs, REQUIRE_SEEDED_AUTH, TEST_USER } from './helpers/auth.js'; test.describe('Sidebar navigation', () => { test.beforeEach(async ({ page }) => { await loginAs(page, TEST_USER.email, TEST_USER.password); const url = page.url(); test.skip( !REQUIRE_SEEDED_AUTH && !url.includes('/chat'), 'No seeded test user — skipping authenticated tests', ); }); test('sidebar shows the Mosaic brand', async ({ page }) => { await page.goto('/chat'); // The brand block is a logo image plus "Mosaic / Mission Control" text, // not a link. await expect(page.getByRole('img', { name: /mosaic logo/i })).toBeVisible(); await expect(page.getByText('Mission Control')).toBeVisible(); }); test('Chat nav link navigates to /chat', async ({ page }) => { await page.goto('/settings'); await page .getByRole('link', { name: /^chat$/i }) .first() .click(); await expect(page).toHaveURL(/\/chat/); }); test('Projects nav link navigates to /projects', async ({ page }) => { await page.goto('/chat'); await page .getByRole('link', { name: /projects/i }) .first() .click(); await expect(page).toHaveURL(/\/projects/); }); test('Settings nav link navigates to /settings', async ({ page }) => { await page.goto('/chat'); await page .getByRole('link', { name: /settings/i }) .first() .click(); await expect(page).toHaveURL(/\/settings/); }); test('Tasks nav link navigates to /tasks', async ({ page }) => { await page.goto('/chat'); await page.getByRole('link', { name: /tasks/i }).first().click(); await expect(page).toHaveURL(/\/tasks/); }); test('active link is visually highlighted', async ({ page }) => { await page.goto('/chat'); // The sidebar marks the active item with `font-medium` (plus an inline // primary-color style); inactive items get the hover class instead. const chatLink = page.getByRole('link', { name: /^chat$/i }).first(); const projectsLink = page.getByRole('link', { name: /^projects$/i }).first(); await expect(chatLink).toHaveClass(/font-medium/); await expect(projectsLink).not.toHaveClass(/font-medium/); }); }); test.describe('Route transitions', () => { test.beforeEach(async ({ page }) => { await loginAs(page, TEST_USER.email, TEST_USER.password); const url = page.url(); test.skip( !REQUIRE_SEEDED_AUTH && !url.includes('/chat'), 'No seeded test user — skipping authenticated tests', ); }); test('navigating chat → projects → settings → chat works without errors', async ({ page }) => { await page.goto('/chat'); await expect(page).toHaveURL(/\/chat/); // level: 1 — empty-state h2s ("No projects yet") also match the loose // patterns, and a two-element match is a strict-mode violation. await page.goto('/projects'); await expect(page.getByRole('heading', { level: 1, name: /projects/i })).toBeVisible(); await page.goto('/settings'); await expect(page.getByRole('heading', { level: 1, name: /settings/i })).toBeVisible(); await page.goto('/chat'); await expect(page).toHaveURL(/\/chat/); }); test('back-button navigation works between pages', async ({ page }) => { await page.goto('/chat'); await page.goto('/projects'); await page.goBack(); await expect(page).toHaveURL(/\/chat/); }); });