@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,359 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
- import { Router } from "./router.mjs";
3
- import { RouteType } from "./types.mjs";
4
- describe("Router Window Navigation Tests", () => {
5
- let router;
6
- let mockApps;
7
- beforeEach(() => {
8
- vi.clearAllMocks();
9
- mockApps = {
10
- home: vi.fn(() => ({
11
- mount: vi.fn(),
12
- unmount: vi.fn(),
13
- renderToString: vi.fn().mockResolvedValue("<div>Home</div>")
14
- })),
15
- about: vi.fn(() => ({
16
- mount: vi.fn(),
17
- unmount: vi.fn(),
18
- renderToString: vi.fn().mockResolvedValue("<div>About</div>")
19
- })),
20
- user: vi.fn(() => ({
21
- mount: vi.fn(),
22
- unmount: vi.fn(),
23
- renderToString: vi.fn().mockResolvedValue("<div>User</div>")
24
- }))
25
- };
26
- router = new Router({
27
- routes: [
28
- { path: "/", app: "home" },
29
- { path: "/about", app: "about" },
30
- { path: "/user/:id", app: "user" }
31
- ],
32
- apps: mockApps
33
- });
34
- });
35
- function createWindowNavigationTests(methodName, expectedIsPush) {
36
- describe("\u{1FA9F} ".concat(methodName, " Core Functionality Tests"), () => {
37
- it("should support using current route path", async () => {
38
- await router.push("/about");
39
- const result = await router[methodName]("/about");
40
- expect(result.type).toBe(RouteType[methodName]);
41
- expect(result.path).toBe("/about");
42
- expect(result.isPush).toBe(expectedIsPush);
43
- expect(result.handle).not.toBeNull();
44
- });
45
- it("should support string path parameters", async () => {
46
- const result = await router[methodName]("/user/123");
47
- expect(result.type).toBe(RouteType[methodName]);
48
- expect(result.path).toBe("/user/123");
49
- expect(result.params.id).toBe("123");
50
- expect(result.isPush).toBe(expectedIsPush);
51
- expect(result.handle).not.toBeNull();
52
- });
53
- it("should support object parameters", async () => {
54
- const result = await router[methodName]({
55
- path: "/user/456",
56
- query: { tab: "profile" },
57
- hash: "section1"
58
- });
59
- expect(result.type).toBe(RouteType[methodName]);
60
- expect(result.path).toBe("/user/456");
61
- expect(result.params.id).toBe("456");
62
- expect(result.query.tab).toBe("profile");
63
- expect(result.url.hash).toBe("#section1");
64
- expect(result.isPush).toBe(expectedIsPush);
65
- expect(result.handle).not.toBeNull();
66
- });
67
- it("should correctly handle complete URLs", async () => {
68
- const result = await router[methodName](
69
- "https://example.com/user/789?sort=name#top"
70
- );
71
- expect(result.type).toBe(RouteType[methodName]);
72
- expect(result.url.href).toBe(
73
- "https://example.com/user/789?sort=name#top"
74
- );
75
- expect(result.isPush).toBe(expectedIsPush);
76
- expect(result.handle).not.toBeNull();
77
- });
78
- });
79
- describe("\u{1F3AF} ".concat(methodName, " Specific Behavior Tests"), () => {
80
- it("should set correct isPush flag", async () => {
81
- const result = await router[methodName]("/about");
82
- expect(result.isPush).toBe(expectedIsPush);
83
- expect(result.type).toBe(RouteType[methodName]);
84
- });
85
- it("should call location handler", async () => {
86
- let locationCalled = false;
87
- let receivedRoute = null;
88
- const windowRouter = new Router({
89
- routes: [{ path: "/", app: "home" }],
90
- apps: mockApps,
91
- fallback: (to, from) => {
92
- locationCalled = true;
93
- receivedRoute = to;
94
- return { windowNavigation: true };
95
- }
96
- });
97
- await windowRouter.push("/");
98
- const result = await windowRouter[methodName]("/about");
99
- expect(locationCalled).toBe(true);
100
- expect(receivedRoute.isPush).toBe(expectedIsPush);
101
- expect(result.handleResult).toEqual({ windowNavigation: true });
102
- windowRouter.destroy();
103
- });
104
- it("should not update current route state", async () => {
105
- await router.push("/about");
106
- const beforeRoute = router.route;
107
- await router[methodName]("/user/123");
108
- const afterRoute = router.route;
109
- expect(afterRoute.path).toBe(beforeRoute.path);
110
- expect(afterRoute.url.href).toBe(beforeRoute.url.href);
111
- });
112
- it("should not trigger MicroApp update", async () => {
113
- const updateSpy = vi.spyOn(router.microApp, "_update");
114
- await router[methodName]("/user/123");
115
- expect(updateSpy).not.toHaveBeenCalled();
116
- });
117
- });
118
- describe("\u{1F6E1}\uFE0F ".concat(methodName, " Route Guards Tests"), () => {
119
- it("should execute beforeEach guards", async () => {
120
- let guardCalled = false;
121
- const unregister = router.beforeEach(async (to, from) => {
122
- guardCalled = true;
123
- expect(to.isPush).toBe(expectedIsPush);
124
- });
125
- await router[methodName]("/about");
126
- expect(guardCalled).toBe(true);
127
- unregister();
128
- });
129
- it("should abort navigation when guard returns false", async () => {
130
- const unregister = router.beforeEach((to, from) => {
131
- return false;
132
- });
133
- await expect(router[methodName]("/about")).rejects.toThrow(
134
- "Navigation was aborted"
135
- );
136
- unregister();
137
- });
138
- it("should support guard redirects", async () => {
139
- const unregister = router.beforeEach(async (to) => {
140
- if (to.path === "/about") {
141
- return "/user/redirect";
142
- }
143
- });
144
- const result = await router[methodName]("/about");
145
- expect(result.path).toBe("/user/redirect");
146
- expect(result.params.id).toBe("redirect");
147
- unregister();
148
- });
149
- it("should execute afterEach guards", async () => {
150
- let guardCalled = false;
151
- const unregister = router.afterEach((to, from) => {
152
- guardCalled = true;
153
- expect(to.isPush).toBe(expectedIsPush);
154
- });
155
- await router[methodName]("/about");
156
- expect(guardCalled).toBe(true);
157
- unregister();
158
- });
159
- });
160
- describe("\u{1F3AD} ".concat(methodName, " Edge Cases Tests"), () => {
161
- it("should handle non-existent routes", async () => {
162
- const result = await router[methodName]("/nonexistent");
163
- expect(result.handle).not.toBeNull();
164
- expect(result.matched.length).toBe(0);
165
- expect(result.isPush).toBe(expectedIsPush);
166
- });
167
- it("should handle empty string path", async () => {
168
- const result = await router[methodName]("");
169
- expect(result.handle).not.toBeNull();
170
- expect(result.isPush).toBe(expectedIsPush);
171
- });
172
- it("should handle special characters", async () => {
173
- const result = await router[methodName](
174
- "/user/\u6D4B\u8BD5\u7528\u6237?name=\u5F20\u4E09&age=25#\u4E2A\u4EBA\u4FE1\u606F"
175
- );
176
- expect(result.handle).not.toBeNull();
177
- expect(result.isPush).toBe(expectedIsPush);
178
- expect(result.url.pathname).toContain(
179
- "%E6%B5%8B%E8%AF%95%E7%94%A8%E6%88%B7"
180
- );
181
- });
182
- });
183
- describe("\u26A1 ".concat(methodName, " Task Cancellation and Concurrency Control"), () => {
184
- it("should support concurrent calls", async () => {
185
- const promises = [
186
- router[methodName]("/user/1").catch((err) => err),
187
- router[methodName]("/user/2").catch((err) => err),
188
- router[methodName]("/user/3").catch((err) => err)
189
- ];
190
- const results = await Promise.all(promises);
191
- const successResults = results.filter(
192
- (r) => !(r instanceof Error) && r.handle !== null
193
- );
194
- const errorResults = results.filter((r) => r instanceof Error);
195
- expect(successResults.length).toBeGreaterThan(0);
196
- expect(successResults.length + errorResults.length).toBe(3);
197
- successResults.forEach((result) => {
198
- expect(result.isPush).toBe(expectedIsPush);
199
- });
200
- });
201
- it("should correctly handle rapid consecutive calls", async () => {
202
- const results = [];
203
- for (let i = 0; i < 5; i++) {
204
- results.push(await router[methodName]("/user/".concat(i)));
205
- }
206
- results.forEach((result, index) => {
207
- expect(result.handle).not.toBeNull();
208
- expect(result.params.id).toBe(String(index));
209
- expect(result.isPush).toBe(expectedIsPush);
210
- });
211
- });
212
- });
213
- describe("\u274C ".concat(methodName, " Error Handling"), () => {
214
- it("should handle exceptions in guards", async () => {
215
- const unregister = router.beforeEach(async () => {
216
- throw new Error("Guard error");
217
- });
218
- await expect(router[methodName]("/about")).rejects.toThrow();
219
- unregister();
220
- });
221
- it("should handle location handler exceptions", async () => {
222
- const windowRouter = new Router({
223
- routes: [{ path: "/", app: "home" }],
224
- apps: mockApps,
225
- fallback: () => {
226
- throw new Error("Location handler error");
227
- }
228
- });
229
- await windowRouter.push("/");
230
- await expect(
231
- windowRouter[methodName]("/about")
232
- ).rejects.toThrow();
233
- windowRouter.destroy();
234
- });
235
- });
236
- describe("\u{1F9E9} ".concat(methodName, " Async Component Handling"), () => {
237
- it("should correctly handle async components", async () => {
238
- const asyncRouter = new Router({
239
- routes: [
240
- {
241
- path: "/async",
242
- app: "home",
243
- asyncComponent: async () => {
244
- await new Promise(
245
- (resolve) => setTimeout(resolve, 10)
246
- );
247
- return () => "AsyncComponent";
248
- }
249
- }
250
- ],
251
- apps: mockApps,
252
- fallback: (to, from) => {
253
- return { windowNavigation: true };
254
- }
255
- });
256
- const result = await asyncRouter[methodName]("/async");
257
- expect(result.handle).not.toBeNull();
258
- expect(result.isPush).toBe(expectedIsPush);
259
- expect(result.matched[0].component).toBeUndefined();
260
- expect(result.matched[0].asyncComponent).toBeDefined();
261
- expect(result.handleResult).toEqual({ windowNavigation: true });
262
- asyncRouter.destroy();
263
- });
264
- it("should handle async component loading failures", async () => {
265
- const asyncRouter = new Router({
266
- routes: [
267
- {
268
- path: "/async-error",
269
- app: "home",
270
- asyncComponent: async () => {
271
- throw new Error("Component load failed");
272
- }
273
- }
274
- ],
275
- apps: mockApps,
276
- fallback: (to, from) => {
277
- return { fallbackHandled: true };
278
- }
279
- });
280
- const result = await asyncRouter[methodName]("/async-error");
281
- expect(result.handle).not.toBeNull();
282
- expect(result.matched[0].component).toBeUndefined();
283
- expect(result.matched[0].asyncComponent).toBeDefined();
284
- expect(result.handleResult).toEqual({ fallbackHandled: true });
285
- asyncRouter.destroy();
286
- });
287
- });
288
- describe("\u{1F527} ".concat(methodName, " Differences from Other Methods"), () => {
289
- it("should behave differently from push/replace methods", async () => {
290
- await router.push("/about");
291
- const pushResult = await router.push("/user/123");
292
- const windowResult = await router[methodName]("/user/456");
293
- expect(router.route.path).toBe("/user/123");
294
- expect(windowResult.isPush).toBe(expectedIsPush);
295
- expect(windowResult.type).toBe(RouteType[methodName]);
296
- expect(pushResult.type).toBe(RouteType.push);
297
- expect(windowResult.type).toBe(RouteType[methodName]);
298
- });
299
- it("should maintain consistency with resolve method in URL parsing", async () => {
300
- const resolvedRoute = router.resolve("/user/789");
301
- const windowRoute = await router[methodName]("/user/789");
302
- expect(windowRoute.url.href).toBe(resolvedRoute.url.href);
303
- expect(windowRoute.params).toEqual(resolvedRoute.params);
304
- expect(windowRoute.matched).toEqual(resolvedRoute.matched);
305
- expect(windowRoute.type).toBe(RouteType[methodName]);
306
- expect(resolvedRoute.type).toBe(RouteType.push);
307
- expect(windowRoute.isPush).toBe(expectedIsPush);
308
- expect(resolvedRoute.isPush).toBe(true);
309
- });
310
- });
311
- }
312
- createWindowNavigationTests("pushWindow", true);
313
- createWindowNavigationTests("replaceWindow", false);
314
- describe("\u{1F504} pushWindow and replaceWindow Comparison Tests", () => {
315
- it("the only difference between the two methods should be the isPush flag", async () => {
316
- const pushResult = await router.pushWindow("/user/123");
317
- const replaceResult = await router.replaceWindow("/user/123");
318
- expect(pushResult.url.href).toBe(replaceResult.url.href);
319
- expect(pushResult.params).toEqual(replaceResult.params);
320
- expect(pushResult.query).toEqual(replaceResult.query);
321
- expect(pushResult.url.hash).toBe(replaceResult.url.hash);
322
- expect(pushResult.matched).toEqual(replaceResult.matched);
323
- expect(pushResult.isPush).toBe(true);
324
- expect(replaceResult.isPush).toBe(false);
325
- expect(pushResult.type).toBe(RouteType.pushWindow);
326
- expect(replaceResult.type).toBe(RouteType.replaceWindow);
327
- });
328
- it("both methods should call the same location handler", async () => {
329
- const locationCalls = [];
330
- const windowRouter = new Router({
331
- routes: [{ path: "/", app: "home" }],
332
- apps: mockApps,
333
- fallback: (to, from) => {
334
- locationCalls.push({
335
- method: to.type,
336
- isPush: to.isPush,
337
- path: to.path
338
- });
339
- return { called: true };
340
- }
341
- });
342
- await windowRouter.push("/");
343
- await windowRouter.pushWindow("/test");
344
- await windowRouter.replaceWindow("/test");
345
- expect(locationCalls).toHaveLength(2);
346
- expect(locationCalls[0]).toEqual({
347
- method: "pushWindow",
348
- isPush: true,
349
- path: "/test"
350
- });
351
- expect(locationCalls[1]).toEqual({
352
- method: "replaceWindow",
353
- isPush: false,
354
- path: "/test"
355
- });
356
- windowRouter.destroy();
357
- });
358
- });
359
- });
@@ -1 +0,0 @@
1
- export {};