136 lines
3.6 KiB
TypeScript
136 lines
3.6 KiB
TypeScript
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<void> {
|
|
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<void> {
|
|
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<void> {
|
|
await expect(page).toHaveURL(new RegExp(expectedPath));
|
|
},
|
|
|
|
/**
|
|
* Assert element is visible with custom timeout
|
|
*/
|
|
async assertVisible(page: Page, selector: string, timeout?: number): Promise<void> {
|
|
await expect(page.locator(selector)).toBeVisible({
|
|
timeout: timeout ?? testConfig.defaultTimeout,
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Assert element is not visible
|
|
*/
|
|
async assertNotVisible(page: Page, selector: string, timeout?: number): Promise<void> {
|
|
await expect(page.locator(selector)).not.toBeVisible({
|
|
timeout: timeout ?? testConfig.defaultTimeout,
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Assert text is present on page
|
|
*/
|
|
async assertTextPresent(page: Page, text: string): Promise<void> {
|
|
await expect(page.locator(`text=${text}`)).toBeVisible();
|
|
},
|
|
|
|
/**
|
|
* Assert text is not present on page
|
|
*/
|
|
async assertTextNotPresent(page: Page, text: string): Promise<void> {
|
|
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();
|
|
}
|