import { afterEach, expect, test, vi } from "vitest"; import { setAccessToken, setSelectedAppCode } from "@/shared/api/request"; import { createH5Link, createSystemMessagePushFanout, deleteH5Link, listH5Links, updateH5Link, updateH5Links, } from "./api"; afterEach(() => { setAccessToken(""); setSelectedAppCode("lalu"); vi.unstubAllGlobals(); }); test("H5 config API pins every request to its explicit app scope", async () => { setSelectedAppCode("lalu"); const link = { appCode: "huwaa", key: "achievement", label: "成就", updatedAtMs: 1000, url: "https://h5.example.com/achievement", }; vi.stubGlobal( "fetch", vi.fn(async (_url, init) => { const method = String(init?.method || "GET"); const data = method === "GET" || (method === "PUT" && !String(_url).endsWith("/achievement")) ? { items: [link], total: 1 } : method === "DELETE" ? { deleted: true } : link; return new Response(JSON.stringify({ code: 0, data }), { status: method === "POST" ? 201 : 200 }); }), ); const payload = { key: link.key, label: link.label, url: link.url }; await listH5Links(" Huwaa "); await createH5Link("huwaa", payload); await updateH5Links("huwaa", { items: [payload] }); await updateH5Link("huwaa", link.key, payload); await deleteH5Link("huwaa", link.key); const calls = vi.mocked(fetch).mock.calls; expect(calls.map(([, init]) => init?.method)).toEqual(["GET", "POST", "PUT", "PUT", "DELETE"]); calls.forEach(([, init]) => { expect(init?.headers).toMatchObject({ "X-App-Code": "huwaa" }); }); expect(String(calls[0][0])).toContain("/api/v1/admin/app-config/h5-links"); expect(String(calls[3][0])).toContain("/api/v1/admin/app-config/h5-links/achievement"); expect(JSON.parse(String(calls[1][1]?.body))).toEqual(payload); expect(JSON.parse(String(calls[2][1]?.body))).toEqual({ items: [payload] }); expect(JSON.parse(String(calls[3][1]?.body))).toEqual(payload); }); test("system message push fanout API keeps existing operations path", async () => { vi.stubGlobal( "fetch", vi.fn( async () => new Response( JSON.stringify({ code: 0, data: { command_id: "admin_notice_test", created: true, job_id: "mfan_test", message_type: "system", status: "pending", target_scope: "all_registered_users", }, }), ), ), ); await createSystemMessagePushFanout({ action_param: "https://example.com", action_type: "app_h5", batch_size: 500, message_type: "system", producer_event_type: "admin_full_server_notice", summary: "今晚 23:00 维护", target_scope: "all_registered_users", title: "维护通知", }); const [url, init] = vi.mocked(fetch).mock.calls[0]; expect(String(url)).toContain("/api/v1/admin/operations/full-server-notices/fanout"); expect(init?.method).toBe("POST"); expect(JSON.parse(String(init?.body))).toMatchObject({ action_param: "https://example.com", action_type: "app_h5", message_type: "system", producer_event_type: "admin_full_server_notice", target_scope: "all_registered_users", title: "维护通知", }); }); test("system message push fanout API preserves string user IDs", async () => { vi.stubGlobal( "fetch", vi.fn( async () => new Response( JSON.stringify({ code: 0, data: { command_id: "admin_notice_users", created: true, job_id: "mfan_users", message_type: "system", status: "pending", target_scope: "user_ids", }, }), ), ), ); await createSystemMessagePushFanout({ message_type: "system", summary: "指定用户维护", target_scope: "user_ids", title: "维护通知", user_ids: ["325379237278126080", "42"], }); const [, init] = vi.mocked(fetch).mock.calls[0]; expect(JSON.parse(String(init?.body))).toMatchObject({ target_scope: "user_ids", user_ids: ["325379237278126080", "42"], }); });