154 lines
6.4 KiB
JavaScript
154 lines
6.4 KiB
JavaScript
import { afterEach, expect, test, vi } from "vitest";
|
|
import { setAccessToken } from "@/shared/api/request";
|
|
import {
|
|
approveFinanceApplication,
|
|
approveFinanceWithdrawalApplication,
|
|
createFinanceApplication,
|
|
fetchFinanceApplicationOptions,
|
|
filterOperationsByPermissions,
|
|
listFinanceApplications,
|
|
listFinanceRechargeDetails,
|
|
listMyFinanceApplications,
|
|
listFinanceWithdrawalApplications,
|
|
rejectFinanceApplication,
|
|
rejectFinanceWithdrawalApplication
|
|
} from "./api.js";
|
|
import { FINANCE_OPERATIONS } from "./constants.js";
|
|
|
|
afterEach(() => {
|
|
setAccessToken("");
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
test("finance application APIs use generated endpoint paths", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async (url) => {
|
|
if (String(url).includes("/admin/apps")) {
|
|
return new Response(JSON.stringify({ code: 0, data: { items: [{ appCode: "lalu", appName: "lalu" }], total: 1 } }));
|
|
}
|
|
if (String(url).includes("/applications?")) {
|
|
return new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 50, total: 0 } }));
|
|
}
|
|
if (String(url).includes("/applications/mine?")) {
|
|
return new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 50, total: 0 } }));
|
|
}
|
|
if (String(url).includes("/withdrawal-applications?")) {
|
|
return new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 50, total: 0 } }));
|
|
}
|
|
return new Response(JSON.stringify({ code: 0, data: { id: 12 } }));
|
|
})
|
|
);
|
|
|
|
const options = await fetchFinanceApplicationOptions();
|
|
await listFinanceApplications({ page: 1, page_size: 50, status: "pending" });
|
|
await listMyFinanceApplications({ page: 1, page_size: 50 });
|
|
await listFinanceWithdrawalApplications({ page: 1, page_size: 50 });
|
|
await createFinanceApplication({
|
|
appCode: "lalu",
|
|
coinAmount: 100,
|
|
operation: "coin_seller_coin_credit",
|
|
rechargeAmount: 10,
|
|
targetUserId: "10001"
|
|
});
|
|
await approveFinanceApplication(12, { auditRemark: "ok" });
|
|
await rejectFinanceApplication(13, { auditRemark: "bad" });
|
|
await approveFinanceWithdrawalApplication(14, { auditImageUrl: "https://cdn.example.com/pay.png", auditRemark: "ok" });
|
|
await rejectFinanceWithdrawalApplication(15, { auditRemark: "bad" });
|
|
|
|
const calls = vi.mocked(fetch).mock.calls;
|
|
expect(options.apps).toEqual([{ appCode: "lalu", appName: "lalu" }]);
|
|
expect(options.operations.map((item) => item.label)).toEqual([
|
|
"增加用户金币",
|
|
"减少用户金币",
|
|
"用户钱包扣减",
|
|
"用户钱包增加",
|
|
"增加币商金币",
|
|
"减少币商金币"
|
|
]);
|
|
expect(String(calls[0][0])).toContain("/api/v1/admin/apps");
|
|
expect(calls[0][1]?.method).toBe("GET");
|
|
expect(String(calls[1][0])).toContain("/api/v1/admin/finance/applications?");
|
|
expect(String(calls[1][0])).toContain("status=pending");
|
|
expect(calls[1][1]?.method).toBe("GET");
|
|
expect(String(calls[2][0])).toContain("/api/v1/admin/finance/applications/mine?");
|
|
expect(calls[2][1]?.method).toBe("GET");
|
|
expect(String(calls[3][0])).toContain("/api/v1/admin/finance/withdrawal-applications?");
|
|
expect(calls[3][1]?.method).toBe("GET");
|
|
expect(String(calls[4][0])).toContain("/api/v1/admin/finance/applications");
|
|
expect(calls[4][1]?.method).toBe("POST");
|
|
expect(JSON.parse(String(calls[4][1]?.body))).toMatchObject({ appCode: "lalu", operation: "coin_seller_coin_credit" });
|
|
expect(String(calls[5][0])).toContain("/api/v1/admin/finance/applications/12/approve");
|
|
expect(calls[5][1]?.method).toBe("POST");
|
|
expect(JSON.parse(String(calls[5][1]?.body))).toEqual({ auditRemark: "ok" });
|
|
expect(String(calls[6][0])).toContain("/api/v1/admin/finance/applications/13/reject");
|
|
expect(calls[6][1]?.method).toBe("POST");
|
|
expect(JSON.parse(String(calls[6][1]?.body))).toEqual({ auditRemark: "bad" });
|
|
expect(String(calls[7][0])).toContain("/api/v1/admin/finance/withdrawal-applications/14/approve");
|
|
expect(calls[7][1]?.method).toBe("POST");
|
|
expect(JSON.parse(String(calls[7][1]?.body))).toEqual({ auditImageUrl: "https://cdn.example.com/pay.png", auditRemark: "ok" });
|
|
expect(String(calls[8][0])).toContain("/api/v1/admin/finance/withdrawal-applications/15/reject");
|
|
expect(calls[8][1]?.method).toBe("POST");
|
|
expect(JSON.parse(String(calls[8][1]?.body))).toEqual({ auditRemark: "bad" });
|
|
});
|
|
|
|
test("filters operation options by backend-configured permissions", () => {
|
|
const allowed = filterOperationsByPermissions(FINANCE_OPERATIONS, [
|
|
"finance-operation:user-coin-credit",
|
|
"finance-operation:coin-seller-coin-debit"
|
|
]);
|
|
|
|
expect(allowed.map((item) => item.value)).toEqual(["user_coin_credit", "coin_seller_coin_debit"]);
|
|
});
|
|
|
|
test("finance recharge details query every app with app header and merge by recharge time", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async (url, init) => {
|
|
const appCode = init?.headers?.["X-App-Code"];
|
|
return new Response(
|
|
JSON.stringify({
|
|
code: 0,
|
|
data: {
|
|
items: [
|
|
{
|
|
appCode,
|
|
coinAmount: appCode === "aslan" ? 2000 : 1000,
|
|
createdAtMs: appCode === "aslan" ? 1760003600000 : 1760000000000,
|
|
exchangeCoinAmount: appCode === "aslan" ? 2000 : 1000,
|
|
exchangeUsdMinorAmount: appCode === "aslan" ? 200 : 100,
|
|
rechargeType: "google_play_recharge",
|
|
status: "succeeded",
|
|
transactionId: `${appCode}-tx`,
|
|
usdMinorAmount: appCode === "aslan" ? 200 : 100,
|
|
userId: "10001"
|
|
}
|
|
],
|
|
page: 1,
|
|
pageSize: 2,
|
|
total: 1
|
|
}
|
|
})
|
|
);
|
|
})
|
|
);
|
|
|
|
const page = await listFinanceRechargeDetails(
|
|
{ page: 1, page_size: 2, start_at_ms: 1760000000000, status: "succeeded" },
|
|
[
|
|
{ appCode: "lalu", appName: "lalu" },
|
|
{ appCode: "aslan", appName: "aslan" }
|
|
]
|
|
);
|
|
|
|
const calls = vi.mocked(fetch).mock.calls;
|
|
expect(page.total).toBe(2);
|
|
expect(page.items.map((item) => item.transactionId)).toEqual(["aslan-tx", "lalu-tx"]);
|
|
expect(calls).toHaveLength(2);
|
|
expect(calls.map(([, init]) => init?.headers?.["X-App-Code"])).toEqual(["lalu", "aslan"]);
|
|
expect(String(calls[0][0])).toContain("/api/v1/admin/payment/recharge-bills?");
|
|
expect(String(calls[0][0])).toContain("page_size=2");
|
|
expect(String(calls[0][0])).toContain("status=succeeded");
|
|
expect(String(calls[0][0])).toContain("start_at_ms=1760000000000");
|
|
});
|