refactor(frontend): 重命名前端项目为 gym-manage-web
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
import { Page, expect } from '@playwright/test';
|
||||
|
||||
export class TestStabilityHelper {
|
||||
private readonly page: Page;
|
||||
private readonly maxRetries: number = 3;
|
||||
private readonly retryDelay: number = 1000;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
async waitForNetworkIdle(timeout: number = 30000): Promise<void> {
|
||||
try {
|
||||
await this.page.waitForLoadState('networkidle', { timeout });
|
||||
} catch (error) {
|
||||
console.log('Network idle timeout, continuing anyway');
|
||||
}
|
||||
}
|
||||
|
||||
async waitForElementVisible(selector: string, timeout: number = 10000): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await expect(element).toBeVisible({ timeout });
|
||||
});
|
||||
}
|
||||
|
||||
async safeClick(selector: string): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await element.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await element.click({ timeout: 5000 });
|
||||
});
|
||||
}
|
||||
|
||||
async safeFill(selector: string, value: string): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await element.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await element.clear();
|
||||
await element.fill(value);
|
||||
});
|
||||
}
|
||||
|
||||
async safeSelect(selector: string, value: string): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await element.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await element.selectOption(value);
|
||||
});
|
||||
}
|
||||
|
||||
async waitForURL(urlPattern: RegExp | string, timeout: number = 30000): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
await this.page.waitForURL(urlPattern, { timeout });
|
||||
});
|
||||
}
|
||||
|
||||
async handleModal(): Promise<void> {
|
||||
try {
|
||||
const modal = this.page.locator('.el-dialog, .el-message-box');
|
||||
const isVisible = await modal.isVisible({ timeout: 2000 });
|
||||
|
||||
if (isVisible) {
|
||||
const confirmButton = modal.locator('.el-button--primary').first();
|
||||
const cancelButton = modal.locator('.el-button--default').first();
|
||||
|
||||
if (await confirmButton.isVisible({ timeout: 1000 })) {
|
||||
await confirmButton.click();
|
||||
} else if (await cancelButton.isVisible({ timeout: 1000 })) {
|
||||
await cancelButton.click();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('No modal found or modal handling failed');
|
||||
}
|
||||
}
|
||||
|
||||
async waitForLoadingComplete(): Promise<void> {
|
||||
try {
|
||||
const loading = this.page.locator('.el-loading-mask, .loading');
|
||||
await loading.waitFor({ state: 'hidden', timeout: 10000 });
|
||||
} catch (error) {
|
||||
console.log('Loading element not found or timeout');
|
||||
}
|
||||
}
|
||||
|
||||
async safeNavigate(url: string): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
await this.page.goto(url, { waitUntil: 'networkidle', timeout: 30000 });
|
||||
});
|
||||
}
|
||||
|
||||
async waitForTableData(tableSelector: string, minRows: number = 1): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const table = this.page.locator(tableSelector);
|
||||
await expect(table).toBeVisible({ timeout: 10000 });
|
||||
|
||||
const rows = table.locator('.el-table__row');
|
||||
const rowCount = await rows.count();
|
||||
expect(rowCount).toBeGreaterThanOrEqual(minRows);
|
||||
});
|
||||
}
|
||||
|
||||
async safeScrollIntoView(selector: string): Promise<void> {
|
||||
const element = this.page.locator(selector);
|
||||
await element.scrollIntoViewIfNeeded();
|
||||
await this.page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
async clearLocalStorage(): Promise<void> {
|
||||
await this.page.evaluate(() => {
|
||||
localStorage.clear();
|
||||
});
|
||||
}
|
||||
|
||||
async clearSessionStorage(): Promise<void> {
|
||||
await this.page.evaluate(() => {
|
||||
sessionStorage.clear();
|
||||
});
|
||||
}
|
||||
|
||||
async takeScreenshot(name: string): Promise<void> {
|
||||
await this.page.screenshot({ path: `test-results/screenshots/${name}.png`, fullPage: true });
|
||||
}
|
||||
|
||||
async getErrorMessage(): Promise<string | null> {
|
||||
try {
|
||||
const errorElement = this.page.locator('.el-message--error, .error-message');
|
||||
const isVisible = await errorElement.isVisible({ timeout: 2000 });
|
||||
|
||||
if (isVisible) {
|
||||
return await errorElement.textContent();
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async hasErrorMessage(): Promise<boolean> {
|
||||
const errorMessage = await this.getErrorMessage();
|
||||
return errorMessage !== null;
|
||||
}
|
||||
|
||||
private async retry<T>(fn: () => Promise<T>): Promise<T> {
|
||||
let lastError: Error | undefined;
|
||||
|
||||
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
|
||||
try {
|
||||
return await fn();
|
||||
} catch (error) {
|
||||
lastError = error as Error;
|
||||
console.log(`Attempt ${attempt} failed, retrying...`, error);
|
||||
|
||||
if (attempt < this.maxRetries) {
|
||||
await this.page.waitForTimeout(this.retryDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError || new Error('All retry attempts failed');
|
||||
}
|
||||
|
||||
async waitForElementNotVisible(selector: string, timeout: number = 10000): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await expect(element).not.toBeVisible({ timeout });
|
||||
});
|
||||
}
|
||||
|
||||
async safeHover(selector: string): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await element.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await element.hover({ timeout: 5000 });
|
||||
});
|
||||
}
|
||||
|
||||
async waitForText(selector: string, text: string, timeout: number = 10000): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await expect(element).toContainText(text, { timeout });
|
||||
});
|
||||
}
|
||||
|
||||
async waitForTextNotPresent(selector: string, text: string, timeout: number = 10000): Promise<void> {
|
||||
await this.retry(async () => {
|
||||
const element = this.page.locator(selector);
|
||||
await expect(element).not.toContainText(text, { timeout });
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user