|
|
@@ -0,0 +1,109 @@
|
|
|
+import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
|
+import type { ProviderChainItem } from "@/types/message";
|
|
|
+
|
|
|
+const getSessionMock = vi.fn();
|
|
|
+const findSessionOriginChainMock = vi.fn();
|
|
|
+const findKeyListMock = vi.fn();
|
|
|
+
|
|
|
+const dbSelectMock = vi.fn();
|
|
|
+const dbFromMock = vi.fn();
|
|
|
+const dbWhereMock = vi.fn();
|
|
|
+const dbLimitMock = vi.fn();
|
|
|
+
|
|
|
+vi.mock("@/lib/auth", () => ({
|
|
|
+ getSession: getSessionMock,
|
|
|
+}));
|
|
|
+
|
|
|
+vi.mock("@/repository/message", () => ({
|
|
|
+ findSessionOriginChain: findSessionOriginChainMock,
|
|
|
+}));
|
|
|
+
|
|
|
+vi.mock("@/repository/key", () => ({
|
|
|
+ findKeyList: findKeyListMock,
|
|
|
+}));
|
|
|
+
|
|
|
+vi.mock("@/drizzle/db", () => ({
|
|
|
+ db: {
|
|
|
+ select: dbSelectMock,
|
|
|
+ },
|
|
|
+}));
|
|
|
+
|
|
|
+describe("getSessionOriginChain", () => {
|
|
|
+ beforeEach(() => {
|
|
|
+ vi.clearAllMocks();
|
|
|
+
|
|
|
+ dbSelectMock.mockReturnValue({ from: dbFromMock });
|
|
|
+ dbFromMock.mockReturnValue({ where: dbWhereMock });
|
|
|
+ dbWhereMock.mockReturnValue({ limit: dbLimitMock });
|
|
|
+ dbLimitMock.mockResolvedValue([{ id: 1 }]);
|
|
|
+
|
|
|
+ findKeyListMock.mockResolvedValue([{ key: "user-key-1" }]);
|
|
|
+ });
|
|
|
+
|
|
|
+ test("admin happy path: returns provider chain", async () => {
|
|
|
+ getSessionMock.mockResolvedValue({ user: { id: 1, role: "admin" } });
|
|
|
+
|
|
|
+ const chain: ProviderChainItem[] = [
|
|
|
+ {
|
|
|
+ id: 11,
|
|
|
+ name: "provider-a",
|
|
|
+ reason: "initial_selection",
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ findSessionOriginChainMock.mockResolvedValue(chain);
|
|
|
+
|
|
|
+ const { getSessionOriginChain } = await import("@/actions/session-origin-chain");
|
|
|
+ const result = await getSessionOriginChain("sess-admin");
|
|
|
+
|
|
|
+ expect(result).toEqual({ ok: true, data: chain });
|
|
|
+ expect(findSessionOriginChainMock).toHaveBeenCalledWith("sess-admin");
|
|
|
+ expect(findKeyListMock).not.toHaveBeenCalled();
|
|
|
+ expect(dbSelectMock).not.toHaveBeenCalled();
|
|
|
+ });
|
|
|
+
|
|
|
+ test("non-admin happy path: returns provider chain after ownership check", async () => {
|
|
|
+ getSessionMock.mockResolvedValue({ user: { id: 2, role: "user" } });
|
|
|
+
|
|
|
+ const chain: ProviderChainItem[] = [
|
|
|
+ {
|
|
|
+ id: 22,
|
|
|
+ name: "provider-b",
|
|
|
+ reason: "session_reuse",
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ findSessionOriginChainMock.mockResolvedValue(chain);
|
|
|
+
|
|
|
+ const { getSessionOriginChain } = await import("@/actions/session-origin-chain");
|
|
|
+ const result = await getSessionOriginChain("sess-user");
|
|
|
+
|
|
|
+ expect(result).toEqual({ ok: true, data: chain });
|
|
|
+ expect(findKeyListMock).toHaveBeenCalledWith(2);
|
|
|
+ expect(dbSelectMock).toHaveBeenCalledTimes(1);
|
|
|
+ expect(findSessionOriginChainMock).toHaveBeenCalledWith("sess-user");
|
|
|
+ });
|
|
|
+
|
|
|
+ test("unauthenticated: returns not logged in", async () => {
|
|
|
+ getSessionMock.mockResolvedValue(null);
|
|
|
+
|
|
|
+ const { getSessionOriginChain } = await import("@/actions/session-origin-chain");
|
|
|
+ const result = await getSessionOriginChain("sess-no-auth");
|
|
|
+
|
|
|
+ expect(result).toEqual({ ok: false, error: "未登录" });
|
|
|
+ expect(findSessionOriginChainMock).not.toHaveBeenCalled();
|
|
|
+ expect(findKeyListMock).not.toHaveBeenCalled();
|
|
|
+ expect(dbSelectMock).not.toHaveBeenCalled();
|
|
|
+ });
|
|
|
+
|
|
|
+ test("not found: returns ok with null data", async () => {
|
|
|
+ getSessionMock.mockResolvedValue({ user: { id: 1, role: "admin" } });
|
|
|
+ findSessionOriginChainMock.mockResolvedValue(null);
|
|
|
+
|
|
|
+ const { getSessionOriginChain } = await import("@/actions/session-origin-chain");
|
|
|
+ const result = await getSessionOriginChain("sess-not-found");
|
|
|
+
|
|
|
+ expect(result).toEqual({ ok: true, data: null });
|
|
|
+ expect(findSessionOriginChainMock).toHaveBeenCalledWith("sess-not-found");
|
|
|
+ expect(findKeyListMock).not.toHaveBeenCalled();
|
|
|
+ expect(dbSelectMock).not.toHaveBeenCalled();
|
|
|
+ });
|
|
|
+});
|