feat: add base page object with common methods

This commit is contained in:
张翔
2026-03-06 12:06:50 +08:00
parent c7686bf1a3
commit b8d22aac9f
+98
View File
@@ -0,0 +1,98 @@
import { Page, Locator } from '@playwright/test';
import { TestConfig } from '../types';
import { defaultConfig } from '../config/base.config';
export class BasePage {
readonly page: Page;
readonly config: TestConfig;
readonly url: string;
constructor(page: Page, url: string, config?: TestConfig) {
this.page = page;
this.url = url;
this.config = config || defaultConfig;
}
async navigate(): Promise<void> {
await this.page.goto(this.url, { waitUntil: 'networkidle', timeout: this.config.timeout });
}
async waitForLoadState(state: 'load' | 'domcontentloaded' | 'networkidle' = 'load'): Promise<void> {
await this.page.waitForLoadState(state, { timeout: this.config.timeout });
}
async click(locator: Locator | string): Promise<void> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
await element.click({ timeout: this.config.timeout });
}
async fill(locator: Locator | string, value: string): Promise<void> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
await element.fill(value);
}
async getText(locator: Locator | string): Promise<string> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
return await element.textContent() || '';
}
async isVisible(locator: Locator | string): Promise<boolean> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
return await element.isVisible();
}
async waitForElement(locator: Locator | string, timeout?: number): Promise<void> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
await element.waitFor({ state: 'visible', timeout: timeout || this.config.timeout });
}
async scrollToElement(locator: Locator | string): Promise<void> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
await element.scrollIntoViewIfNeeded();
}
async takeScreenshot(filename: string): Promise<void> {
const screenshotDir = 'test-framework/reports/screenshots';
await this.page.screenshot({ path: `${screenshotDir}/${filename}` });
}
async hover(locator: Locator | string): Promise<void> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
await element.hover();
}
async getCurrentURL(): Promise<string> {
return this.page.url();
}
async getTitle(): Promise<string> {
return await this.page.title();
}
async getAttribute(locator: Locator | string, attribute: string): Promise<string | null> {
const element = typeof locator === 'string' ? this.page.locator(locator) : locator;
return await element.getAttribute(attribute);
}
async measurePerformance(): Promise<{
loadTime: number;
domContentLoaded: number;
firstPaint: number;
firstContentfulPaint: number;
}> {
const metrics = await this.page.evaluate(() => {
const performance = window.performance;
const timing = performance.timing;
const navigation = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
return {
loadTime: timing.loadEventEnd - timing.navigationStart,
domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart,
firstPaint: navigation ? navigation.loadEventEnd - navigation.fetchStart : 0,
firstContentfulPaint: navigation ? navigation.domContentLoadedEventEnd - navigation.fetchStart : 0,
};
});
return metrics;
}
}