import { afterEach, expect, test, vi } from "vitest"; import { setAccessToken } from "@/shared/api/request"; import { createCoinAdjustment, createFullServerNoticeFanout, exportCoinSellerLedger, getGiftDiamondRatios, getWheelConfig, getWheelDrawSummary, listCoinAdjustments, listCoinSellerLedger, listWheelDraws, lookupCoinAdjustmentTarget, updateGiftDiamondRatios, updateWheelConfig, } from "./api"; afterEach(() => { setAccessToken(""); vi.unstubAllGlobals(); }); test("gift diamond ratio APIs use operations paths", async () => { vi.stubGlobal( "fetch", vi.fn(async () => new Response(JSON.stringify({ code: 0, data: { regionId: 1001, items: [] } }))), ); await getGiftDiamondRatios(1001); await updateGiftDiamondRatios({ regionId: 1001, ratios: { lucky: "40.00", normal: "30.00", super_lucky: "50.00" }, returnCoinRatios: { lucky: "10.00", normal: "30.00", super_lucky: "1.00" }, }); const [getUrl, getInit] = vi.mocked(fetch).mock.calls[0]; const [putUrl, putInit] = vi.mocked(fetch).mock.calls[1]; expect(String(getUrl)).toContain("/api/v1/admin/operations/gift-diamond-ratios?"); expect(String(getUrl)).toContain("region_id=1001"); expect(getInit?.method).toBe("GET"); expect(String(putUrl)).toContain("/api/v1/admin/operations/gift-diamond-ratios"); expect(putInit?.method).toBe("PUT"); expect(JSON.parse(String(putInit?.body))).toMatchObject({ regionId: 1001, ratios: { lucky: "40.00", normal: "30.00", super_lucky: "50.00" }, returnCoinRatios: { lucky: "10.00", normal: "30.00", super_lucky: "1.00" }, }); }); test("full server notice fanout API uses 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_active_users", }, }), ), ), ); await createFullServerNoticeFanout({ action_type: "app_h5", action_param: "https://example.com", batch_size: 500, command_id: "admin_notice_test", message_type: "system", summary: "今晚 23:00 维护", target_scope: "all_active_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", command_id: "admin_notice_test", message_type: "system", target_scope: "all_active_users", title: "维护通知", }); }); test("coin adjustment APIs use generated admin paths", async () => { vi.stubGlobal( "fetch", vi.fn( async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 20, total: 0 } })), ), ); await listCoinAdjustments({ page: 1, page_size: 20, user_keyword: "1001" }); await lookupCoinAdjustmentTarget("1001"); await createCoinAdjustment({ amount: 500, commandId: "coin-adjustment-test", reason: "运营发放", targetUserId: "1001", }); const [listUrl, listInit] = vi.mocked(fetch).mock.calls[0]; const [lookupUrl, lookupInit] = vi.mocked(fetch).mock.calls[1]; const [createUrl, createInit] = vi.mocked(fetch).mock.calls[2]; expect(String(listUrl)).toContain("/api/v1/admin/operations/coin-adjustments?"); expect(String(listUrl)).toContain("user_keyword=1001"); expect(listInit?.method).toBe("GET"); expect(String(lookupUrl)).toContain("/api/v1/admin/operations/coin-adjustments/target?"); expect(String(lookupUrl)).toContain("user_id=1001"); expect(lookupInit?.method).toBe("GET"); expect(String(createUrl)).toContain("/api/v1/admin/operations/coin-adjustments"); expect(createInit?.method).toBe("POST"); }); test("coin seller ledger API uses generated admin path and filters", async () => { vi.stubGlobal( "fetch", vi.fn( async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 20, total: 0 } })), ), ); await listCoinSellerLedger({ ledger_type: "seller_transfer", page: 1, page_size: 20, seller_user_id: "3001", }); const [listUrl, listInit] = vi.mocked(fetch).mock.calls[0]; expect(String(listUrl)).toContain("/api/v1/admin/operations/coin-seller-ledger?"); expect(String(listUrl)).toContain("seller_user_id=3001"); expect(String(listUrl)).toContain("ledger_type=seller_transfer"); expect(listInit?.method).toBe("GET"); }); test("coin seller ledger export API sends current filters without pagination", async () => { vi.stubGlobal( "fetch", vi.fn(async () => new Response("seller,amount\n", { status: 200 })), ); await exportCoinSellerLedger({ end_at_ms: "2000", ledger_type: "admin_stock_credit", seller_keyword: "HUNTER", start_at_ms: "1000", }); const [exportUrl, exportInit] = vi.mocked(fetch).mock.calls[0]; expect(String(exportUrl)).toContain("/api/v1/admin/operations/coin-seller-ledger/export?"); expect(String(exportUrl)).toContain("seller_keyword=HUNTER"); expect(String(exportUrl)).toContain("ledger_type=admin_stock_credit"); expect(String(exportUrl)).toContain("start_at_ms=1000"); expect(String(exportUrl)).toContain("end_at_ms=2000"); expect(String(exportUrl)).not.toContain("page="); expect(exportInit?.method).toBe("GET"); }); test("wheel APIs use activity paths and generated methods", async () => { vi.stubGlobal( "fetch", vi.fn(async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 20, total: 0 } }))), ); await getWheelConfig("default"); await updateWheelConfig({ draw_price_coins: 10000, effective_from_ms: 0, enabled: true, initial_pool_coins: 0, max_single_rtp_payout: 0, pool_rate_percent: 90, pool_reserve_coins: 0, settlement_window_draws: 1000, target_rtp_percent: 90, tiers: [ { display_name: "金币", enabled: true, metadata_json: "{}", probability_percent: 70, reward_coins: 10000, reward_count: 1, reward_id: "", reward_type: "coin", rtp_value_coins: 10000, tier_id: "coin", }, { display_name: "礼物", enabled: true, metadata_json: "{}", probability_percent: 20, reward_coins: 0, reward_count: 1, reward_id: "gift_1001", reward_type: "gift", rtp_value_coins: 5000, tier_id: "gift", }, { display_name: "装扮", enabled: true, metadata_json: "{}", probability_percent: 10, reward_coins: 0, reward_count: 1, reward_id: "dress_1001", reward_type: "dress", rtp_value_coins: 0, tier_id: "dress", }, ], wheel_id: "default", }); await listWheelDraws({ page: 1, page_size: 20, status: "granted", user_id: "1001", wheel_id: "default" }); await getWheelDrawSummary({ status: "granted", user_id: "1001", wheel_id: "default" }); const [getUrl, getInit] = vi.mocked(fetch).mock.calls[0]; const [putUrl, putInit] = vi.mocked(fetch).mock.calls[1]; const [drawsUrl, drawsInit] = vi.mocked(fetch).mock.calls[2]; const [summaryUrl, summaryInit] = vi.mocked(fetch).mock.calls[3]; expect(String(getUrl)).toContain("/api/v1/admin/activity/wheel/config?"); expect(String(getUrl)).toContain("wheel_id=default"); expect(getInit?.method).toBe("GET"); expect(String(putUrl)).toContain("/api/v1/admin/activity/wheel/config?"); expect(putInit?.method).toBe("PUT"); expect(JSON.parse(String(putInit?.body))).toMatchObject({ enabled: true, wheel_id: "default" }); expect(String(drawsUrl)).toContain("/api/v1/admin/activity/wheel/draws?"); expect(String(drawsUrl)).toContain("user_id=1001"); expect(String(drawsUrl)).toContain("status=granted"); expect(drawsInit?.method).toBe("GET"); expect(String(summaryUrl)).toContain("/api/v1/admin/activity/wheel/draw-summary?"); expect(summaryInit?.method).toBe("GET"); });