import { test as base, expect, Page } from '@playwright/test'; import { login, ensureLoggedIn } from '../helpers/auth.helper'; import { waitForBlazorReady } from '../helpers/navigation.helper'; /** * Extended test fixture with authentication state and common utilities */ export const test = base.extend<{ /** Page that is already logged in */ authenticatedPage: Page; }>({ authenticatedPage: async ({ page }, use) => { // Navigate to the app and login await page.goto('/'); await page.waitForLoadState('networkidle', { timeout: 60000 }); await login(page); await waitForBlazorReady(page); // Provide the authenticated page to the test await use(page); }, }); export { expect }; /** * Test configuration options */ export const testConfig = { /** Default timeout for waiting operations */ defaultTimeout: 30000, /** Timeout for Blazor WASM initialization */ blazorTimeout: 120000, /** Timeout for network operations */ networkTimeout: 60000, /** Short wait for UI updates */ shortWait: 500, /** Medium wait for async operations */ mediumWait: 2000, /** Long wait for file operations */ longWait: 5000, }; /** * Common test setup function * @param page - Playwright page object * @param route - Route to navigate to after login (default: '/search') */ export async function setupTest(page: Page, route: string = '/search'): Promise { await page.goto(route); await page.waitForLoadState('networkidle', { timeout: testConfig.networkTimeout }); await ensureLoggedIn(page); await waitForBlazorReady(page); } /** * Test data factory for generating unique test names */ export function generateTestName(prefix: string): string { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); return `${prefix}-${timestamp}`; } /** * Test utilities for common assertions */ export const testUtils = { /** * Wait for page to stabilize after navigation */ async waitForStable(page: Page): Promise { await page.waitForLoadState('networkidle', { timeout: testConfig.networkTimeout }); await page.waitForTimeout(testConfig.shortWait); }, /** * Assert page URL contains expected path */ async assertUrlContains(page: Page, expectedPath: string): Promise { await expect(page).toHaveURL(new RegExp(expectedPath)); }, /** * Assert element is visible with custom timeout */ async assertVisible(page: Page, selector: string, timeout?: number): Promise { await expect(page.locator(selector)).toBeVisible({ timeout: timeout ?? testConfig.defaultTimeout, }); }, /** * Assert element is not visible */ async assertNotVisible(page: Page, selector: string, timeout?: number): Promise { await expect(page.locator(selector)).not.toBeVisible({ timeout: timeout ?? testConfig.defaultTimeout, }); }, /** * Assert text is present on page */ async assertTextPresent(page: Page, text: string): Promise { await expect(page.locator(`text=${text}`)).toBeVisible(); }, /** * Assert text is not present on page */ async assertTextNotPresent(page: Page, text: string): Promise { await expect(page.locator(`text=${text}`)).not.toBeVisible(); }, }; /** * Skip test if condition is met */ export function skipIf(condition: boolean, reason: string): void { if (condition) { test.skip(true, reason); } } /** * Mark test as slow (extends timeout) */ export function markSlow(): void { test.slow(); }