71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
/**
|
||
* E2E 测试公共设施(v0.8.2 P3-3)
|
||
*
|
||
* 封装"启动应用(隔离 userData)+ 本地 mock LLM + 清理"的完整生命周期。
|
||
* 每个测试文件独立调用 launchApp() —— 应用实例与 mock 互相隔离,杜绝跨用例
|
||
* 的运行态竞态(中断链路对"上一 run 的收尾兜底定时器"这类跨用例污染敏感)。
|
||
*/
|
||
|
||
import type { ElectronApplication, Page } from '@playwright/test';
|
||
import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from 'fs';
|
||
import { tmpdir } from 'os';
|
||
import { join } from 'path';
|
||
import { _electron as electron } from 'playwright';
|
||
import { startMockLLM, type MockLLMHandle } from './mock-llm';
|
||
|
||
export interface AppHarness {
|
||
electronApp: ElectronApplication;
|
||
page: Page;
|
||
mock: MockLLMHandle;
|
||
userDataDir: string;
|
||
workspaceDir: string;
|
||
/** 关闭应用 + mock + 清理临时目录 */
|
||
cleanup: () => Promise<void>;
|
||
}
|
||
|
||
export async function launchApp(): Promise<AppHarness> {
|
||
// 1. 本地 mock Provider(随机端口,仅监听 127.0.0.1)
|
||
const mock = await startMockLLM();
|
||
|
||
// 2. 隔离的用户数据与工作空间目录
|
||
const userDataDir = mkdtempSync(join(tmpdir(), 'metona-e2e-user-'));
|
||
const workspaceDir = join(userDataDir, 'workspace');
|
||
mkdirSync(workspaceDir, { recursive: true });
|
||
// workspace-config.json 指向隔离工作空间(main.ts 启动时优先读取)
|
||
writeFileSync(
|
||
join(userDataDir, 'workspace-config.json'),
|
||
JSON.stringify({ workspacePath: workspaceDir }),
|
||
'utf-8',
|
||
);
|
||
|
||
// 3. 启动 Electron(产物构建由 npm run test:e2e 的 build 步骤保证)
|
||
const electronApp = await electron.launch({
|
||
args: ['.'],
|
||
env: {
|
||
...process.env,
|
||
METONA_USER_DATA_DIR: userDataDir,
|
||
METONA_E2E_SEED_CONFIG: '1',
|
||
METONA_E2E_LLM_URL: mock.url,
|
||
// 隔离冒烟环境无更新源(生产环境 updater 由 feedUrl 空值禁用,双保险)
|
||
METONA_E2E_DISABLE_UPDATE: '1',
|
||
} as Record<string, string>,
|
||
});
|
||
const page = await electronApp.firstWindow();
|
||
await page.waitForLoadState('domcontentloaded');
|
||
|
||
const cleanup = async (): Promise<void> => {
|
||
await electronApp.close();
|
||
await mock.close();
|
||
// 调试期保留 userData(main.log 排查用);稳定后恢复清理
|
||
if (!process.env['METONA_E2E_KEEP_USER_DATA']) {
|
||
try {
|
||
rmSync(userDataDir, { recursive: true, force: true });
|
||
} catch {
|
||
/* Windows 文件句柄释放延迟 — 清理失败不影响断言 */
|
||
}
|
||
}
|
||
};
|
||
|
||
return { electronApp, page, mock, userDataDir, workspaceDir, cleanup };
|
||
}
|