import { Page, Locator, expect } from "@playwright/test"; /** * Base page object class containing common functionality * that can be shared across all page objects */ export abstract class BasePage { readonly page: Page; // Common UI elements that appear on most pages readonly title: Locator; readonly loadingIndicator: Locator; readonly themeToggle: Locator; constructor(page: Page) { this.page = page; // Common locators that most pages share this.title = page.locator("h1, h2, [role='heading']").first(); this.loadingIndicator = page.getByRole("status", { name: "Loading" }); this.themeToggle = page.getByRole("button", { name: "Toggle theme" }); } // Common navigation methods async goto(url: string): Promise { await this.page.goto(url); } async refresh(): Promise { await this.page.reload(); } async goBack(): Promise { await this.page.goBack(); } // Common verification methods async verifyPageTitle(expectedTitle: string | RegExp): Promise { await expect(this.page).toHaveTitle(expectedTitle); } async verifyLoadingState(): Promise { await expect(this.loadingIndicator).toBeVisible(); } async verifyNoLoadingState(): Promise { await expect(this.loadingIndicator).not.toBeVisible(); } // Common form interaction methods async clearInput(input: Locator): Promise { await input.clear(); } async fillInput(input: Locator, value: string): Promise { await input.fill(value); } async clickButton(button: Locator): Promise { await button.click(); } // Common validation methods async verifyElementVisible(element: Locator): Promise { await expect(element).toBeVisible(); } async verifyElementNotVisible(element: Locator): Promise { await expect(element).not.toBeVisible(); } async verifyElementText(element: Locator, expectedText: string): Promise { await expect(element).toHaveText(expectedText); } async verifyElementContainsText(element: Locator, expectedText: string): Promise { await expect(element).toContainText(expectedText); } // Common accessibility methods async verifyKeyboardNavigation(elements: Locator[]): Promise { for (const element of elements) { await this.page.keyboard.press("Tab"); await expect(element).toBeFocused(); } } async verifyAriaLabels(elements: { locator: Locator; expectedLabel: string }[]): Promise { for (const { locator, expectedLabel } of elements) { await expect(locator).toHaveAttribute("aria-label", expectedLabel); } } // Common utility methods async getElementText(element: Locator): Promise { return await element.textContent() || ""; } async getElementValue(element: Locator): Promise { return await element.inputValue(); } async isElementVisible(element: Locator): Promise { return await element.isVisible(); } async isElementEnabled(element: Locator): Promise { return await element.isEnabled(); } // Common error handling methods async getFormErrors(): Promise { const errorElements = await this.page.locator('[role="alert"], .error-message, [data-testid="error"]').all(); const errors: string[] = []; for (const element of errorElements) { const text = await element.textContent(); if (text) { errors.push(text.trim()); } } return errors; } async verifyNoErrors(): Promise { const errors = await this.getFormErrors(); expect(errors).toHaveLength(0); } // Common wait methods async waitForElement(element: Locator, timeout: number = 5000): Promise { await element.waitFor({ timeout }); } async waitForElementToDisappear(element: Locator, timeout: number = 5000): Promise { await element.waitFor({ state: "hidden", timeout }); } async waitForUrl(expectedUrl: string | RegExp, timeout: number = 5000): Promise { await this.page.waitForURL(expectedUrl, { timeout }); } // Common screenshot methods async takeScreenshot(name: string): Promise { await this.page.screenshot({ path: `screenshots/${name}.png` }); } async takeElementScreenshot(element: Locator, name: string): Promise { await element.screenshot({ path: `screenshots/${name}.png` }); } }