UNPKG

@esmx/router-vue

Version:

Vue integration for @esmx/router - A universal router that works seamlessly with both Vue 2.7+ and Vue 3

377 lines (376 loc) 11.6 kB
import { Router, RouterMode } from "@esmx/router"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { nextTick } from "vue"; import { createApp, defineComponent, getCurrentInstance, h } from "vue"; import { RouterView } from "./router-view.mjs"; import { getRouterViewDepth, useProvideRouter, useRoute, useRouter, useRouterViewDepth } from "./use.mjs"; describe("Router Vue Integration", () => { let app; let router; let mountPoint; beforeEach(async () => { router = new Router({ mode: RouterMode.memory, routes: [ { path: "/initial", component: {} }, { path: "/new-route", component: {} }, { path: "/user/:id", component: {} }, { path: "/new-path", component: {} } ], base: new URL("http://localhost:8000/") }); await router.replace("/initial"); mountPoint = document.createElement("div"); mountPoint.id = "app"; document.body.appendChild(mountPoint); }); afterEach(() => { if (app) { app.unmount(); } document.body.removeChild(mountPoint); router.destroy(); }); describe("Router and Route Access", () => { it("should provide router and route access", async () => { let routerResult; let routeResult; const TestApp = { setup() { useProvideRouter(router); routerResult = useRouter(); routeResult = useRoute(); return () => h("div", "Test App"); } }; app = createApp(TestApp); app.mount("#app"); expect(routerResult).toEqual(router); expect(routeResult).toBeDefined(); expect(routeResult == null ? void 0 : routeResult.path).toBe("/initial"); }); }); describe("Route Reactivity", () => { it("should update route properties when route changes", async () => { let routeRef; const TestApp = { setup() { useProvideRouter(router); routeRef = useRoute(); return () => h("div", routeRef == null ? void 0 : routeRef.path); } }; app = createApp(TestApp); app.mount("#app"); expect(routeRef == null ? void 0 : routeRef.path).toBe("/initial"); const initialRouteRef = routeRef; await router.replace("/new-route"); await nextTick(); expect(routeRef).toBe(initialRouteRef); expect(routeRef == null ? void 0 : routeRef.path).toBe("/new-route"); }); it("should update route params when route changes", async () => { var _a; let routeRef; const TestApp = { setup() { useProvideRouter(router); routeRef = useRoute(); return () => { var _a2; return h("div", [ h("span", routeRef == null ? void 0 : routeRef.path), h("span", ((_a2 = routeRef == null ? void 0 : routeRef.params) == null ? void 0 : _a2.id) || "no-id") ]); }; } }; app = createApp(TestApp); app.mount("#app"); await router.replace("/user/123"); await nextTick(); expect(routeRef == null ? void 0 : routeRef.path).toBe("/user/123"); expect((_a = routeRef == null ? void 0 : routeRef.params) == null ? void 0 : _a.id).toBe("123"); }); it("should automatically update view when route changes", async () => { const renderCount = { value: 0 }; let routeRef; const TestApp = { setup() { useProvideRouter(router); routeRef = useRoute(); return () => { renderCount.value++; return h("div", routeRef == null ? void 0 : routeRef.path); }; } }; app = createApp(TestApp); app.mount("#app"); const initialRenderCount = renderCount.value; expect(routeRef == null ? void 0 : routeRef.path).toBe("/initial"); await router.replace("/new-route"); await nextTick(); expect(renderCount.value).toBeGreaterThan(initialRenderCount); expect(routeRef == null ? void 0 : routeRef.path).toBe("/new-route"); const previousRenderCount = renderCount.value; await router.replace("/new-path"); await nextTick(); expect(renderCount.value).toBeGreaterThan(previousRenderCount); expect(routeRef == null ? void 0 : routeRef.path).toBe("/new-path"); }); }); describe("Nested Components", () => { it("should provide route context to child components", async () => { let parentRoute; let childRoute; const ChildComponent = { setup() { childRoute = useRoute(); return () => h("div", "Child: " + (childRoute == null ? void 0 : childRoute.path)); } }; const ParentComponent = { setup() { parentRoute = useRoute(); return () => h("div", [ h("span", "Parent: " + (parentRoute == null ? void 0 : parentRoute.path)), h(ChildComponent) ]); } }; const TestApp = { setup() { useProvideRouter(router); return () => h(ParentComponent); } }; app = createApp(TestApp); app.mount("#app"); expect(parentRoute).toBeDefined(); expect(childRoute).toBeDefined(); expect(parentRoute == null ? void 0 : parentRoute.path).toBe("/initial"); expect(childRoute == null ? void 0 : childRoute.path).toBe("/initial"); await router.replace("/new-path"); await nextTick(); expect(parentRoute == null ? void 0 : parentRoute.path).toBe("/new-path"); expect(childRoute == null ? void 0 : childRoute.path).toBe("/new-path"); }); }); describe("RouterView Depth", () => { it("should get depth in single RouterView", async () => { let observedDepth; const LeafProbe = defineComponent({ setup() { const p = getCurrentInstance().proxy; observedDepth = getRouterViewDepth(p); return () => h("div"); } }); const Level1 = defineComponent({ setup() { return () => h("div", [h(LeafProbe)]); } }); router = new Router({ mode: RouterMode.memory, routes: [{ path: "/level1", component: Level1 }], base: new URL("http://localhost:8000/") }); await router.replace("/level1"); const TestApp = defineComponent({ setup() { useProvideRouter(router); return () => h("div", [h(RouterView)]); } }); app = createApp(TestApp); app.mount("#app"); await nextTick(); expect(observedDepth).toBe(1); }); it("should get depth in nested RouterView", async () => { let observedDepth; const LeafProbe = defineComponent({ setup() { const p = getCurrentInstance().proxy; observedDepth = getRouterViewDepth(p); return () => h("div"); } }); const Level1 = defineComponent({ setup() { return () => h("div", [h(RouterView)]); } }); const Leaf = defineComponent({ setup() { return () => h("div", [h(LeafProbe)]); } }); router = new Router({ mode: RouterMode.memory, routes: [ { path: "/level1", component: Level1, children: [{ path: "leaf", component: Leaf }] } ], base: new URL("http://localhost:8000/") }); await router.replace("/level1/leaf"); const TestApp = defineComponent({ setup() { useProvideRouter(router); return () => h("div", [h(RouterView)]); } }); app = createApp(TestApp); app.mount("#app"); await nextTick(); expect(observedDepth).toBe(2); }); it("should get depth in double-nested RouterViews", async () => { let observedDepth; const LeafProbe = defineComponent({ setup() { const p = getCurrentInstance().proxy; observedDepth = getRouterViewDepth(p); return () => h("div"); } }); const Level1 = defineComponent({ setup() { return () => h("div", [h(RouterView)]); } }); const Level2 = defineComponent({ setup() { return () => h("div", [h(RouterView)]); } }); const Leaf = defineComponent({ setup() { return () => h("div", [h(LeafProbe)]); } }); router = new Router({ mode: RouterMode.memory, routes: [ { path: "/level1", component: Level1, children: [ { path: "level2", component: Level2, children: [{ path: "leaf", component: Leaf }] } ] } ], base: new URL("http://localhost:8000/") }); await router.replace("/level1/level2/leaf"); const TestApp = defineComponent({ setup() { useProvideRouter(router); return () => h("div", [h(RouterView)]); } }); app = createApp(TestApp); app.mount("#app"); await nextTick(); expect(observedDepth).toBe(3); }); it("should throw when no RouterView ancestor exists", async () => { let callDepth; const Probe = defineComponent({ setup() { const p = getCurrentInstance().proxy; callDepth = () => getRouterViewDepth(p); return () => h("div"); } }); const TestApp = defineComponent({ setup() { useProvideRouter(router); return () => h(Probe); } }); app = createApp(TestApp); app.mount("#app"); await nextTick(); expect(() => callDepth()).toThrow( new Error( "[@esmx/router-vue] RouterView depth not found. Please ensure a RouterView exists in ancestor components." ) ); }); it("should return 0 for useRouterViewDepth without RouterView", async () => { let observed = -1; const Probe = defineComponent({ setup() { observed = useRouterViewDepth(); return () => h("div"); } }); const TestApp = defineComponent({ setup() { useProvideRouter(router); return () => h(Probe); } }); app = createApp(TestApp); app.mount("#app"); await nextTick(); expect(observed).toBe(0); }); it("should reflect depth via useRouterViewDepth at each level", async () => { let level1Depth = -1; let level2Depth = -1; const Level2 = defineComponent({ setup() { level2Depth = useRouterViewDepth(); return () => h("div"); } }); const Level1 = defineComponent({ setup() { level1Depth = useRouterViewDepth(); return () => h("div", [h(RouterView)]); } }); router = new Router({ mode: RouterMode.memory, routes: [ { path: "/level1", component: Level1, children: [{ path: "level2", component: Level2 }] } ], base: new URL("http://localhost:8000/") }); await router.replace("/level1/level2"); const TestApp = defineComponent({ setup() { useProvideRouter(router); return () => h("div", [h(RouterView)]); } }); app = createApp(TestApp); app.mount("#app"); await nextTick(); expect(level1Depth).toBe(1); expect(level2Depth).toBe(2); }); }); });