import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; describe("ensure-storage-state", () => { let tmpDir: string; afterEach(() => { if (tmpDir && fs.existsSync(tmpDir)) { fs.rmSync(tmpDir, { recursive: true, force: true }); } vi.resetModules(); vi.restoreAllMocks(); delete process.env.RPA_STORAGE_STATE_PATH; delete process.env.RPA_AUTO_BOOTSTRAP_STORAGE; delete process.env.RPA_MOCK_MODE; }); it("会话文件已存在时跳过 bootstrap", async () => { tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "rpa-ensure-")); const stateFile = path.join(tmpDir, "state.json"); fs.writeFileSync(stateFile, '{"cookies":[]}'); process.env.RPA_STORAGE_STATE_PATH = stateFile; const launch = vi.fn(); vi.doMock("@/lib/rpa/browser-launch", () => ({ launchRpaBrowser: launch })); const { ensureMothershipStorageState } = await import( "@/lib/rpa/ensure-storage-state" ); await ensureMothershipStorageState(); expect(launch).not.toHaveBeenCalled(); }); it("缺文件且关闭自动 bootstrap 时抛错", async () => { tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "rpa-ensure-")); const stateFile = path.join(tmpDir, "missing.json"); process.env.RPA_STORAGE_STATE_PATH = stateFile; process.env.RPA_AUTO_BOOTSTRAP_STORAGE = "false"; const { ensureMothershipStorageState } = await import( "@/lib/rpa/ensure-storage-state" ); await expect(ensureMothershipStorageState()).rejects.toThrow(/record:mothership/); }); it("缺文件时自动 bootstrap 并写入 storageState", async () => { tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "rpa-ensure-")); const stateFile = path.join(tmpDir, "state.json"); process.env.RPA_STORAGE_STATE_PATH = stateFile; process.env.MOTHERSHIP_QUOTE_URLS = "https://www.mothership.com/"; const persistContext = vi.fn(async () => { fs.mkdirSync(path.dirname(stateFile), { recursive: true }); fs.writeFileSync(stateFile, '{"cookies":[{"name":"s","value":"1"}]}'); }); vi.doMock("@/lib/rpa/browser-launch", () => ({ launchRpaBrowser: vi.fn(async () => ({ newContext: vi.fn(async () => ({ newPage: vi.fn(async () => ({ close: vi.fn(async () => undefined), })), close: vi.fn(async () => undefined), })), close: vi.fn(async () => undefined), })), })); vi.doMock("@/lib/rpa/storage-state", async () => { const actual = await vi.importActual( "@/lib/rpa/storage-state", ); return { ...actual, persistContext }; }); vi.doMock("@/workers/rpa/quote-page-adapter", () => ({ quotePageAdapter: { resolveQuoteEntry: vi.fn(async () => ({ activeUrl: "https://x" })), preCheck: vi.fn(async () => true), }, })); const { ensureMothershipStorageState } = await import( "@/lib/rpa/ensure-storage-state" ); await ensureMothershipStorageState(); expect(fs.existsSync(stateFile)).toBe(true); expect(persistContext).toHaveBeenCalled(); }); });