import { Page, Locator } from '@playwright/test'; export class TestHelpers { static async waitForElementVisible(locator: Locator, timeout: number = 5000): Promise { try { await locator.waitFor({ state: 'visible', timeout }); return true; } catch { return false; } } static async waitForElementHidden(locator: Locator, timeout: number = 5000): Promise { try { await locator.waitFor({ state: 'hidden', timeout }); return true; } catch { return false; } } static async safeClick(locator: Locator, timeout: number = 5000): Promise { try { await locator.waitFor({ state: 'visible', timeout }); await locator.click(); return true; } catch (error) { console.warn('Safe click failed:', error); return false; } } static async safeFill(locator: Locator, value: string, timeout: number = 5000): Promise { try { await locator.waitFor({ state: 'visible', timeout }); await locator.clear(); await locator.fill(value); return true; } catch (error) { console.warn('Safe fill failed:', error); return false; } } static async safeSelect(locator: Locator, value: string, timeout: number = 5000): Promise { try { await locator.waitFor({ state: 'visible', timeout }); await locator.selectOption(value); return true; } catch (error) { console.warn('Safe select failed:', error); return false; } } static async retryOperation( operation: () => Promise, maxRetries: number = 3, delayMs: number = 1000 ): Promise { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await operation(); } catch (error) { if (attempt === maxRetries) { console.error(`Operation failed after ${maxRetries} attempts:`, error); return null; } console.log(`Attempt ${attempt} failed, retrying in ${delayMs}ms...`); await new Promise(resolve => setTimeout(resolve, delayMs)); } } return null; } static async waitForNetworkIdle(page: Page, timeout: number = 10000): Promise { try { await page.waitForLoadState('networkidle', { timeout }); } catch (error) { console.warn('Network idle timeout, continuing...'); } } static async waitForNavigation(page: Page, urlPattern: RegExp, timeout: number = 10000): Promise { try { await page.waitForURL(urlPattern, { timeout }); return true; } catch { return false; } } static async handleDialog(page: Page, action: 'accept' | 'dismiss' = 'accept'): Promise { page.on('dialog', async dialog => { if (action === 'accept') { await dialog.accept(); } else { await dialog.dismiss(); } }); } static async getTableData(table: Locator): Promise { const rows = await table.locator('tbody tr').all(); const data: string[][] = []; for (const row of rows) { const cells = await row.locator('td').allTextContents(); data.push(cells); } return data; } static async findTableRowByContent(table: Locator, content: string): Promise { const rows = await table.locator('tbody tr').all(); for (const row of rows) { const textContent = await row.textContent(); if (textContent && textContent.includes(content)) { return row; } } return null; } static async scrollToElement(page: Page, locator: Locator): Promise { await locator.scrollIntoViewIfNeeded(); await page.waitForTimeout(300); } static async waitForAnimation(locator: Locator): Promise { await locator.waitFor({ state: 'attached' }); await locator.evaluate(el => { return new Promise(resolve => { requestAnimationFrame(() => { setTimeout(resolve, 300); }); }); }); } static async takeScreenshot(page: Page, name: string): Promise { await page.screenshot({ path: `test-results/screenshots/${name}.png`, fullPage: true }); } static async waitForPageLoad(page: Page, timeout: number = 10000): Promise { try { await page.waitForLoadState('load', { timeout }); } catch (error) { console.warn('Page load timeout, continuing...'); } } static async waitForDOMContent(page: Page, timeout: number = 10000): Promise { try { await page.waitForLoadState('domcontentloaded', { timeout }); } catch (error) { console.warn('DOM content load timeout, continuing...'); } } static async isElementVisible(locator: Locator): Promise { try { return await locator.isVisible({ timeout: 1000 }); } catch { return false; } } static async isElementEnabled(locator: Locator): Promise { try { return await locator.isEnabled({ timeout: 1000 }); } catch { return false; } } static async getElementText(locator: Locator): Promise { try { return await locator.textContent({ timeout: 5000 }); } catch { return null; } } static async getElementCount(locator: Locator): Promise { try { return await locator.count(); } catch { return 0; } } static async waitForTextContent(locator: Locator, expectedText: string, timeout: number = 5000): Promise { try { await locator.waitFor({ state: 'visible', timeout }); const text = await locator.textContent(); return text !== null && text.includes(expectedText); } catch { return false; } } static async clearInput(locator: Locator): Promise { await locator.click(); await locator.fill(''); await locator.press('Control+A'); await locator.press('Backspace'); } static async waitForSuccessMessage(page: Page, timeout: number = 5000): Promise { const successMessage = page.locator('.el-message--success, .success-message, [class*="success"]'); try { await successMessage.waitFor({ state: 'visible', timeout }); return true; } catch { return false; } } static async waitForErrorMessage(page: Page, timeout: number = 5000): Promise { const errorMessage = page.locator('.el-message--error, .error-message, [class*="error"]'); try { await errorMessage.waitFor({ state: 'visible', timeout }); return true; } catch { return false; } } static async waitForLoadingComplete(page: Page, timeout: number = 10000): Promise { const loadingSpinner = page.locator('.el-loading-mask, .loading, [class*="loading"]'); try { await loadingSpinner.waitFor({ state: 'visible', timeout: 2000 }); await loadingSpinner.waitFor({ state: 'hidden', timeout }); } catch { console.log('No loading spinner found or already hidden'); } } static async waitForModal(page: Page, timeout: number = 5000): Promise { const modal = page.locator('.el-dialog, .modal, [role="dialog"]'); try { await modal.waitFor({ state: 'visible', timeout }); return true; } catch { return false; } } static async closeModal(page: Page): Promise { const closeButton = page.locator('.el-dialog__close, .modal-close, button[aria-label="Close"]'); try { await closeButton.click(); return true; } catch { return false; } } static async waitForSelectDropdown(page: Page, timeout: number = 5000): Promise { const dropdown = page.locator('.el-select-dropdown, .select-dropdown'); try { await dropdown.waitFor({ state: 'visible', timeout }); return true; } catch { return false; } } static async selectFromDropdown(page: Page, value: string): Promise { const option = page.locator('.el-select-dropdown__item, .select-option').filter({ hasText: value }); try { await option.click(); return true; } catch { return false; } } }