92 lines
4.3 KiB
TypeScript
92 lines
4.3 KiB
TypeScript
// @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<typeof useCmsStore>;
|
||
|
||
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");
|
||
});
|
||
});
|