hyapp-admin-platform/finance/src/FinanceApp.test.jsx

115 lines
4.4 KiB
JavaScript

import { render, screen, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, expect, test, vi } from "vitest";
import { ToastProvider } from "@/shared/ui/ToastProvider.jsx";
import { FinanceApp } from "./FinanceApp.jsx";
import {
fetchFinanceOptions,
fetchFinanceRechargeApps,
fetchFinanceRechargeOverview,
fetchFinanceRechargeSummaries,
fetchFinanceSession,
listFinanceCoinSellerRechargeOrders,
listFinanceRechargeDetails,
listFinanceRechargeRegions,
listFinanceWithdrawalApplications,
} from "./api.js";
import { EMPTY_RECHARGE_OVERVIEW, EMPTY_RECHARGE_SUMMARY } from "./format.js";
vi.mock("./api.js", () => ({
approveFinanceWithdrawalApplication: vi.fn(),
createFinanceCoinSellerRechargeOrder: vi.fn(),
exportFinanceRechargeBills: vi.fn(),
fetchFinanceOptions: vi.fn(),
fetchFinanceRechargeApps: vi.fn(),
fetchFinanceRechargeOverview: vi.fn(),
fetchFinanceRechargeSummaries: vi.fn(),
fetchFinanceSession: vi.fn(),
grantFinanceCoinSellerRechargeOrder: vi.fn(),
getFinanceCoinSellerRechargeExchangeRate: vi.fn(),
getFinanceUSDTAddresses: vi.fn(),
listFinanceCoinSellerRechargeOrders: vi.fn(),
listFinanceRechargeDetails: vi.fn(),
listFinanceRechargeRegions: vi.fn(),
listFinanceWithdrawalApplications: vi.fn(),
rejectFinanceWithdrawalApplication: vi.fn(),
refreshFinanceGoogleRechargePaid: vi.fn(),
replaceFinanceCoinSellerRechargeExchangeRate: vi.fn(),
upsertFinanceUSDTAddress: vi.fn(),
quoteFinanceCoinSellerRechargeOrder: vi.fn(),
verifyFinanceCoinSellerRechargeOrder: vi.fn(),
verifyFinanceCoinSellerRechargeReceipt: vi.fn()
}));
const defaultSession = {
canAccessFinance: true,
canAuditWithdrawalApplications: false,
canConfigureCoinSellerRechargeExchangeRate: false,
canCreateCoinSellerRechargeOrder: false,
canGrantCoinSellerRechargeOrder: false,
canUpdateUSDTAddress: false,
canVerifyCoinSellerRechargeOrder: false,
canViewAppRechargeDetails: false,
canViewCoinSellerRechargeOrders: false,
canViewWithdrawalApplications: true,
permissions: ["finance-withdrawal:view"],
user: { account: "admin", name: "admin" }
};
beforeEach(() => {
vi.mocked(fetchFinanceOptions).mockResolvedValue({ apps: [{ appCode: "lalu", appName: "lalu" }] });
vi.mocked(fetchFinanceRechargeApps).mockResolvedValue([{ appCode: "lalu", appName: "Lalu" }]);
vi.mocked(fetchFinanceRechargeOverview).mockResolvedValue(EMPTY_RECHARGE_OVERVIEW);
vi.mocked(fetchFinanceRechargeSummaries).mockResolvedValue({ merged: EMPTY_RECHARGE_SUMMARY, perApp: [] });
vi.mocked(fetchFinanceSession).mockResolvedValue(defaultSession);
vi.mocked(listFinanceCoinSellerRechargeOrders).mockResolvedValue({ items: [], page: 1, pageSize: 50, total: 0 });
vi.mocked(listFinanceRechargeDetails).mockResolvedValue({ items: [], page: 1, pageSize: 50, total: 0 });
vi.mocked(listFinanceRechargeRegions).mockResolvedValue([]);
vi.mocked(listFinanceWithdrawalApplications).mockResolvedValue({ items: [], page: 1, pageSize: 50, total: 0 });
});
afterEach(() => {
vi.restoreAllMocks();
vi.clearAllMocks();
window.history.pushState(null, "", "/");
});
test("preserves the finance entry when the expired session asks the user to log in again", async () => {
vi.mocked(fetchFinanceSession).mockRejectedValueOnce(new Error("登录已失效"));
window.history.pushState(null, "", "/finance/?view=rechargeDetails");
render(
<ToastProvider>
<FinanceApp />
</ToastProvider>
);
expect(await screen.findByRole("link", { name: "重新登录" })).toHaveAttribute(
"href",
"/login?redirect=%2Ffinance%2F%3Fview%3DrechargeDetails"
);
});
test("defaults recharge finance views to yesterday in China timezone", async () => {
vi.spyOn(Date, "now").mockReturnValue(Date.UTC(2026, 6, 8, 4));
vi.mocked(fetchFinanceSession).mockResolvedValue({
...defaultSession,
canViewAppRechargeDetails: true,
permissions: ["finance-recharge-detail:view"]
});
render(
<ToastProvider>
<FinanceApp />
</ToastProvider>
);
const yesterdayButton = await screen.findByRole("button", { name: "昨天" });
expect(yesterdayButton).toHaveClass("is-on");
expect(screen.getByRole("button", { name: "今天" })).toBeInTheDocument();
await waitFor(() => expect(listFinanceRechargeDetails).toHaveBeenCalled());
const [query] = vi.mocked(listFinanceRechargeDetails).mock.calls.at(-1);
expect(query.start_at_ms).toBe(Date.UTC(2026, 6, 6, 16));
expect(query.end_at_ms).toBe(Date.UTC(2026, 6, 7, 16));
});