99 lines
3.4 KiB
TypeScript
99 lines
3.4 KiB
TypeScript
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/);
|
|
});
|
|
});
|