@esmx/router 3.0.0-rc.29 → 3.0.0-rc.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.zh-CN.md +82 -1
  2. package/dist/index.d.ts +1 -2
  3. package/dist/index.mjs +0 -1
  4. package/dist/navigation.mjs +4 -4
  5. package/package.json +3 -3
  6. package/src/index.ts +0 -3
  7. package/src/navigation.ts +4 -4
  8. package/dist/index.test.d.ts +0 -1
  9. package/dist/index.test.mjs +0 -8
  10. package/dist/location.test.d.ts +0 -8
  11. package/dist/location.test.mjs +0 -370
  12. package/dist/matcher.test.d.ts +0 -1
  13. package/dist/matcher.test.mjs +0 -1492
  14. package/dist/micro-app.dom.test.d.ts +0 -1
  15. package/dist/micro-app.dom.test.mjs +0 -532
  16. package/dist/navigation.test.d.ts +0 -1
  17. package/dist/navigation.test.mjs +0 -681
  18. package/dist/route-task.test.d.ts +0 -1
  19. package/dist/route-task.test.mjs +0 -673
  20. package/dist/route-transition.test.d.ts +0 -1
  21. package/dist/route-transition.test.mjs +0 -146
  22. package/dist/route.test.d.ts +0 -1
  23. package/dist/route.test.mjs +0 -1664
  24. package/dist/router-back.test.d.ts +0 -1
  25. package/dist/router-back.test.mjs +0 -361
  26. package/dist/router-forward.test.d.ts +0 -1
  27. package/dist/router-forward.test.mjs +0 -376
  28. package/dist/router-go.test.d.ts +0 -1
  29. package/dist/router-go.test.mjs +0 -73
  30. package/dist/router-guards-cleanup.test.d.ts +0 -1
  31. package/dist/router-guards-cleanup.test.mjs +0 -437
  32. package/dist/router-push.test.d.ts +0 -1
  33. package/dist/router-push.test.mjs +0 -115
  34. package/dist/router-replace.test.d.ts +0 -1
  35. package/dist/router-replace.test.mjs +0 -114
  36. package/dist/router-resolve.test.d.ts +0 -1
  37. package/dist/router-resolve.test.mjs +0 -393
  38. package/dist/router-restart-app.dom.test.d.ts +0 -1
  39. package/dist/router-restart-app.dom.test.mjs +0 -616
  40. package/dist/router-window-navigation.test.d.ts +0 -1
  41. package/dist/router-window-navigation.test.mjs +0 -359
  42. package/dist/util.test.d.ts +0 -1
  43. package/dist/util.test.mjs +0 -1020
  44. package/src/index.test.ts +0 -9
  45. package/src/location.test.ts +0 -406
  46. package/src/matcher.test.ts +0 -1685
  47. package/src/micro-app.dom.test.ts +0 -708
  48. package/src/navigation.test.ts +0 -858
  49. package/src/route-task.test.ts +0 -901
  50. package/src/route-transition.test.ts +0 -178
  51. package/src/route.test.ts +0 -2014
  52. package/src/router-back.test.ts +0 -487
  53. package/src/router-forward.test.ts +0 -506
  54. package/src/router-go.test.ts +0 -91
  55. package/src/router-guards-cleanup.test.ts +0 -595
  56. package/src/router-push.test.ts +0 -140
  57. package/src/router-replace.test.ts +0 -139
  58. package/src/router-resolve.test.ts +0 -475
  59. package/src/router-restart-app.dom.test.ts +0 -783
  60. package/src/router-window-navigation.test.ts +0 -457
  61. package/src/util.test.ts +0 -1262
