template-saas-frontend-v2/tests/e2e/utils/helpers.ts
rckrdmrd eb95d0e276 Initial commit - Frontend de template-saas migrado desde monorepo
Migración desde workspace-v2/projects/template-saas/apps/frontend
Este repositorio es parte del estándar multi-repo v2

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:07:16 -06:00

164 lines
3.4 KiB
TypeScript

import { Page, expect } from '@playwright/test';
/**
* Wait for page to be fully loaded
*/
export async function waitForPageLoad(page: Page): Promise<void> {
await page.waitForLoadState('networkidle');
}
/**
* Wait for API call to complete
*/
export async function waitForApi(
page: Page,
urlPattern: string | RegExp
): Promise<void> {
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<string, string>
): Promise<void> {
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<void> {
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<void> {
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<void> {
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<number> {
return await page.locator(tableSelector).count();
}
/**
* Click table row action button
*/
export async function clickRowAction(
page: Page,
rowIndex: number,
actionName: string
): Promise<void> {
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<void> {
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<void> {
await page.route(urlPattern, (route) => {
route.fulfill({
status,
contentType: 'application/json',
body: JSON.stringify(response),
});
});
}