- 添加 Gemini 2.5 Flash 对话接口(流式+非流式) - 添加 NanoBanana 图像生成/编辑接口 - 添加 Sora2 视频生成接口(文生视频、图生视频、去水印) - 移除 models-integration 子项目(功能已迁移至主后端) - 新增测试文档和 Playwright E2E 配置 - 更新前端页面和 API 接口 - 更新后端配置和日志处理
78 lines
2.5 KiB
TypeScript
78 lines
2.5 KiB
TypeScript
import { Page, FrameLocator, Locator } from '@playwright/test';
|
|
|
|
/** App base URL (H5 dev server) */
|
|
export const BASE_URL = 'http://localhost:8080';
|
|
|
|
/** Credentials for demo account */
|
|
export const TEST_CREDENTIALS = {
|
|
phone: '18621813282',
|
|
password: 'A123456',
|
|
};
|
|
|
|
/**
|
|
* Returns the frame or page to interact with.
|
|
* If the page has a #iframe element (pc.html wrapper), use the frame context;
|
|
* otherwise use the page directly.
|
|
*/
|
|
export async function getAppContext(page: Page): Promise<Page | FrameLocator> {
|
|
const hasIframe = await page.locator('#iframe').count();
|
|
if (hasIframe > 0) {
|
|
return page.frameLocator('#iframe');
|
|
}
|
|
return page;
|
|
}
|
|
|
|
/**
|
|
* Navigate to an internal UniApp hash route.
|
|
* Works whether we are inside an iframe or directly on root.
|
|
*/
|
|
export async function goToPage(page: Page, route: string): Promise<void> {
|
|
await page.goto(`${BASE_URL}/#/${route}`);
|
|
// Brief wait for Vue router & components to hydrate
|
|
await page.waitForTimeout(1500);
|
|
}
|
|
|
|
/**
|
|
* Perform login flow using phone + password.
|
|
* Expects to already be on the login page or navigates there.
|
|
*/
|
|
export async function login(
|
|
page: Page,
|
|
phone = TEST_CREDENTIALS.phone,
|
|
password = TEST_CREDENTIALS.password,
|
|
): Promise<void> {
|
|
await goToPage(page, 'pages/users/login/index');
|
|
|
|
// UniApp H5 renders <input> as native HTML input elements
|
|
const phoneInput = page.locator('input[type="number"], input[placeholder*="手机号"]').first();
|
|
const passwordInput = page.locator('input[type="password"], input[placeholder*="密码"]').first();
|
|
|
|
await phoneInput.waitFor({ state: 'visible', timeout: 10_000 });
|
|
await phoneInput.fill(phone);
|
|
await passwordInput.fill(password);
|
|
|
|
// Agree to terms (checkbox-group)
|
|
const checkbox = page.locator('uni-checkbox, .checkbox').first();
|
|
const isChecked = await checkbox.getAttribute('checked').catch(() => null);
|
|
if (!isChecked || isChecked === 'false') {
|
|
await checkbox.click().catch(() => {
|
|
// Fallback: click the parent checkbox-group
|
|
return page.locator('uni-checkbox-group, .checkgroup').first().click();
|
|
});
|
|
}
|
|
|
|
// Click login button (current === 0 → "账号登录" button)
|
|
const loginBtn = page.locator('.logon').first();
|
|
await loginBtn.click();
|
|
|
|
// Wait for navigation away from login page
|
|
await page.waitForTimeout(3000);
|
|
}
|
|
|
|
/**
|
|
* Wait until the UniApp page finishes mounting (title or key element appears).
|
|
*/
|
|
export async function waitForPageReady(page: Page, selector: string, timeout = 10_000): Promise<void> {
|
|
await page.locator(selector).waitFor({ state: 'visible', timeout });
|
|
}
|