|
1 | 1 | import type { RouterPlugin } from '../src/plugin' |
2 | 2 | import { describe, expect, it, vi } from 'vitest' |
3 | 3 | import { computed, createApp, ref, watch } from 'vue' |
4 | | -import { createMemoryHistory } from 'vue-router' |
5 | | -import { asVuePlugin, createRouter } from '../src/index' |
| 4 | +import { createRouter as _createRouter, createMemoryHistory } from 'vue-router' |
| 5 | +import { createRouter, withInstall } from '../src/index' |
| 6 | +import { getInternals } from '../src/internals' |
6 | 7 |
|
7 | 8 | describe.concurrent('vue Router Plugin System', () => { |
8 | 9 | // 测试插件基础功能 |
@@ -107,27 +108,114 @@ describe.concurrent('vue Router Plugin System', () => { |
107 | 108 | expect(logSpy).toHaveBeenCalledTimes(2) |
108 | 109 | }) |
109 | 110 |
|
110 | | - // 测试 asVuePlugin |
111 | | - it('test asVuePlugin', () => { |
112 | | - const counter = ref(0) |
113 | | - const logSpy = vi.fn() |
114 | | - const mockPlugin: RouterPlugin = () => { |
115 | | - const doubled = computed(() => counter.value * 2) |
116 | | - watch(doubled, logSpy, { immediate: true, flush: 'sync' }) |
117 | | - counter.value = 1 |
118 | | - } |
| 111 | + // 多个 runWithApp 的刷新顺序 |
| 112 | + it('should flush runWithApp handlers in registration order', () => { |
| 113 | + const calls: string[] = [] |
| 114 | + const p1: RouterPlugin = ctx => ctx.runWithApp(() => calls.push('a')) |
| 115 | + const p2: RouterPlugin = ctx => ctx.runWithApp(() => calls.push('b')) |
| 116 | + const p3: RouterPlugin = ctx => ctx.runWithApp(() => calls.push('c')) |
119 | 117 |
|
120 | 118 | const router = createRouter({ |
121 | 119 | history: createMemoryHistory(), |
122 | 120 | routes: [], |
| 121 | + plugins: [p1, p2, p3], |
123 | 122 | }) |
124 | 123 |
|
125 | 124 | const app = createApp(() => null) |
126 | | - app.use(router).use(asVuePlugin(mockPlugin)) |
| 125 | + app.use(router) |
| 126 | + |
| 127 | + expect(calls).toEqual(['a', 'b', 'c']) |
| 128 | + }) |
| 129 | + |
| 130 | + // 使用 withInstall:通过 router 直接安装(app.use 前,runWithApp 应延迟) |
| 131 | + it('withInstall: install with router before app.use should defer runWithApp', () => { |
| 132 | + const runWithAppSpy = vi.fn() |
| 133 | + const Plugin = withInstall((ctx) => { |
| 134 | + ctx.runWithApp(() => runWithAppSpy()) |
| 135 | + }) |
| 136 | + |
| 137 | + const router = _createRouter({ |
| 138 | + history: createMemoryHistory(), |
| 139 | + routes: [], |
| 140 | + }) |
| 141 | + |
| 142 | + // install via router directly |
| 143 | + Plugin.install(router) |
| 144 | + |
| 145 | + // before app.use, runWithApp should not run |
| 146 | + expect(runWithAppSpy).not.toHaveBeenCalled() |
| 147 | + |
| 148 | + const app = createApp(() => null) |
| 149 | + app.use(router) |
| 150 | + expect(runWithAppSpy).toHaveBeenCalledOnce() |
| 151 | + }) |
| 152 | + |
| 153 | + // 使用 withInstall:通过 router 在 app.use 后安装(应立即执行 runWithApp) |
| 154 | + it('withInstall: install with router after app.use should run runWithApp immediately', () => { |
| 155 | + const runWithAppSpy = vi.fn() |
| 156 | + const Plugin = withInstall((ctx) => { |
| 157 | + ctx.runWithApp(() => runWithAppSpy()) |
| 158 | + }) |
| 159 | + |
| 160 | + const router = createRouter({ |
| 161 | + history: createMemoryHistory(), |
| 162 | + routes: [], |
| 163 | + }) |
| 164 | + |
| 165 | + const app = createApp(() => null) |
| 166 | + app.use(router) |
| 167 | + |
| 168 | + Plugin.install(router) |
| 169 | + expect(runWithAppSpy).toHaveBeenCalledOnce() |
| 170 | + }) |
| 171 | + |
| 172 | + // 使用 withInstall:通过 app.use 安装时,若未先注册 router,应抛错 |
| 173 | + it('withInstall: installing with app before router should throw', () => { |
| 174 | + const Plugin = withInstall(() => {}) |
| 175 | + const app = createApp(() => null) |
| 176 | + expect(() => app.use(Plugin as any)).toThrowError( |
| 177 | + /Please install vue-router first/, |
| 178 | + ) |
| 179 | + }) |
| 180 | + |
| 181 | + // 使用 withInstall:onUninstall 应在 app.unmount 时触发 |
| 182 | + it('withInstall: should register uninstall hook', () => { |
| 183 | + const uninstallSpy = vi.fn() |
| 184 | + const Plugin = withInstall((ctx) => { |
| 185 | + ctx.onUninstall(uninstallSpy) |
| 186 | + }) |
| 187 | + |
| 188 | + const router = createRouter({ |
| 189 | + history: createMemoryHistory(), |
| 190 | + routes: [], |
| 191 | + }) |
| 192 | + |
| 193 | + const app = createApp(() => null) |
| 194 | + app.use(router) |
| 195 | + |
| 196 | + Plugin.install(router) |
| 197 | + |
| 198 | + expect(uninstallSpy).not.toHaveBeenCalled() |
127 | 199 | app.unmount() |
| 200 | + expect(uninstallSpy).toHaveBeenCalledOnce() |
| 201 | + }) |
128 | 202 |
|
129 | | - expect(logSpy).toHaveBeenCalledTimes(2) |
130 | | - counter.value = 2 |
131 | | - expect(logSpy).toHaveBeenCalledTimes(2) |
| 203 | + // overrideRouterInstall 幂等:仅包裹一次 install,并有内部标记 |
| 204 | + it('overrideRouterInstall is idempotent (wrapped once with internal flag)', () => { |
| 205 | + const router = _createRouter({ history: createMemoryHistory(), routes: [] }) |
| 206 | + const originalInstall = router.install |
| 207 | + |
| 208 | + const P1 = withInstall(() => {}) |
| 209 | + P1.install(router) |
| 210 | + const wrappedOnce = router.install |
| 211 | + expect(wrappedOnce).not.toBe(originalInstall) |
| 212 | + |
| 213 | + const P2 = withInstall(() => {}) |
| 214 | + P2.install(router) |
| 215 | + const wrappedTwice = router.install |
| 216 | + expect(wrappedTwice).toBe(wrappedOnce) |
| 217 | + |
| 218 | + // internal flag should be true |
| 219 | + expect(getInternals(router).isInstallOverridden).toBe(true) |
132 | 220 | }) |
133 | 221 | }) |
0 commit comments