import { describe, it, expect, vi } from "vitest"; import { ascending, filterTree, filterNoPermissionTree, isOneOfArray, getParentPaths, findRouteByPath, handleAliveRoute, formatFlatteningRoutes, formatTwoStageRoutes, initRouter, getTopMenu, addPathMatch, getHistoryMode, addAsyncRoutes, hasAuth, getAuths } from "../utils"; import { RouteRecordRaw } from "vue-router"; import { storageLocal } from "@pureadmin/utils"; import { usePermissionStoreHook } from "@/store/modules/permission"; import { useMultiTagsStoreHook } from "@/store/modules/multiTags"; describe("Router Utils", () => { /** * @description 测试 ascending 函数 * @function ascending * @test 验证路由按 meta.rank 升序排序 */ describe("ascending", () => { it("should sort routes by meta.rank in ascending order", () => { const routes = [ { meta: { rank: 3 } }, { meta: { rank: 1 } }, { meta: { rank: 2 } } ]; const result = ascending(routes); expect(result[0].meta.rank).toBe(1); expect(result[1].meta.rank).toBe(2); expect(result[2].meta.rank).toBe(3); }); it("should assign rank if not provided", () => { const routes = [{ name: "Home", path: "/" }, { name: "About" }]; const result = ascending(routes); expect(result[0].meta.rank).toBe(2); expect(result[1].meta.rank).toBe(3); }); }); /** * @description 测试 filterTree 函数 * @function filterTree * @test 验证过滤掉 meta.showLink 为 false 的路由 */ describe("filterTree", () => { it("should filter out routes with meta.showLink set to false", () => { const routes = [ { meta: { showLink: true } }, { meta: { showLink: false } }, { meta: { showLink: true } } ]; const result = filterTree(routes); expect(result.length).toBe(2); expect(result[0].meta.showLink).toBe(true); expect(result[1].meta.showLink).toBe(true); }); }); /** * @description 测试 filterNoPermissionTree 函数 * @function filterNoPermissionTree * @test 验证过滤掉无权限的路由 */ describe("filterNoPermissionTree", () => { it("should filter out routes without permission", () => { const routes = [ { meta: { roles: ["admin"] } }, { meta: { roles: ["user"] } }, { meta: { roles: [] } } ]; vi.spyOn(storageLocal(), "getItem").mockReturnValue({ roles: ["admin"] }); const result = filterNoPermissionTree(routes); expect(result.length).toBe(1); expect(result[0].meta.roles).toEqual(["admin"]); }); }); /** * @description 测试 isOneOfArray 函数 * @function isOneOfArray * @test 验证两个数组是否存在交集 */ describe("isOneOfArray", () => { it("should return true if arrays have common elements", () => { expect(isOneOfArray(["admin", "user"], ["user", "guest"])).toBe(true); }); it("should return false if arrays have no common elements", () => { expect(isOneOfArray(["admin"], ["user"])).toBe(false); }); }); /** * @description 测试 getParentPaths 函数 * @function getParentPaths * @test 验证获取父级路径集合 */ describe("getParentPaths", () => { it("should return parent paths for a given route path", () => { const routes = [ { path: "/parent", children: [{ path: "/child" }] } ]; const result = getParentPaths("/child", routes); expect(result).toEqual(["/parent"]); }); }); /** * @description 测试 findRouteByPath 函数 * @function findRouteByPath * @test 验证根据路径查找路由 */ describe("findRouteByPath", () => { it("should find route by path", () => { const routes = [ { path: "/parent", children: [{ path: "/child" }] } ]; const result = findRouteByPath("/child", routes); expect(result.path).toBe("/child"); }); }); /** * @description 测试 handleAliveRoute 函数 * @function handleAliveRoute * @test 验证处理缓存路由的逻辑 */ describe("handleAliveRoute", () => { it("should handle cache route operations", () => { const mockCacheOperate = vi.fn(); vi.spyOn(usePermissionStoreHook(), "cacheOperate").mockImplementation( mockCacheOperate ); handleAliveRoute({ name: "test" }, "add"); expect(mockCacheOperate).toHaveBeenCalledWith({ mode: "add", name: "test" }); }); }); /** * @description 测试 formatFlatteningRoutes 函数 * @function formatFlatteningRoutes * @test 验证将多级嵌套路由处理成一维数组 */ describe("formatFlatteningRoutes", () => { it("should flatten nested routes into a one-dimensional array", () => { const routes = [ { path: "/parent", children: [{ path: "/child" }] } ]; const result = formatFlatteningRoutes(routes); expect(result.length).toBe(2); expect(result[0].path).toBe("/parent"); expect(result[1].path).toBe("/child"); }); }); /** * @description 测试 formatTwoStageRoutes 函数 * @function formatTwoStageRoutes * @test 验证将一维数组处理成多级嵌套数组 */ describe("formatTwoStageRoutes", () => { it("should format one-dimensional routes into two-stage routes", () => { const routes = [ { path: "/", component: "Home" }, { path: "/about", component: "About" } ]; const result = formatTwoStageRoutes(routes); expect(result[0].children.length).toBe(1); expect(result[0].children[0].path).toBe("/about"); }); }); /** * @description 测试 initRouter 函数 * @function initRouter * @test 验证初始化路由的逻辑 */ describe("initRouter", () => { it("should initialize router with cached routes", () => { const mockHandleAsyncRoutes = vi.fn(); vi.spyOn(storageLocal(), "getItem").mockReturnValue([{ path: "/cached" }]); vi.spyOn(usePermissionStoreHook(), "handleWholeMenus").mockImplementation( mockHandleAsyncRoutes ); initRouter(); expect(mockHandleAsyncRoutes).toHaveBeenCalledWith([{ path: "/cached" }]); }); }); /** * @description 测试 getTopMenu 函数 * @function getTopMenu * @test 验证获取顶级菜单的逻辑 */ describe("getTopMenu", () => { it("should return the top menu", () => { const mockWholeMenus = [ { children: [{ path: "/top" }] } ]; vi.spyOn(usePermissionStoreHook(), "wholeMenus", "get").mockReturnValue( mockWholeMenus ); const result = getTopMenu(); expect(result.path).toBe("/top"); }); }); /** * @description 测试 addPathMatch 函数 * @function addPathMatch * @test 验证添加通配路由的逻辑 */ describe("addPathMatch", () => { it("should add a wildcard route if not exists", () => { const mockAddRoute = vi.fn(); vi.spyOn(router, "hasRoute").mockReturnValue(false); vi.spyOn(router, "addRoute").mockImplementation(mockAddRoute); addPathMatch(); expect(mockAddRoute).toHaveBeenCalledWith({ path: "/:pathMatch(.*)", name: "pathMatch", redirect: "/error/404" }); }); }); /** * @description 测试 getHistoryMode 函数 * @function getHistoryMode * @test 验证获取路由历史模式的逻辑 */ describe("getHistoryMode", () => { it("should return hash history mode", () => { const result = getHistoryMode("hash"); expect(result).toBeDefined(); }); }); /** * @description 测试 addAsyncRoutes 函数 * @function addAsyncRoutes * @test 验证添加动态路由的逻辑 */ describe("addAsyncRoutes", () => { it("should add async routes with correct meta and component", () => { const routes = [{ path: "/async", meta: {} }]; const result = addAsyncRoutes(routes); expect(result[0].meta.backstage).toBe(true); }); }); /** * @description 测试 hasAuth 函数 * @function hasAuth * @test 验证是否有按钮级别的权限 */ describe("hasAuth", () => { it("should return true if auth exists", () => { vi.spyOn(router.currentRoute.value.meta, "auths", "get").mockReturnValue([ "admin" ]); expect(hasAuth("admin")).toBe(true); }); }); /** * @description 测试 getAuths 函数 * @function getAuths * @test 验证获取当前页面按钮级别的权限 */ describe("getAuths", () => { it("should return current route auths", () => { vi.spyOn(router.currentRoute.value.meta, "auths", "get").mockReturnValue([ "admin" ]); expect(getAuths()).toEqual(["admin"]); }); }); });