// @vitest-environment jsdom /** * docs/13 方案 C 复检:真实 vue-router 集成(docs/15 §3 T1/T4)。 * siteLayer.spec.ts 全程 router 桩(vi.mock vue-router),覆盖不到镜像层真实匹配与守卫重定向, * 本文件装载 routes.ts 全量路由 + router/index.ts 守卫补位: * ① 路由结构:/site/{code} 无 component 镜像层存在、镜像去 name、meta.modId 保留、空段 redirect 兜底; * ② 镜像层真实 resolve 命中(渲染层由 router-view 对无 component 记录跳过推进,此处验匹配链); * ③ 守卫:子站编码当学校段 → 定向主站前缀且余部原样保留(含站点段),并恢复学校上下文; * ④ legacyRedirect 旧链带 id 重定向。 */ import { beforeEach, describe, expect, it } from "vitest"; import { createPinia, setActivePinia } from "pinia"; import { useCmsStore } from "@/store"; import router from "@/router"; import { routes } from "@/router/routes"; const SITES = [ { id: 1, code: "demo", name: "云海大学门户", parentSiteId: 0, schId: 1001, schName: "云海大学" }, { id: 2, code: "jdxy", name: "机电学院", parentSiteId: 1, schId: 1001, schName: "云海大学" }, ]; let store: ReturnType; beforeEach(() => { localStorage.clear(); const pinia = createPinia(); setActivePinia(pinia); store = useCmsStore(pinia); store.user = { superAdmin: true, sites: SITES } as any; }); describe("docs/13 路由结构(真实 routes 数组,docs/15 T1)", () => { it("① /site/{code} 无 component 镜像层存在;镜像去 name、meta.modId 保留、空段 redirect 到 article", () => { const sch = routes.find(r => r.path === "/sch/:schCode")!; const siteLayer = sch.children!.find(r => r.path === "site/:siteCode") as any; expect(siteLayer).toBeTruthy(); expect(siteLayer.component).toBeUndefined(); expect(siteLayer.children![0].path).toBe(""); expect(siteLayer.children![0].redirect).toBeTruthy(); const mirror = siteLayer.children!.find((c: any) => c.path === "category"); expect(mirror!.name).toBeUndefined(); expect((mirror!.meta as any).modId).toBe(2); }); it("①b 主站清单与镜像层不重名(防重复注册告警)", () => { expect(router.getRoutes().filter(r => r.name === "CategoryManage")).toHaveLength(1); expect(router.getRoutes().filter(r => r.name === "ArticleList")).toHaveLength(1); }); it("② 子站 URL 真实 resolve 命中镜像记录;主站 URL 命中主记录", () => { const sub = router.resolve("/sch/demo/site/jdxy/category"); expect(sub.matched).toHaveLength(3); expect(sub.name).toBeUndefined(); expect(sub.meta.modId).toBe(2); const main = router.resolve("/sch/demo/category"); expect(main.matched).toHaveLength(2); expect(main.name).toBe("CategoryManage"); }); }); describe("docs/13 守卫与旧链兼容(真实 router.push,docs/15 T4)", () => { it("③ 子站编码当学校段 → 重定向主站前缀(余部保留)并恢复学校上下文", async () => { await router.push("/sch/jdxy/article"); expect(router.currentRoute.value.path).toBe("/sch/demo/article"); expect(store.currentSchool?.mainSiteCode).toBe("demo"); }); it("③b 子站编码当学校段且 URL 已带站点段 → 站点段原样保留", async () => { await router.push("/sch/jdxy/site/jdxy/category"); expect(router.currentRoute.value.path).toBe("/sch/demo/site/jdxy/category"); expect(router.currentRoute.value.params.siteCode).toBe("jdxy"); }); it("③c 学校编码不在用户可管理站点内 → 回工作台", async () => { await router.push("/sch/other-school/article"); expect(router.currentRoute.value.path).toBe("/workbench"); }); it("④ 旧链 /article/edit/:id → 当前学校上下文主站形态(id 后缀保留)", async () => { store.currentSchool = { schId: 1001, schName: "云海大学", mainSiteId: 1, mainSiteCode: "demo", mainSiteName: "云海大学门户", } as any; await router.push("/article/edit/9"); expect(router.currentRoute.value.path).toBe("/sch/demo/article/edit/9"); }); });