learning_ai_clock/web/e2e/navigation.spec.ts

47 lines
1.8 KiB
TypeScript

import { test, expect } from '@playwright/test';
test.describe('Navigation', () => {
test('dashboard loads with ChronoMind heading', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('h1').filter({ hasText: 'ChronoMind' })).toBeVisible({ timeout: 30_000 });
});
test('sidebar contains all nav links', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('h1').filter({ hasText: 'ChronoMind' })).toBeVisible({ timeout: 30_000 });
const links = ['Routines', 'History & Stats', 'Focus Mode', 'Settings'];
for (const label of links) {
await expect(page.getByRole('link', { name: label })).toBeVisible();
}
});
test('navigates to all pages without errors', async ({ page }) => {
const errors: string[] = [];
page.on('pageerror', err => errors.push(err.message));
const routes = ['/', '/routines', '/history', '/focus', '/settings'];
for (const route of routes) {
await page.goto(route);
await page.waitForLoadState('networkidle');
}
const realErrors = errors.filter(e => !e.includes('fetch') && !e.includes('Failed'));
expect(realErrors).toHaveLength(0);
});
test('New Timer button is visible on dashboard', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('h1').filter({ hasText: 'ChronoMind' })).toBeVisible({ timeout: 30_000 });
await expect(page.getByRole('button', { name: 'New Timer' })).toBeVisible();
});
test('landing page is accessible at /landing', async ({ page }) => {
await page.goto('/landing');
await expect(page.getByText(/never be caught/i)).toBeVisible();
});
});