feat: v0.8.2 安全纵深补全 · 协议保真 · 断链修复 — 图片SSRF/根MEMORY.md保护根治 · Anthropic thinking回传+pause_turn续传 · 2523 用例全量回归 + E2E 扩充
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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 };
|
||||
}
|
||||
Reference in New Issue
Block a user