feat(dashboard): Enhance dashboard with PageHeader, StatCard, and auth fixes
- Create PageHeader component with title, description, and action slots - Create StatCard component with trend indicators and icons - Update dashboard with KPI cards, Quick Actions, and Allocation Preview - Polish login page with branding and centered layout - Fix auth redirect: authenticated users accessing /login go to dashboard - Fix page refresh: auth state persists, no blank page - Fix sidebar: visible after login, toggle works, state persists - Fix CSS import: add app.css to layout, fix DaisyUI import path - Fix breadcrumbs: home icon links to /dashboard - Add comprehensive E2E and unit tests Refs: openspec/changes/p03-dashboard-enhancement Closes: p03-dashboard-enhancement
This commit is contained in:
62
frontend/tests/e2e/login.spec.ts
Normal file
62
frontend/tests/e2e/login.spec.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Login Page', () => {
|
||||
test('login page is centered and displays branding', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
|
||||
// Check page title
|
||||
await expect(page).toHaveTitle(/Login/);
|
||||
|
||||
// Check branding/logo is visible
|
||||
await expect(page.getByRole('heading', { name: 'Headroom' })).toBeVisible();
|
||||
await expect(page.getByText('Resource Planning & Capacity Management')).toBeVisible();
|
||||
|
||||
// Check logo icon is present (using the LayoutDashboard icon container)
|
||||
const logoContainer = page.locator('.bg-primary.rounded-2xl');
|
||||
await expect(logoContainer).toBeVisible();
|
||||
|
||||
// Check login form is centered (card is visible and centered via flexbox)
|
||||
const card = page.locator('.card');
|
||||
await expect(card).toBeVisible();
|
||||
|
||||
// Check welcome message
|
||||
await expect(page.getByRole('heading', { name: 'Welcome Back' })).toBeVisible();
|
||||
await expect(page.getByText('Sign in to access your dashboard')).toBeVisible();
|
||||
|
||||
// Check form elements are present
|
||||
await expect(page.getByLabel('Email')).toBeVisible();
|
||||
await expect(page.getByLabel('Password')).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: /Login/i })).toBeVisible();
|
||||
|
||||
// Check demo credentials section
|
||||
await expect(page.getByText('Demo Access')).toBeVisible();
|
||||
await expect(page.getByText('Use these credentials to explore:')).toBeVisible();
|
||||
await expect(page.locator('code').filter({ hasText: 'admin@example.com' })).toBeVisible();
|
||||
await expect(page.locator('code').filter({ hasText: 'password' })).toBeVisible();
|
||||
|
||||
// Check footer
|
||||
await expect(page.getByText('Headroom - Engineering Resource Planning')).toBeVisible();
|
||||
});
|
||||
|
||||
test('login form is vertically centered in viewport', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
|
||||
// Get the container and check it uses flexbox centering
|
||||
const container = page.locator('.min-h-screen');
|
||||
await expect(container).toHaveClass(/flex-col/);
|
||||
await expect(container).toHaveClass(/items-center/);
|
||||
await expect(container).toHaveClass(/justify-center/);
|
||||
|
||||
// The card should be centered both horizontally and vertically
|
||||
const card = page.locator('.card');
|
||||
const box = await card.boundingBox();
|
||||
const viewport = page.viewportSize();
|
||||
|
||||
if (box && viewport) {
|
||||
const cardCenterY = box.y + box.height / 2;
|
||||
const viewportCenterY = viewport.height / 2;
|
||||
// Allow for some margin of error (within 100px of center)
|
||||
expect(Math.abs(cardCenterY - viewportCenterY)).toBeLessThan(100);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user