import { describe, expect, it } from "vitest"; import { RpaError } from "@/modules/rpa/errors"; import { RPAContext, resolveRPAContext } from "@/workers/rpa/kernel/context"; import { assertRPAContext, ensureArray, isRPAContext, snapshotContextContract, } from "@/workers/rpa/kernel/context-validator"; function mockPage(): object { return { locator: () => ({ filter: () => ({ nth: () => ({}) }), first: () => ({}), }), waitForTimeout: async () => undefined, url: () => "https://example.com", }; } describe("context-validator", () => { it("ensureArray:undefined → []", () => { expect(ensureArray(undefined)).toEqual([]); expect(ensureArray(null)).toEqual([]); expect(ensureArray([1])).toEqual([1]); }); it("resolveRPAContext:已是 context 时不再包一层", () => { const page = mockPage(); const ctx = new RPAContext(page as never); const resolved = resolveRPAContext(ctx); expect(resolved).toBe(ctx); expect(isRPAContext(resolved)).toBe(true); }); it("fromSession 误传 context 不再导致 page.locator 断裂", () => { const page = mockPage(); const ctx = new RPAContext(page as never); const wrapped = RPAContext.fromSession(ctx); expect(wrapped).toBe(ctx); expect(snapshotContextContract(wrapped).hasPage).toBe(true); }); it("assertRPAContext:缺 state 时 fail-fast", () => { const page = mockPage(); const broken = { page, selectors: {}, exec: {}, runtime: {}, getWidgetScrollAt: () => 0, setWidgetScrollAt: () => undefined, }; expect(() => assertRPAContext(broken)).toThrow(RpaError); }); });