2026-07-11 02:26:23 +08:00

258 lines
9.6 KiB
TypeScript

import { afterEach, expect, test, vi } from "vitest";
import { setAccessToken, setSelectedAppCode } from "@/shared/api/request";
import { getVipConfig, getVipProgram, grantVipTrialCard, updateVipConfig, updateVipProgram } from "./api";
afterEach(() => {
setAccessToken("");
setSelectedAppCode("lalu");
vi.unstubAllGlobals();
});
test("vip program and level APIs normalize snake case responses", async () => {
setSelectedAppCode("fami");
vi.stubGlobal(
"fetch",
vi
.fn()
.mockResolvedValueOnce(
envelope({
config: {
app_code: "fami",
config_version: 3,
grant_mode: "trial_card",
level_count: 9,
program_type: "tiered_privilege_v1",
status: "active",
trial_card_enabled: true,
upgrade_expiry_policy: "replace_from_now",
},
benefits: [
{
auto_equip: false,
benefit_code: "anti_kick",
benefit_type: "function",
execution_scope: "room",
metadata_json: "{}",
name: "防踢",
resource_id: 0,
resource_type: "",
sort_order: 320,
status: "active",
trial_enabled: true,
unlock_level: 9,
},
],
}),
)
.mockResolvedValueOnce(
envelope({
levels: [
{
benefits: [
{
benefit_code: "anti_kick",
benefit_type: "function",
unlock_level: 9,
name: "防踢",
resource_id: 0,
resource_type: "",
execution_scope: "room",
auto_equip: false,
metadata_json: "{}",
sort_order: 10,
status: "active",
trial_enabled: true,
},
{
auto_equip: false,
benefit_code: "daily_coin_rebate",
benefit_type: "function",
execution_scope: "wallet",
metadata_json: "{}",
name: "金币返现",
resource_id: 0,
resource_type: "",
sort_order: 20,
status: "active",
trial_enabled: true,
unlock_level: 6,
},
],
duration_ms: 2592000000,
level: 9,
name: "VIP9",
price_coin: 9000,
reward_resource_group_id: 99,
sort_order: 90,
status: "active",
},
],
server_time_ms: 1780000000000,
}),
),
);
const program = await getVipProgram();
const config = await getVipConfig();
expect(program).toMatchObject({
appCode: "fami",
benefitInheritancePolicy: "target_only",
configVersion: 3,
grantMode: "trial_card",
levelCount: 9,
programType: "tiered_privilege_v1",
trialCardEnabled: true,
upgradeExpiryPolicy: "replace_from_now",
});
expect(program.benefits).toEqual([
expect.objectContaining({ benefitCode: "anti_kick", executionScope: "room", unlockLevel: 9 }),
]);
expect(config.levels[0]).toMatchObject({
durationMs: 2592000000,
level: 9,
priceCoin: 9000,
rewardResourceGroupId: 99,
});
expect(config.levels[0].benefits[0]).toEqual({
benefitCode: "anti_kick",
benefitType: "function",
unlockLevel: 9,
name: "防踢",
resourceId: 0,
resourceType: "",
executionScope: "room",
autoEquip: false,
metadataJson: "{}",
sortOrder: 10,
status: "active",
trialEnabled: true,
});
expect(config.levels[0].benefits[1]).toMatchObject({
benefitCode: "daily_coin_rebate",
trialEnabled: false,
});
expect(requestHeaders(vi.mocked(fetch).mock.calls[0][1])["X-App-Code"]).toBe("fami");
});
test("vip updates and trial grant use generated contract paths", async () => {
setSelectedAppCode("fami");
vi.stubGlobal(
"fetch",
vi
.fn()
.mockResolvedValueOnce(
envelope({ appCode: "fami", levelCount: 9, programType: "tiered_privilege_v1", status: "active" }),
)
.mockResolvedValueOnce(envelope({ levels: [] }))
.mockResolvedValueOnce(envelope({ transactionId: "trial_1" }, 201)),
);
await updateVipProgram({
benefitInheritancePolicy: "target_only",
downgradePurchasePolicy: "reject",
grantMode: "trial_card",
levelCount: 9,
programType: "tiered_privilege_v1",
sameLevelExpiryPolicy: "extend_remaining",
status: "active",
trialCardEnabled: true,
upgradeExpiryPolicy: "replace_from_now",
});
await updateVipConfig({
levels: [
{
benefits: [
{
benefitCode: "room_entry_notice",
benefitType: "function",
unlockLevel: 2,
name: "VIP进房通知",
resourceId: 0,
resourceType: "",
executionScope: "room",
autoEquip: false,
metadataJson: "{}",
sortOrder: 10,
status: "active",
trialEnabled: true,
},
{
benefitCode: "daily_coin_rebate",
benefitType: "function",
unlockLevel: 6,
name: "金币返现",
resourceId: 0,
resourceType: "",
executionScope: "wallet",
autoEquip: false,
metadataJson: "{}",
sortOrder: 20,
status: "active",
trialEnabled: true,
},
],
durationMs: 2592000000,
level: 2,
name: "VIP2",
priceCoin: 2000,
requiredRechargeCoinAmount: 0,
rewardResourceGroupId: 22,
sortOrder: 20,
status: "active",
},
],
});
await grantVipTrialCard({
commandId: "vip-trial-card-grant-test",
durationMs: 20 * 24 * 60 * 60 * 1000,
level: 5,
reason: "manual",
targetUserId: "318705991371722752",
});
const [programUrl, programInit] = vi.mocked(fetch).mock.calls[0];
const [configUrl, configInit] = vi.mocked(fetch).mock.calls[1];
const [grantUrl, grantInit] = vi.mocked(fetch).mock.calls[2];
expect(String(programUrl)).toContain("/api/v1/admin/activity/vip-program");
expect(programInit?.method).toBe("PUT");
expect(requestBody(programInit)).toMatchObject({
config: {
levelCount: 9,
programType: "tiered_privilege_v1",
status: "active",
grantMode: "trial_card",
benefitInheritancePolicy: "target_only",
upgradeExpiryPolicy: "replace_from_now",
},
});
expect(String(configUrl)).toContain("/api/v1/admin/activity/vip-levels");
expect(configInit?.method).toBe("PUT");
expect(requestBody(configInit)).toMatchObject({
levels: [
expect.objectContaining({
benefits: [
expect.objectContaining({ benefitCode: "room_entry_notice" }),
expect.objectContaining({ benefitCode: "daily_coin_rebate", trialEnabled: false }),
],
}),
],
});
expect(String(grantUrl)).toContain("/api/v1/admin/activity/vip-trial-card-grants");
expect(grantInit?.method).toBe("POST");
expect(requestBody(grantInit)).toMatchObject({ durationMs: 1728000000, level: 5 });
expect(requestBody(grantInit)).not.toHaveProperty("resourceId");
});
function envelope(data: unknown, status = 200) {
return new Response(JSON.stringify({ code: 0, data }), { status });
}
function requestHeaders(init: RequestInit | undefined): Record<string, string> {
return (init?.headers || {}) as Record<string, string>;
}
function requestBody(init: RequestInit | undefined): Record<string, unknown> {
return JSON.parse(String(init?.body || "{}")) as Record<string, unknown>;
}