@@ -1,437 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
- import { Router } from "./router.mjs";
3
- import { RouterMode } from "./types.mjs";
4
- import { removeFromArray } from "./util.mjs";
5
- describe("Router Guards Cleanup Tests", () => {
6
- let router;
7
- beforeEach(async () => {
8
- router = new Router({
9
- mode: RouterMode.memory,
10
- base: new URL("http://localhost:3000/"),
11
- routes: [
12
- {
13
- path: "/",
14
- component: () => "Home"
15
- },
16
- {
17
- path: "/test1",
18
- component: () => "Test1"
19
- },
20
- {
21
- path: "/test2",
22
- component: () => "Test2"
23
- },
24
- {
25
- path: "/test3",
26
- component: () => "Test3"
27
- }
28
- ]
29
- });
30
- await router.replace("/");
31
- });
32
- afterEach(() => {
33
- router.destroy();
34
- });
35
- describe("\u{1F525} Guard Cleanup Effect Verification", () => {
36
- describe("beforeEach cleanup effects", () => {
37
- test("guard should not execute after cleanup", async () => {
38
- const spy = vi.fn();
39
- const unregister = router.beforeEach(spy);
40
- await router.push("/test1");
41
- expect(spy).toHaveBeenCalledTimes(1);
42
- unregister();
43
- await router.push("/test2");
44
- expect(spy).toHaveBeenCalledTimes(1);
45
- });
46
- test("guard should not execute after cleanup for multiple navigations", async () => {
47
- const spy = vi.fn();
48
- const unregister = router.beforeEach(spy);
49
- await router.push("/test1");
50
- expect(spy).toHaveBeenCalledTimes(1);
51
- unregister();
52
- await router.push("/test2");
53
- await router.push("/test3");
54
- await router.push("/");
55
- expect(spy).toHaveBeenCalledTimes(1);
56
- });
57
- test("async guard should not execute after cleanup", async () => {
58
- const spy = vi.fn();
59
- const asyncGuard = async (to, from) => {
60
- await new Promise((resolve) => setTimeout(resolve, 10));
61
- spy(to, from);
62
- };
63
- const unregister = router.beforeEach(asyncGuard);
64
- await router.push("/test1");
65
- expect(spy).toHaveBeenCalledTimes(1);
66
- unregister();
67
- await router.push("/test2");
68
- expect(spy).toHaveBeenCalledTimes(1);
69
- });
70
- });
71
- describe("afterEach cleanup effects", () => {
72
- test("guard should not execute after cleanup", async () => {
73
- const spy = vi.fn();
74
- const unregister = router.afterEach(spy);
75
- await router.push("/test1");
76
- expect(spy).toHaveBeenCalledTimes(1);
77
- unregister();
78
- await router.push("/test2");
79
- expect(spy).toHaveBeenCalledTimes(1);
80
- });
81
- test("guard should not execute after cleanup for multiple navigations", async () => {
82
- const spy = vi.fn();
83
- const unregister = router.afterEach(spy);
84
- await router.push("/test1");
85
- expect(spy).toHaveBeenCalledTimes(1);
86
- unregister();
87
- await router.push("/test2");
88
- await router.push("/test3");
89
- await router.push("/");
90
- expect(spy).toHaveBeenCalledTimes(1);
91
- });
92
- });
93
- });
94
- describe("\u26A1 Multiple Guards Independent Cleanup", () => {
95
- describe("beforeEach multiple guards cleanup", () => {
96
- test("cleaning single guard should not affect other guards", async () => {
97
- const spy1 = vi.fn();
98
- const spy2 = vi.fn();
99
- const spy3 = vi.fn();
100
- const unregister1 = router.beforeEach(spy1);
101
- const unregister2 = router.beforeEach(spy2);
102
- const unregister3 = router.beforeEach(spy3);
103
- await router.push("/test1");
104
- expect(spy1).toHaveBeenCalledTimes(1);
105
- expect(spy2).toHaveBeenCalledTimes(1);
106
- expect(spy3).toHaveBeenCalledTimes(1);
107
- unregister2();
108
- await router.push("/test2");
109
- expect(spy1).toHaveBeenCalledTimes(2);
110
- expect(spy2).toHaveBeenCalledTimes(1);
111
- expect(spy3).toHaveBeenCalledTimes(2);
112
- unregister1();
113
- unregister3();
114
- });
115
- test("cleaning multiple guards should work correctly", async () => {
116
- const spy1 = vi.fn();
117
- const spy2 = vi.fn();
118
- const spy3 = vi.fn();
119
- const spy4 = vi.fn();
120
- const unregister1 = router.beforeEach(spy1);
121
- const unregister2 = router.beforeEach(spy2);
122
- const unregister3 = router.beforeEach(spy3);
123
- const unregister4 = router.beforeEach(spy4);
124
- await router.push("/test1");
125
- expect(spy1).toHaveBeenCalledTimes(1);
126
- expect(spy2).toHaveBeenCalledTimes(1);
127
- expect(spy3).toHaveBeenCalledTimes(1);
128
- expect(spy4).toHaveBeenCalledTimes(1);
129
- unregister1();
130
- unregister3();
131
- spy1.mockClear();
132
- spy2.mockClear();
133
- spy3.mockClear();
134
- spy4.mockClear();
135
- await router.push("/test2");
136
- expect(spy1).not.toHaveBeenCalled();
137
- expect(spy2).toHaveBeenCalledTimes(1);
138
- expect(spy3).not.toHaveBeenCalled();
139
- expect(spy4).toHaveBeenCalledTimes(1);
140
- unregister2();
141
- unregister4();
142
- });
143
- test("guard execution order should remain correct after cleanup", async () => {
144
- const executionOrder = [];
145
- const guard1 = () => {
146
- executionOrder.push("guard1");
147
- };
148
- const guard2 = () => {
149
- executionOrder.push("guard2");
150
- };
151
- const guard3 = () => {
152
- executionOrder.push("guard3");
153
- };
154
- router.beforeEach(guard1);
155
- const unregister2 = router.beforeEach(guard2);
156
- router.beforeEach(guard3);
157
- await router.push("/test1");
158
- expect(executionOrder).toEqual(["guard1", "guard2", "guard3"]);
159
- executionOrder.length = 0;
160
- unregister2();
161
- await router.push("/test2");
162
- expect(executionOrder).toEqual(["guard1", "guard3"]);
163
- });
164
- });
165
- describe("afterEach multiple guards cleanup", () => {
166
- test("cleaning single afterEach guard should not affect other guards", async () => {
167
- const spy1 = vi.fn();
168
- const spy2 = vi.fn();
169
- const spy3 = vi.fn();
170
- const unregister1 = router.afterEach(spy1);
171
- const unregister2 = router.afterEach(spy2);
172
- const unregister3 = router.afterEach(spy3);
173
- await router.push("/test1");
174
- expect(spy1).toHaveBeenCalledTimes(1);
175
- expect(spy2).toHaveBeenCalledTimes(1);
176
- expect(spy3).toHaveBeenCalledTimes(1);
177
- unregister2();
178
- await router.push("/test2");
179
- expect(spy1).toHaveBeenCalledTimes(2);
180
- expect(spy2).toHaveBeenCalledTimes(1);
181
- expect(spy3).toHaveBeenCalledTimes(2);
182
- unregister1();
183
- unregister3();
184
- });
185
- test("afterEach guard execution order should remain correct after cleanup", async () => {
186
- const executionOrder = [];
187
- const guard1 = () => {
188
- executionOrder.push("after1");
189
- };
190
- const guard2 = () => {
191
- executionOrder.push("after2");
192
- };
193
- const guard3 = () => {
194
- executionOrder.push("after3");
195
- };
196
- router.afterEach(guard1);
197
- const unregister2 = router.afterEach(guard2);
198
- router.afterEach(guard3);
199
- await router.push("/test1");
200
- expect(executionOrder).toEqual(["after1", "after2", "after3"]);
201
- executionOrder.length = 0;
202
- unregister2();
203
- await router.push("/test2");
204
- expect(executionOrder).toEqual(["after1", "after3"]);
205
- });
206
- });
207
- describe("mixed guards cleanup", () => {
208
- test("beforeEach and afterEach guards should cleanup independently", async () => {
209
- const beforeSpy = vi.fn();
210
- const afterSpy = vi.fn();
211
- const unregisterBefore = router.beforeEach(beforeSpy);
212
- const unregisterAfter = router.afterEach(afterSpy);
213
- await router.push("/test1");
214
- expect(beforeSpy).toHaveBeenCalledTimes(1);
215
- expect(afterSpy).toHaveBeenCalledTimes(1);
216
- unregisterBefore();
217
- await router.push("/test2");
218
- expect(beforeSpy).toHaveBeenCalledTimes(1);
219
- expect(afterSpy).toHaveBeenCalledTimes(2);
220
- unregisterAfter();
221
- await router.push("/test3");
222
- expect(beforeSpy).toHaveBeenCalledTimes(1);
223
- expect(afterSpy).toHaveBeenCalledTimes(2);
224
- });
225
- });
226
- });
227
- describe("\u{1F6E1}\uFE0F Edge Cases Testing", () => {
228
- describe("repeated cleanup safety", () => {
229
- test("repeated cleanup function calls should be safe", () => {
230
- const spy = vi.fn();
231
- const unregister = router.beforeEach(spy);
232
- expect(() => {
233
- unregister();
234
- unregister();
235
- unregister();
236
- }).not.toThrow();
237
- });
238
- test("guard should still not execute after repeated cleanup", async () => {
239
- const spy = vi.fn();
240
- const unregister = router.beforeEach(spy);
241
- await router.push("/test1");
242
- expect(spy).toHaveBeenCalledTimes(1);
243
- unregister();
244
- unregister();
245
- unregister();
246
- await router.push("/test2");
247
- expect(spy).toHaveBeenCalledTimes(1);
248
- });
249
- });
250
- describe("cleanup and re-registration", () => {
251
- test("can re-register same guard after cleanup", async () => {
252
- const spy = vi.fn();
253
- const unregister1 = router.beforeEach(spy);
254
- await router.push("/test1");
255
- expect(spy).toHaveBeenCalledTimes(1);
256
- unregister1();
257
- const unregister2 = router.beforeEach(spy);
258
- await router.push("/test2");
259
- expect(spy).toHaveBeenCalledTimes(2);
260
- unregister2();
261
- });
262
- test("re-registration after cleanup should work normally", async () => {
263
- const spy = vi.fn();
264
- let unregister = router.beforeEach(spy);
265
- await router.push("/test1");
266
- expect(spy).toHaveBeenCalledTimes(1);
267
- unregister();
268
- unregister = router.beforeEach(spy);
269
- await router.push("/test2");
270
- expect(spy).toHaveBeenCalledTimes(2);
271
- unregister();
272
- unregister = router.beforeEach(spy);
273
- await router.push("/test3");
274
- expect(spy).toHaveBeenCalledTimes(3);
275
- unregister();
276
- });
277
- });
278
- describe("same guard multiple registrations", () => {
279
- test("same guard function registered multiple times should handle correctly", async () => {
280
- const spy = vi.fn();
281
- const unregister1 = router.beforeEach(spy);
282
- const unregister2 = router.beforeEach(spy);
283
- await router.push("/test1");
284
- expect(spy).toHaveBeenCalledTimes(2);
285
- unregister1();
286
- await router.push("/test2");
287
- expect(spy).toHaveBeenCalledTimes(3);
288
- unregister2();
289
- await router.push("/test3");
290
- expect(spy).toHaveBeenCalledTimes(3);
291
- });
292
- test("complex scenario with same guard multiple registrations and cleanups", async () => {
293
- const spy = vi.fn();
294
- const unregister1 = router.beforeEach(spy);
295
- const unregister2 = router.beforeEach(spy);
296
- const unregister3 = router.beforeEach(spy);
297
- await router.push("/test1");
298
- expect(spy).toHaveBeenCalledTimes(3);
299
- unregister2();
300
- await router.push("/test2");
301
- expect(spy).toHaveBeenCalledTimes(5);
302
- unregister1();
303
- unregister3();
304
- await router.push("/test3");
305
- expect(spy).toHaveBeenCalledTimes(5);
306
- });
307
- });
308
- describe("empty array and non-existent element handling", () => {
309
- test("removing element from empty array should be safe", () => {
310
- const emptyArray = [];
311
- const element = vi.fn();
312
- expect(() => {
313
- removeFromArray(emptyArray, element);
314
- }).not.toThrow();
315
- expect(emptyArray).toEqual([]);
316
- });
317
- test("removing non-existent element should be safe", () => {
318
- const array = [vi.fn(), vi.fn(), vi.fn()];
319
- const nonExistentElement = vi.fn();
320
- const originalLength = array.length;
321
- expect(() => {
322
- removeFromArray(array, nonExistentElement);
323
- }).not.toThrow();
324
- expect(array).toHaveLength(originalLength);
325
- });
326
- });
327
- describe("special value handling", () => {
328
- test("removeFromArray should handle NaN values correctly", () => {
329
- const arr = [1, Number.NaN, 3, Number.NaN, 5];
330
- removeFromArray(arr, Number.NaN);
331
- expect(arr).toEqual([1, 3, Number.NaN, 5]);
332
- });
333
- test("removeFromArray should handle function references correctly", () => {
334
- const func1 = () => "func1";
335
- const func2 = () => "func2";
336
- const func3 = () => "func3";
337
- const arr = [func1, func2, func3];
338
- removeFromArray(arr, func2);
339
- expect(arr).toEqual([func1, func3]);
340
- });
341
- test("removeFromArray should handle object references correctly", () => {
342
- const obj1 = { id: 1 };
343
- const obj2 = { id: 2 };
344
- const obj3 = { id: 3 };
345
- const arr = [obj1, obj2, obj3];
346
- removeFromArray(arr, obj2);
347
- expect(arr).toEqual([obj1, obj3]);
348
- });
349
- });
350
- describe("memory leak protection", () => {
351
- test("large number of guard registrations and cleanups should not cause memory leaks", () => {
352
- const unregisters = [];
353
- for (let i = 0; i < 100; i++) {
354
- const guard = vi.fn();
355
- const unregister = router.beforeEach(guard);
356
- unregisters.push(unregister);
357
- }
358
- expect(router.transition.guards.beforeEach).toHaveLength(100);
359
- unregisters.forEach((unregister) => unregister());
360
- expect(router.transition.guards.beforeEach).toHaveLength(0);
361
- });
362
- test("mixed registration and cleanup should not cause memory leaks", () => {
363
- const guards = [];
364
- const unregisters = [];
365
- for (let i = 0; i < 50; i++) {
366
- const guard = vi.fn();
367
- guards.push(guard);
368
- const unregister = router.beforeEach(guard);
369
- unregisters.push(unregister);
370
- if (i % 5 === 0 && i > 0) {
371
- unregisters[i - 5]();
372
- }
373
- }
374
- unregisters.forEach((unregister) => unregister());
375
- expect(router.transition.guards.beforeEach).toHaveLength(0);
376
- expect(router.transition.guards.afterEach).toHaveLength(0);
377
- });
378
- });
379
- describe("concurrent cleanup safety", () => {
380
- test("cleaning guard during navigation should be safe", async () => {
381
- let unregister = null;
382
- let guardExecuted = false;
383
- const guard = async () => {
384
- guardExecuted = true;
385
- unregister == null ? void 0 : unregister();
386
- await new Promise((resolve) => setTimeout(resolve, 10));
387
- };
388
- unregister = router.beforeEach(guard);
389
- await expect(router.push("/test1")).resolves.toBeDefined();
390
- expect(guardExecuted).toBe(true);
391
- guardExecuted = false;
392
- await router.push("/test2");
393
- expect(guardExecuted).toBe(false);
394
- });
395
- test("cleaning multiple guards simultaneously should be safe", async () => {
396
- const guards = Array.from({ length: 10 }, () => vi.fn());
397
- const unregisters = guards.map(
398
- (guard) => router.beforeEach(guard)
399
- );
400
- await router.push("/test1");
401
- guards.forEach(
402
- (guard) => expect(guard).toHaveBeenCalledTimes(1)
403
- );
404
- unregisters.forEach((unregister) => unregister());
405
- await router.push("/test2");
406
- guards.forEach(
407
- (guard) => expect(guard).toHaveBeenCalledTimes(1)
408
- );
409
- });
410
- });
411
- });
412
- describe("\u{1F527} Router destroy cleanup verification", () => {
413
- test("Router destroy should cleanup all guards", async () => {
414
- const beforeSpy = vi.fn();
415
- const afterSpy = vi.fn();
416
- router.beforeEach(beforeSpy);
417
- router.afterEach(afterSpy);
418
- await router.push("/test1");
419
- expect(beforeSpy).toHaveBeenCalledTimes(1);
420
- expect(afterSpy).toHaveBeenCalledTimes(1);
421
- router.destroy();
422
- const newRouter = new Router({
423
- mode: RouterMode.memory,
424
- base: new URL("http://localhost:3000/"),
425
- routes: [
426
- { path: "/", component: () => "Home" },
427
- { path: "/test", component: () => "Test" }
428
- ]
429
- });
430
- await newRouter.replace("/");
431
- await newRouter.push("/test");
432
- expect(beforeSpy).toHaveBeenCalledTimes(1);
433
- expect(afterSpy).toHaveBeenCalledTimes(1);
434
- newRouter.destroy();
435
- });
436
- });
437
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,115 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test } from "vitest";
2
- import { Router } from "./router.mjs";
3
- import { RouteType, RouterMode } from "./types.mjs";
4
- describe("Router Push Tests", () => {
5
- let router;
6
- beforeEach(async () => {
7
- router = new Router({
8
- mode: RouterMode.memory,
9
- base: new URL("http://localhost:3000/"),
10
- routes: [
11
- { path: "/", component: () => "Home" },
12
- { path: "/user/:id", component: () => "User" },
13
- { path: "/about", component: () => "About" },
14
- {
15
- path: "/async",
16
- asyncComponent: () => new Promise(
17
- (resolve) => setTimeout(() => resolve("AsyncComponent"), 10)
18
- )
19
- }
20
- ]
21
- });
22
- await router.replace("/");
23
- });
24
- afterEach(() => {
25
- router.destroy();
26
- });
27
- describe("Basic push navigation", () => {
28
- test("should successfully push to new route", async () => {
29
- const route = await router.push("/user/123");
30
- expect(route.path).toBe("/user/123");
31
- expect(route.params.id).toBe("123");
32
- expect(route.type).toBe(RouteType.push);
33
- expect(route.handle).not.toBe(null);
34
- expect(router.route.path).toBe("/user/123");
35
- });
36
- test("should handle query parameters in push", async () => {
37
- const route = await router.push(
38
- "/user/123?tab=profile&active=true"
39
- );
40
- expect(route.params.id).toBe("123");
41
- expect(route.query.tab).toBe("profile");
42
- expect(route.query.active).toBe("true");
43
- });
44
- test("should handle async component loading", async () => {
45
- const route = await router.push("/async");
46
- expect(route.path).toBe("/async");
47
- expect(route.handle).not.toBe(null);
48
- });
49
- });
50
- describe("Error handling", () => {
51
- test("should throw error for async component loading failure", async () => {
52
- const errorRouter = new Router({
53
- mode: RouterMode.memory,
54
- base: new URL("http://localhost:3000/"),
55
- routes: [
56
- { path: "/", component: () => "Home" },
57
- {
58
- path: "/error",
59
- asyncComponent: () => Promise.reject(new Error("Loading failed"))
60
- }
61
- ]
62
- });
63
- await errorRouter.replace("/");
64
- await expect(errorRouter.push("/error")).rejects.toThrow();
65
- errorRouter.destroy();
66
- });
67
- test("should throw error when guard prevents navigation", async () => {
68
- const guardRouter = new Router({
69
- mode: RouterMode.memory,
70
- base: new URL("http://localhost:3000/"),
71
- routes: [
72
- { path: "/", component: () => "Home" },
73
- {
74
- path: "/protected",
75
- component: () => "Protected",
76
- beforeEnter: () => false
77
- }
78
- ]
79
- });
80
- await guardRouter.replace("/");
81
- await expect(guardRouter.push("/protected")).rejects.toThrow();
82
- guardRouter.destroy();
83
- });
84
- });
85
- describe("Concurrent navigation", () => {
86
- test("should handle concurrent push operations", async () => {
87
- const promises = [
88
- router.push("/user/1").catch((err) => err),
89
- router.push("/user/2").catch((err) => err)
90
- ];
91
- const [result1, result2] = await Promise.all(promises);
92
- const successResults = [result1, result2].filter(
93
- (r) => !(r instanceof Error)
94
- );
95
- const errorResults = [result1, result2].filter(
96
- (r) => r instanceof Error
97
- );
98
- expect(successResults).toHaveLength(1);
99
- expect(errorResults).toHaveLength(1);
100
- });
101
- });
102
- describe("Edge cases", () => {
103
- test("should handle push to current route", async () => {
104
- await router.push("/about");
105
- const route = await router.push("/about");
106
- expect(route.path).toBe("/about");
107
- expect(route.handle).not.toBe(null);
108
- });
109
- test("should handle empty parameter", async () => {
110
- const route = await router.push("");
111
- expect(route).toBeDefined();
112
- expect(typeof route.path).toBe("string");
113
- });
114
- });
115
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,114 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test } from "vitest";
2
- import { Router } from "./router.mjs";
3
- import { RouteType, RouterMode } from "./types.mjs";
4
- describe("Router Replace Tests", () => {
5
- let router;
6
- beforeEach(async () => {
7
- router = new Router({
8
- mode: RouterMode.memory,
9
- base: new URL("http://localhost:3000/"),
10
- routes: [
11
- { path: "/", component: () => "Home" },
12
- { path: "/user/:id", component: () => "User" },
13
- { path: "/about", component: () => "About" },
14
- {
15
- path: "/async",
16
- asyncComponent: () => new Promise(
17
- (resolve) => setTimeout(() => resolve("AsyncComponent"), 10)
18
- )
19
- }
20
- ]
21
- });
22
- await router.replace("/");
23
- });
24
- afterEach(() => {
25
- router.destroy();
26
- });
27
- describe("Basic replace navigation", () => {
28
- test("should successfully replace current route", async () => {
29
- await router.push("/about");
30
- const route = await router.replace("/user/123");
31
- expect(route.path).toBe("/user/123");
32
- expect(route.params.id).toBe("123");
33
- expect(route.type).toBe(RouteType.replace);
34
- expect(route.handle).not.toBe(null);
35
- expect(router.route.path).toBe("/user/123");
36
- });
37
- test("should handle query parameters in replace", async () => {
38
- const route = await router.replace(
39
- "/user/123?tab=profile&active=true"
40
- );
41
- expect(route.params.id).toBe("123");
42
- expect(route.query.tab).toBe("profile");
43
- expect(route.query.active).toBe("true");
44
- });
45
- test("should handle async component loading", async () => {
46
- const route = await router.replace("/async");
47
- expect(route.path).toBe("/async");
48
- expect(route.handle).not.toBe(null);
49
- });
50
- });
51
- describe("Error handling", () => {
52
- test("should throw error for async component loading failure", async () => {
53
- const errorRouter = new Router({
54
- mode: RouterMode.memory,
55
- base: new URL("http://localhost:3000/"),
56
- routes: [
57
- { path: "/", component: () => "Home" },
58
- {
59
- path: "/error",
60
- asyncComponent: () => Promise.reject(new Error("Loading failed"))
61
- }
62
- ]
63
- });
64
- await errorRouter.replace("/");
65
- await expect(errorRouter.replace("/error")).rejects.toThrow();
66
- errorRouter.destroy();
67
- });
68
- test("should throw error when guard prevents navigation", async () => {
69
- const guardRouter = new Router({
70
- mode: RouterMode.memory,
71
- base: new URL("http://localhost:3000/"),
72
- routes: [
73
- { path: "/", component: () => "Home" },
74
- {
75
- path: "/protected",
76
- component: () => "Protected",
77
- beforeEnter: () => false
78
- }
79
- ]
80
- });
81
- await guardRouter.replace("/");
82
- await expect(guardRouter.replace("/protected")).rejects.toThrow();
83
- guardRouter.destroy();
84
- });
85
- });
86
- describe("History management", () => {
87
- test("should not create new history entry", async () => {
88
- await router.push("/about");
89
- await router.replace("/user/123");
90
- const backRoute = await router.back();
91
- expect(backRoute == null ? void 0 : backRoute.path).toBe("/");
92
- });
93
- test("should replace current entry in history", async () => {
94
- await router.push("/about");
95
- await router.push("/user/456");
96
- await router.replace("/user/789");
97
- const backRoute = await router.back();
98
- expect(backRoute == null ? void 0 : backRoute.path).toBe("/about");
99
- });
100
- });
101
- describe("Edge cases", () => {
102
- test("should handle replace to current route", async () => {
103
- await router.push("/about");
104
- const route = await router.replace("/about");
105
- expect(route.path).toBe("/about");
106
- expect(route.handle).not.toBe(null);
107
- });
108
- test("should handle empty parameter", async () => {
109
- const route = await router.replace("");
110
- expect(route).toBeDefined();
111
- expect(typeof route.path).toBe("string");
112
- });
113
- });
114
- });
@@ -1 +0,0 @@
1
- export {};