You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/__tests__/workers/rpa/parked-quote-session.test.ts

93 lines
3.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import type { BrowserContext, Page } from "playwright";
vi.mock("@/workers/rpa/page-prep", () => ({
dismissCookieConsent: vi.fn().mockResolvedValue(undefined),
scrollQuoteWidgetIntoView: vi.fn().mockResolvedValue(undefined),
}));
import {
hasParkedQuoteSession,
parkQuoteSession,
preheatParkedQuoteSession,
releaseAllParkedQuoteSessions,
releaseParkedQuoteSession,
takeParkedQuoteSession,
canPersistParkedQuoteSession,
getParkedQuoteSessionTtlMs,
sweepExpiredParkedSessions,
} from "@/workers/rpa/parked-quote-session";
function mockSession(id: string) {
const page = {
close: vi.fn().mockResolvedValue(undefined),
} as unknown as Page;
const context = {
close: vi.fn().mockResolvedValue(undefined),
} as unknown as BrowserContext;
return { id, page, context };
}
describe("parked-quote-session", () => {
beforeEach(async () => {
vi.stubEnv("RPA_WORKER_ID", "test-worker-1");
await releaseAllParkedQuoteSessions();
});
afterEach(async () => {
await releaseAllParkedQuoteSessions();
vi.unstubAllEnvs();
});
it("park → take 接管同一会话", async () => {
const { id, page, context } = mockSession("sess-a");
await parkQuoteSession(id, page, context);
expect(hasParkedQuoteSession(id)).toBe(true);
const taken = await takeParkedQuoteSession(id);
expect(taken?.page).toBe(page);
expect(hasParkedQuoteSession(id)).toBe(false);
});
it("release 关闭 page/context", async () => {
const { id, page, context } = mockSession("sess-b");
await parkQuoteSession(id, page, context);
expect(await releaseParkedQuoteSession(id)).toBe(true);
expect(page.close).toHaveBeenCalled();
expect(context.close).toHaveBeenCalled();
});
it("take 不存在的 session 返回 null", async () => {
expect(await takeParkedQuoteSession("missing")).toBeNull();
});
it("preheat 对驻留 session 返回 true", async () => {
const { id, page, context } = mockSession("sess-c");
await parkQuoteSession(id, page, context);
expect(await preheatParkedQuoteSession(id)).toBe(true);
});
it("canPersistParkedQuoteSession 需 RPA_WORKER_ID", () => {
vi.stubEnv("RPA_WORKER_ID", "");
expect(canPersistParkedQuoteSession()).toBe(false);
vi.stubEnv("RPA_WORKER_ID", "w1");
expect(canPersistParkedQuoteSession()).toBe(true);
});
it("自定义 ttlMs:过期后 sweep 释放", async () => {
vi.useFakeTimers();
const { id, page, context } = mockSession("sess-ttl");
await parkQuoteSession(id, page, context, { ttlMs: 5_000 });
expect(getParkedQuoteSessionTtlMs(id)).toBe(5_000);
expect(hasParkedQuoteSession(id)).toBe(true);
vi.advanceTimersByTime(5_001);
expect(sweepExpiredParkedSessions()).toBe(1);
// release 为 fire-and-forget,等微任务关掉 page
await Promise.resolve();
await Promise.resolve();
expect(hasParkedQuoteSession(id)).toBe(false);
expect(page.close).toHaveBeenCalled();
vi.useRealTimers();
});
});