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( , ); } 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", })), }; }