import { readFileSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, it } from "vitest"; import { parseRecordArgs, resolveOutputBasename, resolveStoragePath, shouldEnforceGd15, } from "@/scripts/record-mothership"; import { isForbiddenQuoteUrl } from "@/lib/rpa/env"; const SCRIPT_PATH = join(process.cwd(), "scripts", "record-mothership.sh"); describe("record-mothership.sh (task-121)", () => { const content = readFileSync(SCRIPT_PATH, "utf8"); it("存在且包含 headed 与 codegen 启动", () => { expect(content).toContain("RPA_HEADLESS=false"); expect(content).toContain("playwright"); expect(content).toContain("codegen"); }); it("禁止 GD-15 黑名单 URL", () => { expect(content).toContain("dashboard.mothership.com"); expect(content).toContain("www.mothership.com/quote"); expect(content).toContain("check_url"); }); it("产出录制脚本与 storageState 路径", () => { expect(content).toContain(".rpa/recordings"); expect(content).toContain("mothership-storage.json"); expect(content).toContain("--save-storage"); }); }); const TS_SCRIPT_PATH = join(process.cwd(), "scripts", "record-mothership.ts"); describe("record-mothership.ts (Windows 跨平台)", () => { const content = readFileSync(TS_SCRIPT_PATH, "utf8"); it("存在且包含 headed codegen 与 GD-15 校验", () => { expect(content).toContain('RPA_HEADLESS: "false"'); expect(content).toContain("playwright"); expect(content).toContain("codegen"); expect(content).toContain("isForbiddenQuoteUrl"); }); it("产出录制脚本与 storageState 路径", () => { expect(content).toContain(".rpa/recordings"); expect(content).toContain("mothership-storage.json"); expect(content).toContain("--save-storage"); }); it("支持 --logged-in 独立产物前缀与 storage", () => { expect(content).toContain("--logged-in"); expect(content).toContain("mothership-logged-in-"); expect(content).toContain("mothership-logged-in-storage.json"); }); }); describe("record-mothership parseRecordArgs / GD-15 分模式", () => { it("默认匿名;--logged-in / --login 切换模式", () => { expect(parseRecordArgs(["node", "record-mothership.ts"]).mode).toBe( "anonymous", ); expect( parseRecordArgs(["node", "record-mothership.ts", "--logged-in"]).mode, ).toBe("logged-in"); expect( parseRecordArgs(["node", "record-mothership.ts", "--login"]).mode, ).toBe("logged-in"); }); it("解析起始 URL 与 help", () => { const withUrl = parseRecordArgs([ "node", "x", "--logged-in", "https://dashboard.mothership.com/", ]); expect(withUrl.mode).toBe("logged-in"); expect(withUrl.startUrl).toBe("https://dashboard.mothership.com/"); expect(parseRecordArgs(["node", "x", "--help"]).help).toBe(true); }); it("登录后产物前缀与 storage 路径隔离", () => { expect(resolveOutputBasename("logged-in", "20260715-120000")).toBe( "mothership-logged-in-20260715-120000.js", ); expect(resolveOutputBasename("anonymous", "20260715-120000")).toBe( "mothership-20260715-120000.js", ); expect(resolveStoragePath("logged-in").replace(/\\/g, "/")).toMatch( /mothership-logged-in-storage\.json$/, ); expect(resolveStoragePath("anonymous").replace(/\\/g, "/")).toMatch( /mothership-storage\.json$/, ); }); it("仅匿名模式强制 GD-15;登录后允许 dashboard URL", () => { expect(shouldEnforceGd15("anonymous")).toBe(true); expect(shouldEnforceGd15("logged-in")).toBe(false); const dash = "https://dashboard.mothership.com/quotes/new"; expect(isForbiddenQuoteUrl(dash)).toBe(true); // 登录模式不执行 GD-15 exit:逻辑门为 shouldEnforceGd15 && isForbidden expect(shouldEnforceGd15("logged-in") && isForbiddenQuoteUrl(dash)).toBe( false, ); expect(shouldEnforceGd15("anonymous") && isForbiddenQuoteUrl(dash)).toBe( true, ); }); });