feat: add Playwright E2E and API regression test suite
Production-ready test infrastructure with Page Object Model pattern, reusable fixtures for auth/DB/test-data, and example tests covering login flow, dashboard, accounts CRUD API, and visual regression. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
56
tests/page-objects/DashboardPage.ts
Normal file
56
tests/page-objects/DashboardPage.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Page object for the Dashboard (/dashboard).
|
||||
*
|
||||
* Maps to: frontend/src/pages/dashboard/DashboardPage.tsx
|
||||
* Data: GET /api/reports/dashboard
|
||||
*/
|
||||
|
||||
import { type Page, expect } from '@playwright/test';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class DashboardPage extends BasePage {
|
||||
readonly path = '/dashboard';
|
||||
|
||||
// ─── Locators ────────────────────────────────────────────────
|
||||
|
||||
/** Main dashboard heading */
|
||||
get heading() {
|
||||
return this.page.getByRole('heading', { name: /dashboard/i }).first();
|
||||
}
|
||||
|
||||
/** Account balance summary cards */
|
||||
get balanceCards() {
|
||||
return this.page.locator('[class*="Card"]').filter({ hasText: /balance|total/i });
|
||||
}
|
||||
|
||||
/** Sidebar navigation */
|
||||
get sidebar() {
|
||||
return this.page.locator('nav').first();
|
||||
}
|
||||
|
||||
/** Sidebar links */
|
||||
sidebarLink(name: string) {
|
||||
return this.sidebar.getByRole('link', { name });
|
||||
}
|
||||
|
||||
// ─── Actions ─────────────────────────────────────────────────
|
||||
|
||||
/** Wait for dashboard data to load */
|
||||
override async waitForReady(): Promise<void> {
|
||||
await this.page.waitForLoadState('networkidle');
|
||||
// Dashboard typically loads report data
|
||||
await expect(this.page.locator('main')).toBeVisible();
|
||||
}
|
||||
|
||||
/** Assert the dashboard has loaded with content */
|
||||
async assertLoaded(): Promise<void> {
|
||||
await this.assertOnPage();
|
||||
await expect(this.page.locator('main')).not.toBeEmpty();
|
||||
}
|
||||
|
||||
/** Navigate to a section via sidebar */
|
||||
async navigateToSection(section: string): Promise<void> {
|
||||
await this.sidebarLink(section).click();
|
||||
await this.page.waitForLoadState('networkidle');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user