Files
headroom/frontend/tests/e2e/navigation-links.spec.ts
Santhosh Janardhanan 91269d91a8 feat(pages): Complete p05-page-migrations with all pages and navigation tests
- Create Team Members page with DataTable, search, and filters
- Create Projects page with status badges and workflow
- Create placeholder pages for Allocations, Actuals, Reports, Settings, Master Data
- Fix navigation config: change /team to /team-members
- Remove old Navigation.svelte component
- Add comprehensive navigation link E2E tests (16 tests)
- Add Team Members and Projects page E2E tests

All 16 navigation link tests passing:
- Dashboard, Team Members, Projects, Allocations, Actuals
- All 5 Reports pages (Forecast, Utilization, Costs, Variance, Allocation)
- Admin pages (Settings, Master Data)
- Authentication preservation across pages

Refs: openspec/changes/p05-page-migrations
Closes: p05-page-migrations
2026-02-18 19:03:56 -05:00

121 lines
4.1 KiB
TypeScript

import { test, expect } from '@playwright/test';
/**
* Navigation Link Validation Test
*
* This test verifies all navigation links from the dashboard work correctly.
*/
test.describe('Dashboard Navigation Links', () => {
test.beforeEach(async ({ page }) => {
// Login first
await page.goto('/login');
await page.fill('input[type="email"]', 'superuser@headroom.test');
await page.fill('input[type="password"]', 'password');
await page.click('button[type="submit"]');
await page.waitForURL('/dashboard');
});
test('dashboard page is accessible', async ({ page }) => {
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1', { hasText: 'Dashboard' })).toBeVisible();
await expect(page).toHaveTitle(/Dashboard/);
});
test('team members page is accessible via navigation', async ({ page }) => {
// Click on Team Members link
await page.click('a[href="/team-members"]');
await page.waitForURL('/team-members', { timeout: 10000 });
// Verify page loaded (use h1 for page title specifically)
await expect(page.locator('h1', { hasText: 'Team Members' })).toBeVisible();
await expect(page).toHaveTitle(/Team Members/);
});
test('projects page is accessible via navigation', async ({ page }) => {
await page.click('a[href="/projects"]');
await page.waitForURL('/projects', { timeout: 10000 });
await expect(page.locator('h1', { hasText: 'Projects' })).toBeVisible();
await expect(page).toHaveTitle(/Projects/);
});
test('allocations page is accessible via navigation', async ({ page }) => {
await page.click('a[href="/allocations"]');
await page.waitForURL('/allocations', { timeout: 10000 });
await expect(page.locator('h1', { hasText: 'Allocations' })).toBeVisible();
await expect(page).toHaveTitle(/Allocations/);
});
test('actuals page is accessible via navigation', async ({ page }) => {
await page.click('a[href="/actuals"]');
await page.waitForURL('/actuals', { timeout: 10000 });
await expect(page.locator('h1', { hasText: 'Actuals' })).toBeVisible();
await expect(page).toHaveTitle(/Actuals/);
});
test('reports pages are accessible', async ({ page }) => {
const reportPages = [
{ href: '/reports/forecast', title: 'Forecast', heading: 'Forecast' },
{ href: '/reports/utilization', title: 'Utilization', heading: 'Utilization' },
{ href: '/reports/costs', title: 'Cost', heading: 'Costs' },
{ href: '/reports/variance', title: 'Variance', heading: 'Variance' },
{ href: '/reports/allocation', title: 'Allocation Matrix', heading: 'Allocation Matrix' },
];
for (const report of reportPages) {
// Navigate directly to test page exists
await page.goto(report.href);
await page.waitForLoadState('networkidle');
// Verify page loaded
await expect(page.locator('h1', { hasText: report.heading })).toBeVisible({ timeout: 5000 });
await expect(page).toHaveTitle(new RegExp(report.title));
// Should have sidebar (authenticated)
await expect(page.locator('[data-testid="sidebar"]')).toBeVisible();
}
});
test('admin pages are accessible for superuser', async ({ page }) => {
const adminPages = [
{ href: '/settings', title: 'Settings' },
{ href: '/master-data', title: 'Master Data' },
];
for (const admin of adminPages) {
await page.goto(admin.href);
await page.waitForLoadState('networkidle');
await expect(page.locator('h1', { hasText: admin.title })).toBeVisible({ timeout: 5000 });
await expect(page).toHaveTitle(new RegExp(admin.title));
}
});
test('navigation preserves authentication across pages', async ({ page }) => {
const pages = [
'/dashboard',
'/team-members',
'/projects',
'/allocations',
'/actuals',
'/reports/forecast',
'/settings'
];
for (const url of pages) {
await page.goto(url);
await page.waitForLoadState('networkidle');
// Should not redirect to login
expect(page.url()).not.toContain('/login');
// Verify still authenticated (sidebar should be visible)
await expect(page.locator('[data-testid="sidebar"]'),
`Sidebar should be visible on ${url}`).toBeVisible({ timeout: 5000 });
}
});
});