2026-06-22 20:59:41 +08:00

253 lines
9.0 KiB
TypeScript

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");
});