324 lines
14 KiB
TypeScript

import { afterEach, expect, test, vi } from "vitest";
import { setAccessToken } from "@/shared/api/request";
import {
adminAddAgencyHost,
createBDLeader,
createCountry,
createCoinSeller,
createManager,
createRegion,
creditCoinSellerStock,
debitCoinSellerStock,
deleteAgency,
disableRegion,
listAgencies,
listBDs,
listCoinSellerSubApplications,
listCoinSellerSubSellers,
listCoinSellers,
listCountries,
listHosts,
listManagers,
listRegions,
getJob,
renameCountryCode,
replaceRegionCountries,
approveCoinSellerSubApplication,
rejectCoinSellerSubApplication,
setCoinSellerStatus,
updateBDLeaderPositionAlias,
updateCountry,
updateManager,
} from "./api";
afterEach(() => {
setAccessToken("");
vi.unstubAllGlobals();
});
test("host org list APIs use generated admin paths and filters", async () => {
vi.stubGlobal(
"fetch",
vi.fn(
async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 10, total: 0 } })),
),
);
await listBDs({
page: 1,
page_size: 10,
parent_leader_user_id: 21,
region_id: 7,
sort_by: "salary_wallet",
sort_direction: "asc",
status: "active",
});
await listAgencies({
keyword: "agency",
page: 2,
page_size: 10,
parent_bd_user_id: 31,
sort_by: "salary_wallet",
sort_direction: "desc",
});
await listManagers({
keyword: "manager",
page: 1,
page_size: 10,
region_id: 7,
status: "active",
});
await createManager({
canManageCrossRegion: false,
canBlockUser: false,
canGrantBadge: false,
canGrantVip: true,
contact: "+63",
targetUserId: "1003",
});
await updateManager("1003", {
canManageCrossRegion: true,
canBlockUser: false,
canGrantVehicle: true,
canGrantVip: false,
canTransferUserCountry: false,
contact: "+63",
status: "disabled",
});
await listHosts({ agency_id: 41, page: 1, page_size: 10, sort_by: "diamond", sort_direction: "desc" });
await listCoinSellers({
page: 1,
page_size: 10,
region_id: 7,
sort_by: "merchant_balance",
sort_direction: "desc",
status: "active",
});
await createBDLeader({
commandId: "bd-leader-test",
positionAlias: "Senior Admin",
targetUserId: "1002",
});
await updateBDLeaderPositionAlias("1002", {
commandId: "bd-leader-position-alias-test",
positionAlias: "Regional Admin",
});
await createCoinSeller({ commandId: "coin-seller-test", reason: "contact", targetUserId: "1001" });
await setCoinSellerStatus("1001", { commandId: "coin-seller-status-test", reason: "disable", status: "disabled" });
await creditCoinSellerStock("1001", {
coinAmount: 8000000,
commandId: "coin-seller-stock-test",
rechargeAmount: "100.000000",
type: "usdt_purchase",
});
await debitCoinSellerStock("1001", {
coinAmount: 1000,
commandId: "coin-seller-stock-debit-test",
rechargeAmount: "1.25",
reason: "deduct bad stock",
});
await adminAddAgencyHost(7001, {
commandId: "agency-add-host-test",
reason: "manual add",
targetUserId: "1004",
});
await deleteAgency(7001, { commandId: "agency-delete-test", reason: "cleanup" });
const [bdUrl, bdInit] = vi.mocked(fetch).mock.calls[0];
const [agencyUrl] = vi.mocked(fetch).mock.calls[1];
const [managerUrl, managerInit] = vi.mocked(fetch).mock.calls[2];
const [managerCreateUrl, managerCreateInit] = vi.mocked(fetch).mock.calls[3];
const [managerUpdateUrl, managerUpdateInit] = vi.mocked(fetch).mock.calls[4];
const [hostUrl] = vi.mocked(fetch).mock.calls[5];
const [coinSellerUrl, coinSellerInit] = vi.mocked(fetch).mock.calls[6];
const [bdLeaderCreateUrl, bdLeaderCreateInit] = vi.mocked(fetch).mock.calls[7];
const [bdLeaderAliasUrl, bdLeaderAliasInit] = vi.mocked(fetch).mock.calls[8];
const [coinSellerCreateUrl, coinSellerCreateInit] = vi.mocked(fetch).mock.calls[9];
const [coinSellerStatusUrl, coinSellerStatusInit] = vi.mocked(fetch).mock.calls[10];
const [coinSellerStockUrl, coinSellerStockInit] = vi.mocked(fetch).mock.calls[11];
const [coinSellerStockDebitUrl, coinSellerStockDebitInit] = vi.mocked(fetch).mock.calls[12];
const [agencyAddHostUrl, agencyAddHostInit] = vi.mocked(fetch).mock.calls[13];
const [agencyDeleteUrl, agencyDeleteInit] = vi.mocked(fetch).mock.calls[14];
expect(String(bdUrl)).toContain("/api/v1/admin/bds?");
expect(String(bdUrl)).toContain("parent_leader_user_id=21");
expect(String(bdUrl)).toContain("region_id=7");
expect(String(bdUrl)).toContain("sort_by=salary_wallet");
expect(String(bdUrl)).toContain("sort_direction=asc");
expect(String(bdUrl)).toContain("status=active");
expect(bdInit?.method).toBe("GET");
expect(String(agencyUrl)).toContain("/api/v1/admin/agencies?");
expect(String(agencyUrl)).toContain("parent_bd_user_id=31");
expect(String(agencyUrl)).toContain("sort_by=salary_wallet");
expect(String(agencyUrl)).toContain("sort_direction=desc");
expect(String(managerUrl)).toContain("/api/v1/admin/managers?");
expect(String(managerUrl)).toContain("keyword=manager");
expect(String(managerUrl)).toContain("region_id=7");
expect(String(managerUrl)).toContain("status=active");
expect(String(managerUrl)).not.toContain("parent_bd_user_id");
expect(managerInit?.method).toBe("GET");
expect(String(managerCreateUrl)).toContain("/api/v1/admin/managers");
expect(managerCreateInit?.method).toBe("POST");
expect(JSON.parse(String(managerCreateInit?.body))).toEqual({
canManageCrossRegion: false,
canBlockUser: false,
canGrantBadge: false,
canGrantVip: true,
contact: "+63",
targetUserId: "1003",
});
expect(String(managerUpdateUrl)).toContain("/api/v1/admin/managers/1003");
expect(managerUpdateInit?.method).toBe("PUT");
expect(JSON.parse(String(managerUpdateInit?.body))).toEqual({
canManageCrossRegion: true,
canBlockUser: false,
canGrantVehicle: true,
canGrantVip: false,
canTransferUserCountry: false,
contact: "+63",
status: "disabled",
});
expect(String(hostUrl)).toContain("/api/v1/admin/hosts?");
expect(String(hostUrl)).toContain("agency_id=41");
expect(String(hostUrl)).toContain("sort_by=diamond");
expect(String(hostUrl)).toContain("sort_direction=desc");
expect(String(coinSellerUrl)).toContain("/api/v1/admin/coin-sellers?");
expect(String(coinSellerUrl)).toContain("region_id=7");
expect(String(coinSellerUrl)).toContain("sort_by=merchant_balance");
expect(String(coinSellerUrl)).toContain("sort_direction=desc");
expect(String(coinSellerUrl)).toContain("status=active");
expect(coinSellerInit?.method).toBe("GET");
expect(String(bdLeaderCreateUrl)).toContain("/api/v1/admin/bd-leaders");
expect(bdLeaderCreateInit?.method).toBe("POST");
expect(JSON.parse(String(bdLeaderCreateInit?.body))).toMatchObject({ positionAlias: "Senior Admin" });
expect(JSON.parse(String(bdLeaderCreateInit?.body))).not.toHaveProperty("regionId");
expect(String(bdLeaderAliasUrl)).toContain("/api/v1/admin/bd-leaders/1002/position-alias");
expect(bdLeaderAliasInit?.method).toBe("PATCH");
expect(JSON.parse(String(bdLeaderAliasInit?.body))).toMatchObject({ positionAlias: "Regional Admin" });
expect(String(coinSellerCreateUrl)).toContain("/api/v1/admin/coin-sellers");
expect(coinSellerCreateInit?.method).toBe("POST");
expect(String(coinSellerStatusUrl)).toContain("/api/v1/admin/coin-sellers/1001/status");
expect(coinSellerStatusInit?.method).toBe("PATCH");
expect(String(coinSellerStockUrl)).toContain("/api/v1/admin/coin-sellers/1001/stock-credits");
expect(coinSellerStockInit?.method).toBe("POST");
expect(String(coinSellerStockDebitUrl)).toContain("/api/v1/admin/coin-sellers/1001/stock-debits");
expect(coinSellerStockDebitInit?.method).toBe("POST");
expect(String(agencyAddHostUrl)).toContain("/api/v1/admin/agencies/7001/hosts");
expect(agencyAddHostInit?.method).toBe("POST");
expect(JSON.parse(String(agencyAddHostInit?.body))).toMatchObject({
commandId: "agency-add-host-test",
targetUserId: "1004",
});
expect(String(agencyDeleteUrl)).toContain("/api/v1/admin/agencies/7001/delete");
expect(agencyDeleteInit?.method).toBe("POST");
expect(JSON.parse(String(agencyDeleteInit?.body))).toMatchObject({ commandId: "agency-delete-test" });
});
test("coin seller sub application APIs use generated admin paths", async () => {
vi.stubGlobal(
"fetch",
vi.fn(
async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 10, total: 0 } })),
),
);
await listCoinSellerSubSellers("3001", { page: 1, page_size: 10 });
await listCoinSellerSubApplications({
keyword: "163001",
page: 2,
page_size: 10,
parent_user_id: "3001",
status: "pending",
target_user_id: "3002",
});
await approveCoinSellerSubApplication("sub-app-1", {
commandId: "approve-sub-app-test",
reason: "ok",
});
await rejectCoinSellerSubApplication("sub-app-2", {
commandId: "reject-sub-app-test",
reason: "bad",
});
const [subSellerUrl, subSellerInit] = vi.mocked(fetch).mock.calls[0];
const [applicationUrl, applicationInit] = vi.mocked(fetch).mock.calls[1];
const [approveUrl, approveInit] = vi.mocked(fetch).mock.calls[2];
const [rejectUrl, rejectInit] = vi.mocked(fetch).mock.calls[3];
expect(String(subSellerUrl)).toContain("/api/v1/admin/coin-sellers/3001/sub-sellers?");
expect(String(subSellerUrl)).toContain("page=1");
expect(subSellerInit?.method).toBe("GET");
expect(String(applicationUrl)).toContain("/api/v1/admin/coin-seller-sub-applications?");
expect(String(applicationUrl)).toContain("keyword=163001");
expect(String(applicationUrl)).toContain("parent_user_id=3001");
expect(String(applicationUrl)).toContain("target_user_id=3002");
expect(String(applicationUrl)).toContain("status=pending");
expect(applicationInit?.method).toBe("GET");
expect(String(approveUrl)).toContain("/api/v1/admin/coin-seller-sub-applications/sub-app-1/approve");
expect(approveInit?.method).toBe("POST");
expect(JSON.parse(String(approveInit?.body))).toMatchObject({ commandId: "approve-sub-app-test" });
expect(String(rejectUrl)).toContain("/api/v1/admin/coin-seller-sub-applications/sub-app-2/reject");
expect(rejectInit?.method).toBe("POST");
expect(JSON.parse(String(rejectInit?.body))).toMatchObject({ commandId: "reject-sub-app-test" });
});
test("country and region APIs use generated admin paths", async () => {
vi.stubGlobal(
"fetch",
vi.fn(async () => new Response(JSON.stringify({ code: 0, data: { items: [], total: 0 } }))),
);
await listCountries({ enabled: true });
await createCountry({
countryCode: "US",
countryDisplayName: "United States",
countryName: "United States",
enabled: true,
});
await updateCountry(12, { countryDisplayName: "United States", countryName: "United States" });
await renameCountryCode(12, {
countryCode: "USA",
countryDisplayName: "United States",
countryName: "United States",
sortOrder: 10,
});
await getJob(99);
await listRegions({ status: "active" });
await createRegion({ countries: ["US"], name: "North America", regionCode: "NA" });
await replaceRegionCountries(7, { countries: ["US", "CA"] });
await disableRegion(7);
const [countryListUrl, countryListInit] = vi.mocked(fetch).mock.calls[0];
const [countryCreateUrl, countryCreateInit] = vi.mocked(fetch).mock.calls[1];
const [countryUpdateUrl, countryUpdateInit] = vi.mocked(fetch).mock.calls[2];
const [countryRenameUrl, countryRenameInit] = vi.mocked(fetch).mock.calls[3];
const [jobUrl, jobInit] = vi.mocked(fetch).mock.calls[4];
const [regionListUrl, regionListInit] = vi.mocked(fetch).mock.calls[5];
const [regionCreateUrl, regionCreateInit] = vi.mocked(fetch).mock.calls[6];
const [regionCountriesUrl, regionCountriesInit] = vi.mocked(fetch).mock.calls[7];
const [regionDisableUrl, regionDisableInit] = vi.mocked(fetch).mock.calls[8];
expect(String(countryListUrl)).toContain("/api/v1/admin/countries?");
expect(String(countryListUrl)).toContain("enabled=true");
expect(countryListInit?.method).toBe("GET");
expect(String(countryCreateUrl)).toContain("/api/v1/admin/countries");
expect(countryCreateInit?.method).toBe("POST");
expect(String(countryUpdateUrl)).toContain("/api/v1/admin/countries/12");
expect(countryUpdateInit?.method).toBe("PATCH");
expect(JSON.parse(String(countryUpdateInit?.body))).not.toHaveProperty("countryCode");
expect(String(countryRenameUrl)).toContain("/api/v1/admin/countries/12/rename-code");
expect(countryRenameInit?.method).toBe("POST");
expect(JSON.parse(String(countryRenameInit?.body))).toMatchObject({ countryCode: "USA", sortOrder: 10 });
expect(String(jobUrl)).toContain("/api/v1/jobs/99");
expect(jobInit?.method).toBe("GET");
expect(String(regionListUrl)).toContain("/api/v1/admin/regions?");
expect(String(regionListUrl)).toContain("status=active");
expect(regionListInit?.method).toBe("GET");
expect(String(regionCreateUrl)).toContain("/api/v1/admin/regions");
expect(regionCreateInit?.method).toBe("POST");
expect(String(regionCountriesUrl)).toContain("/api/v1/admin/regions/7/countries");
expect(regionCountriesInit?.method).toBe("PUT");
expect(String(regionDisableUrl)).toContain("/api/v1/admin/regions/7");
expect(regionDisableInit?.method).toBe("DELETE");
});