Add analytics plugin package for tracking and metrics. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
59 lines
2 KiB
TypeScript
59 lines
2 KiB
TypeScript
import { Page, Locator } from '@playwright/test'
|
|
|
|
/**
|
|
* Base Page Object for Analytics Pages
|
|
* Provides common functionality shared across all 10 analytics pages
|
|
*/
|
|
export class AnalyticsPageBase {
|
|
readonly page: Page
|
|
readonly pageTitle: Locator
|
|
readonly dateFilter: Locator
|
|
readonly kpiSection: Locator
|
|
readonly loadingSpinner: Locator
|
|
readonly errorMessage: Locator
|
|
|
|
constructor(page: Page) {
|
|
this.page = page
|
|
this.pageTitle = page.locator('[data-testid="page-title"]')
|
|
this.dateFilter = page.locator('[data-testid="date-filter"]')
|
|
this.kpiSection = page.locator('[data-testid="kpi-section"]')
|
|
this.loadingSpinner = page.locator('[data-testid="loading-spinner"]')
|
|
this.errorMessage = page.locator('[data-testid="error-message"]')
|
|
}
|
|
|
|
async waitForLoad() {
|
|
// Wait for DOM content to be ready
|
|
await this.page.waitForLoadState('domcontentloaded')
|
|
|
|
// If loading spinner appears, wait for it to disappear
|
|
const hasSpinner = await this.loadingSpinner.isVisible().catch(() => false)
|
|
if (hasSpinner) {
|
|
await this.loadingSpinner.waitFor({ state: 'hidden', timeout: 10000 })
|
|
}
|
|
|
|
// Wait for page title to be visible - this is the key indicator page has loaded
|
|
await this.pageTitle.waitFor({ state: 'visible', timeout: 10000 })
|
|
}
|
|
|
|
async selectDateRange(range: '7d' | '30d' | 'this-month' | 'last-month' | 'custom') {
|
|
const button = this.page.locator(`[data-testid="filter-${range}"]`)
|
|
await button.click()
|
|
}
|
|
|
|
async getKpiCardValue(cardTestId: string): Promise<string | null> {
|
|
const card = this.page.locator(`[data-testid="${cardTestId}"]`)
|
|
const valueElement = card.locator('.value')
|
|
|
|
if (await valueElement.isVisible().catch(() => false)) {
|
|
return valueElement.textContent()
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
async verifyKpiCardsRendered(): Promise<number> {
|
|
await this.kpiSection.waitFor({ state: 'visible', timeout: 10000 })
|
|
const cards = this.kpiSection.locator('.kpi-card')
|
|
return cards.count()
|
|
}
|
|
}
|