import { Page, expect } from '@playwright/test'; /** * Wait for page to be fully loaded */ export async function waitForPageLoad(page: Page): Promise { await page.waitForLoadState('networkidle'); } /** * Wait for API call to complete */ export async function waitForApi( page: Page, urlPattern: string | RegExp ): Promise { await page.waitForResponse( (response) => (typeof urlPattern === 'string' ? response.url().includes(urlPattern) : urlPattern.test(response.url())) && response.status() === 200 ); } /** * Fill form fields from object */ export async function fillForm( page: Page, fields: Record ): Promise { for (const [name, value] of Object.entries(fields)) { const input = page.locator(`input[name="${name}"], textarea[name="${name}"]`); if (await input.count() > 0) { await input.fill(value); } } } /** * Submit form and wait for response */ export async function submitFormAndWait( page: Page, apiUrlPattern?: string | RegExp ): Promise { const submitPromise = page.click('button[type="submit"]'); if (apiUrlPattern) { await Promise.all([ submitPromise, waitForApi(page, apiUrlPattern), ]); } else { await submitPromise; } } /** * Check for toast message */ export async function expectToast( page: Page, type: 'success' | 'error' | 'info', messageContains?: string ): Promise { const toast = page.locator(`[data-testid="toast-${type}"], .toast-${type}`); await expect(toast).toBeVisible({ timeout: 5000 }); if (messageContains) { await expect(toast).toContainText(messageContains); } } /** * Navigate with authentication check */ export async function navigateTo( page: Page, path: string, options?: { waitForApi?: string | RegExp } ): Promise { const navigationPromise = page.goto(path); if (options?.waitForApi) { await Promise.all([ navigationPromise, waitForApi(page, options.waitForApi), ]); } else { await navigationPromise; await waitForPageLoad(page); } } /** * Get table row count */ export async function getTableRowCount( page: Page, tableSelector: string = 'table tbody tr' ): Promise { return await page.locator(tableSelector).count(); } /** * Click table row action button */ export async function clickRowAction( page: Page, rowIndex: number, actionName: string ): Promise { const row = page.locator('table tbody tr').nth(rowIndex); await row.locator(`[data-testid="action-${actionName}"]`).click(); } /** * Generate unique test email */ export function generateTestEmail(): string { const timestamp = Date.now(); return `test.${timestamp}@example.com`; } /** * Generate unique test slug */ export function generateTestSlug(): string { const timestamp = Date.now(); return `test-company-${timestamp}`; } /** * Take screenshot for debugging */ export async function debugScreenshot( page: Page, name: string ): Promise { await page.screenshot({ path: `./tests/e2e/screenshots/${name}-${Date.now()}.png`, fullPage: true, }); } /** * Mock API response */ export async function mockApiResponse( page: Page, urlPattern: string | RegExp, response: object, status: number = 200 ): Promise { await page.route(urlPattern, (route) => { route.fulfill({ status, contentType: 'application/json', body: JSON.stringify(response), }); }); }