hyapp-admin-platform/src/App.test.jsx
2026-06-25 13:48:35 +08:00

219 lines
7.8 KiB
JavaScript

import { render, screen } from "@testing-library/react";
import { afterEach, beforeEach, expect, test, vi } from "vitest";
import { MemoryRouter } from "react-router-dom";
import App from "@/app/App.jsx";
import { AppProviders } from "@/app/providers.jsx";
import { adminRoutes } from "@/app/router/routeConfig";
import { setAccessToken } from "@/shared/api/request";
beforeEach(() => {
window.localStorage.clear();
vi.stubGlobal(
"fetch",
vi.fn(async () => new Response(JSON.stringify({ code: 401, message: "unauthorized" }), { status: 401 })),
);
});
afterEach(() => {
vi.unstubAllGlobals();
});
test("renders login route", async () => {
renderWithRoute("/login");
expect(await screen.findByText("HYApp 管理平台")).toBeInTheDocument();
});
test("redirects protected route to login when unauthenticated", async () => {
renderWithRoute("/system/users");
expect(await screen.findByText("HYApp 管理平台")).toBeInTheDocument();
});
test("renders resource list route with an authenticated session", async () => {
setAccessToken("test-token");
vi.mocked(fetch).mockImplementation(async (input) => {
const url = String(input);
if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
return jsonResponse({
accessToken: "test-token",
permissions: ["resource:view"],
user: { userId: 1, username: "admin" },
});
}
if (url.includes("/v1/admin/apps")) {
return jsonResponse({ items: [{ appCode: "lalu", name: "Lalu" }], total: 1 });
}
if (url.includes("/v1/admin/navigation/menus")) {
return jsonResponse([]);
}
if (url.includes("/v1/admin/resources")) {
return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
}
return jsonResponse(null);
});
renderWithRoute("/resources");
expect((await screen.findAllByText("资源列表")).length).toBeGreaterThan(0);
});
test("renders cp config route with an authenticated session", async () => {
setAccessToken("test-token");
vi.mocked(fetch).mockImplementation(async (input) => {
const url = String(input);
if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
return jsonResponse({
accessToken: "test-token",
permissions: ["cp-config:view"],
user: { userId: 1, username: "admin" },
});
}
if (url.includes("/v1/admin/apps")) {
return jsonResponse({ items: [{ appCode: "lalu", name: "Lalu" }], total: 1 });
}
if (url.includes("/v1/admin/navigation/menus")) {
return jsonResponse([]);
}
if (url.includes("/v1/admin/resource-groups")) {
return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
}
if (url.includes("/v1/admin/activity/cp/config")) {
return jsonResponse({
appCode: "lalu",
relations: [
cpRelationFixture("cp", "CP", 1),
cpRelationFixture("brother", "兄弟", 5),
cpRelationFixture("sister", "姐妹", 5),
],
});
}
if (url.includes("/v1/admin/activity/cp/relationships")) {
return jsonResponse({
items: [
{
relationshipId: "cp_1001_1002",
relationType: "cp",
status: "active",
userA: { displayUserId: "1001", userId: "1001", username: "A" },
userB: { displayUserId: "1002", userId: "1002", username: "B" },
intimacyValue: 12000,
level: 2,
durationDays: 3,
gift: { giftId: "rose", giftName: "Rose", giftCount: 1, giftValue: 100 },
formedAtMs: 1760000000000,
},
],
page: 1,
pageSize: 50,
total: 1,
});
}
if (url.includes("/v1/admin/activity/cp/applications")) {
return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
}
return jsonResponse(null);
});
renderWithRoute("/activities/cp-config");
expect((await screen.findAllByText("CP配置")).length).toBeGreaterThan(0);
expect(await screen.findByText("已加载 1 条 · 共 1 条")).toBeInTheDocument();
expect(screen.queryByText("共 1 条")).not.toBeInTheDocument();
});
test("renders cp weekly rank route with an authenticated session", async () => {
setAccessToken("test-token");
vi.mocked(fetch).mockImplementation(async (input) => {
const url = String(input);
if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
return jsonResponse({
accessToken: "test-token",
permissions: ["cp-weekly-rank:view"],
user: { userId: 1, username: "admin" },
});
}
if (url.includes("/v1/admin/apps")) {
return jsonResponse({ items: [{ appCode: "lalu", name: "Lalu" }], total: 1 });
}
if (url.includes("/v1/admin/navigation/menus")) {
return jsonResponse([]);
}
if (url.includes("/v1/admin/resource-groups")) {
return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
}
if (url.includes("/v1/admin/activity/cp-weekly-rank/config")) {
return jsonResponse({
activityCode: "cp_weekly_rank",
enabled: true,
relationType: "cp",
rewards: [
{ rankNo: 1, resourceGroupId: 1001 },
{ rankNo: 2, resourceGroupId: 1002 },
{ rankNo: 3, resourceGroupId: 1003 },
],
topCount: 3,
});
}
if (url.includes("/v1/admin/activity/cp-weekly-rank/settlements")) {
return jsonResponse({
items: [
{
periodStartMs: 1760918400000,
periodEndMs: 1761523200000,
rankNo: 1,
relationshipId: "cp_1001_1002",
score: 12000,
settlementId: "settlement_1",
status: "granted",
userId: "1001",
},
],
total: 1,
});
}
return jsonResponse(null);
});
renderWithRoute("/activities/cp-weekly-rank");
expect((await screen.findAllByText("CP排行活动")).length).toBeGreaterThan(0);
expect(await screen.findByText("已发放")).toBeInTheDocument();
});
test("admin routes declare menu code and permission", () => {
expect(adminRoutes.length).toBeGreaterThan(0);
expect(adminRoutes.every((route) => route.menuCode && route.permission)).toBe(true);
});
function renderWithRoute(route) {
return render(
<AppProviders>
<MemoryRouter initialEntries={[route]}>
<App />
</MemoryRouter>
</AppProviders>,
);
}
function jsonResponse(data) {
return new Response(JSON.stringify({ code: 0, data }), { status: 200 });
}
function cpRelationFixture(relationType, displayName, maxCountPerUser) {
return {
relationType,
displayName,
maxCountPerUser,
applicationExpireHours: 24,
status: "active",
levels: Array.from({ length: 5 }, (_, index) => ({
level: index + 1,
intimacyThreshold: index * 10000,
rewardResourceGroupId: 0,
levelIconUrl: "",
status: "active",
})),
};
}