@esmx/router 3.0.0-rc.18 → 3.0.0-rc.20

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 (158) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +70 -0
  3. package/README.zh-CN.md +70 -0
  4. package/dist/error.d.ts +23 -0
  5. package/dist/error.mjs +61 -0
  6. package/dist/increment-id.d.ts +7 -0
  7. package/dist/increment-id.mjs +11 -0
  8. package/dist/index.d.ts +5 -3
  9. package/dist/index.mjs +14 -3
  10. package/dist/index.test.mjs +8 -0
  11. package/dist/location.d.ts +15 -0
  12. package/dist/location.mjs +53 -0
  13. package/dist/location.test.d.ts +8 -0
  14. package/dist/location.test.mjs +370 -0
  15. package/dist/matcher.d.ts +3 -0
  16. package/dist/matcher.mjs +44 -0
  17. package/dist/matcher.test.mjs +1492 -0
  18. package/dist/micro-app.d.ts +18 -0
  19. package/dist/micro-app.dom.test.d.ts +1 -0
  20. package/dist/micro-app.dom.test.mjs +532 -0
  21. package/dist/micro-app.mjs +80 -0
  22. package/dist/navigation.d.ts +43 -0
  23. package/dist/navigation.mjs +143 -0
  24. package/dist/navigation.test.d.ts +1 -0
  25. package/dist/navigation.test.mjs +681 -0
  26. package/dist/options.d.ts +4 -0
  27. package/dist/options.mjs +88 -0
  28. package/dist/route-task.d.ts +40 -0
  29. package/dist/route-task.mjs +75 -0
  30. package/dist/route-task.test.d.ts +1 -0
  31. package/dist/route-task.test.mjs +673 -0
  32. package/dist/route-transition.d.ts +53 -0
  33. package/dist/route-transition.mjs +307 -0
  34. package/dist/route-transition.test.d.ts +1 -0
  35. package/dist/route-transition.test.mjs +146 -0
  36. package/dist/route.d.ts +72 -0
  37. package/dist/route.mjs +194 -0
  38. package/dist/route.test.d.ts +1 -0
  39. package/dist/route.test.mjs +1664 -0
  40. package/dist/router-back.test.d.ts +1 -0
  41. package/dist/router-back.test.mjs +361 -0
  42. package/dist/router-forward.test.d.ts +1 -0
  43. package/dist/router-forward.test.mjs +376 -0
  44. package/dist/router-go.test.d.ts +1 -0
  45. package/dist/router-go.test.mjs +73 -0
  46. package/dist/router-guards-cleanup.test.d.ts +1 -0
  47. package/dist/router-guards-cleanup.test.mjs +437 -0
  48. package/dist/router-link.d.ts +10 -0
  49. package/dist/router-link.mjs +126 -0
  50. package/dist/router-push.test.d.ts +1 -0
  51. package/dist/router-push.test.mjs +115 -0
  52. package/dist/router-replace.test.d.ts +1 -0
  53. package/dist/router-replace.test.mjs +114 -0
  54. package/dist/router-resolve.test.d.ts +1 -0
  55. package/dist/router-resolve.test.mjs +393 -0
  56. package/dist/router-restart-app.dom.test.d.ts +1 -0
  57. package/dist/router-restart-app.dom.test.mjs +616 -0
  58. package/dist/router-window-navigation.test.d.ts +1 -0
  59. package/dist/router-window-navigation.test.mjs +359 -0
  60. package/dist/router.d.ts +109 -102
  61. package/dist/router.mjs +260 -361
  62. package/dist/types.d.ts +246 -0
  63. package/dist/types.mjs +18 -0
  64. package/dist/util.d.ts +26 -0
  65. package/dist/util.mjs +53 -0
  66. package/dist/util.test.d.ts +1 -0
  67. package/dist/util.test.mjs +1020 -0
  68. package/package.json +10 -13
  69. package/src/error.ts +84 -0
  70. package/src/increment-id.ts +12 -0
  71. package/src/index.test.ts +9 -0
  72. package/src/index.ts +54 -3
  73. package/src/location.test.ts +406 -0
  74. package/src/location.ts +96 -0
  75. package/src/matcher.test.ts +1685 -0
  76. package/src/matcher.ts +59 -0
  77. package/src/micro-app.dom.test.ts +708 -0
  78. package/src/micro-app.ts +101 -0
  79. package/src/navigation.test.ts +858 -0
  80. package/src/navigation.ts +195 -0
  81. package/src/options.ts +131 -0
  82. package/src/route-task.test.ts +901 -0
  83. package/src/route-task.ts +105 -0
  84. package/src/route-transition.test.ts +178 -0
  85. package/src/route-transition.ts +425 -0
  86. package/src/route.test.ts +2014 -0
  87. package/src/route.ts +308 -0
  88. package/src/router-back.test.ts +487 -0
  89. package/src/router-forward.test.ts +506 -0
  90. package/src/router-go.test.ts +91 -0
  91. package/src/router-guards-cleanup.test.ts +595 -0
  92. package/src/router-link.ts +235 -0
  93. package/src/router-push.test.ts +140 -0
  94. package/src/router-replace.test.ts +139 -0
  95. package/src/router-resolve.test.ts +475 -0
  96. package/src/router-restart-app.dom.test.ts +783 -0
  97. package/src/router-window-navigation.test.ts +457 -0
  98. package/src/router.ts +289 -470
  99. package/src/types.ts +341 -0
  100. package/src/util.test.ts +1262 -0
  101. package/src/util.ts +116 -0
  102. package/dist/history/abstract.d.ts +0 -29
  103. package/dist/history/abstract.mjs +0 -107
  104. package/dist/history/base.d.ts +0 -79
  105. package/dist/history/base.mjs +0 -275
  106. package/dist/history/html.d.ts +0 -30
  107. package/dist/history/html.mjs +0 -183
  108. package/dist/history/index.d.ts +0 -7
  109. package/dist/history/index.mjs +0 -16
  110. package/dist/matcher/create-matcher.d.ts +0 -5
  111. package/dist/matcher/create-matcher.mjs +0 -218
  112. package/dist/matcher/create-matcher.spec.mjs +0 -0
  113. package/dist/matcher/index.d.ts +0 -1
  114. package/dist/matcher/index.mjs +0 -1
  115. package/dist/task-pipe/index.d.ts +0 -1
  116. package/dist/task-pipe/index.mjs +0 -1
  117. package/dist/task-pipe/task.d.ts +0 -30
  118. package/dist/task-pipe/task.mjs +0 -66
  119. package/dist/types/index.d.ts +0 -694
  120. package/dist/types/index.mjs +0 -6
  121. package/dist/utils/bom.d.ts +0 -5
  122. package/dist/utils/bom.mjs +0 -10
  123. package/dist/utils/encoding.d.ts +0 -48
  124. package/dist/utils/encoding.mjs +0 -44
  125. package/dist/utils/guards.d.ts +0 -9
  126. package/dist/utils/guards.mjs +0 -12
  127. package/dist/utils/index.d.ts +0 -7
  128. package/dist/utils/index.mjs +0 -27
  129. package/dist/utils/path.d.ts +0 -60
  130. package/dist/utils/path.mjs +0 -282
  131. package/dist/utils/path.spec.mjs +0 -27
  132. package/dist/utils/scroll.d.ts +0 -25
  133. package/dist/utils/scroll.mjs +0 -59
  134. package/dist/utils/utils.d.ts +0 -16
  135. package/dist/utils/utils.mjs +0 -11
  136. package/dist/utils/warn.d.ts +0 -2
  137. package/dist/utils/warn.mjs +0 -12
  138. package/src/history/abstract.ts +0 -149
  139. package/src/history/base.ts +0 -408
  140. package/src/history/html.ts +0 -228
  141. package/src/history/index.ts +0 -20
  142. package/src/matcher/create-matcher.spec.ts +0 -3
  143. package/src/matcher/create-matcher.ts +0 -292
  144. package/src/matcher/index.ts +0 -1
  145. package/src/task-pipe/index.ts +0 -1
  146. package/src/task-pipe/task.ts +0 -97
  147. package/src/types/index.ts +0 -858
  148. package/src/utils/bom.ts +0 -14
  149. package/src/utils/encoding.ts +0 -153
  150. package/src/utils/guards.ts +0 -25
  151. package/src/utils/index.ts +0 -27
  152. package/src/utils/path.spec.ts +0 -32
  153. package/src/utils/path.ts +0 -418
  154. package/src/utils/scroll.ts +0 -120
  155. package/src/utils/utils.ts +0 -30
  156. package/src/utils/warn.ts +0 -13
  157. /package/dist/{matcher/create-matcher.spec.d.ts → index.test.d.ts} +0 -0
  158. /package/dist/{utils/path.spec.d.ts → matcher.test.d.ts} +0 -0
@@ -0,0 +1,114 @@
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
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,393 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from "vitest";
2
+ import { Router } from "./router.mjs";
3
+ import { RouterMode } from "./types.mjs";
4
+ const createTestRouter = () => {
5
+ return new Router({
6
+ mode: RouterMode.memory,
7
+ base: new URL("http://localhost:3000/"),
8
+ routes: createTestRoutes()
9
+ });
10
+ };
11
+ const createTestRoutes = () => {
12
+ return [
13
+ {
14
+ path: "/",
15
+ component: () => "Home",
16
+ meta: { title: "Home Page" }
17
+ },
18
+ {
19
+ path: "/about",
20
+ component: () => "About",
21
+ meta: { title: "About Page", requiresAuth: false }
22
+ },
23
+ {
24
+ path: "/user/:id",
25
+ component: () => "User",
26
+ meta: { title: "User Profile", requiresAuth: true },
27
+ children: [
28
+ {
29
+ path: "/profile",
30
+ component: () => "UserProfile",
31
+ meta: { section: "profile" }
32
+ },
33
+ {
34
+ path: "/settings",
35
+ component: () => "UserSettings",
36
+ meta: { section: "settings" }
37
+ }
38
+ ]
39
+ },
40
+ {
41
+ path: "/admin",
42
+ component: () => "Admin",
43
+ meta: { requiresAuth: true, role: "admin" },
44
+ children: [
45
+ {
46
+ path: "/users",
47
+ component: () => "AdminUsers",
48
+ meta: { section: "users" }
49
+ },
50
+ {
51
+ path: "/settings",
52
+ component: () => "AdminSettings",
53
+ meta: { section: "settings" }
54
+ }
55
+ ]
56
+ },
57
+ {
58
+ path: "/products/:category/:id",
59
+ component: () => "Product",
60
+ meta: { title: "Product Detail" }
61
+ }
62
+ ];
63
+ };
64
+ const createTestCases = () => {
65
+ return {
66
+ validPaths: [
67
+ { path: "/", shouldMatch: true },
68
+ { path: "/about", shouldMatch: true },
69
+ { path: "/user/123", shouldMatch: true },
70
+ { path: "/admin/users", shouldMatch: true }
71
+ ],
72
+ invalidPaths: [
73
+ { path: "/invalid", shouldMatch: false },
74
+ { path: "/user", shouldMatch: false }
75
+ // Missing required parameter
76
+ ]
77
+ };
78
+ };
79
+ describe("Router.resolve method tests", () => {
80
+ let router;
81
+ beforeEach(async () => {
82
+ router = createTestRouter();
83
+ await router.replace("/");
84
+ });
85
+ afterEach(() => {
86
+ router.destroy();
87
+ });
88
+ describe("Core resolution functionality", () => {
89
+ test("should return complete Route object with all required properties", () => {
90
+ const route = router.resolve("/about");
91
+ expect(route).toBeInstanceOf(Object);
92
+ expect(route.type).toBe("push");
93
+ expect(route.path).toBe("/about");
94
+ expect(route.fullPath).toBe("/about");
95
+ expect(route.url).toBeInstanceOf(URL);
96
+ expect(route.params).toBeInstanceOf(Object);
97
+ expect(route.query).toBeInstanceOf(Object);
98
+ expect(route.meta).toBeInstanceOf(Object);
99
+ expect(route.matched).toBeInstanceOf(Array);
100
+ });
101
+ test("should not trigger actual navigation", () => {
102
+ const originalPath = router.route.path;
103
+ router.resolve("/about");
104
+ router.resolve("/user/123");
105
+ router.resolve("/admin/users");
106
+ expect(router.route.path).toBe(originalPath);
107
+ });
108
+ test("should correctly resolve string path", () => {
109
+ const route = router.resolve("/user/123");
110
+ expect(route.path).toBe("/user/123");
111
+ expect(route.params.id).toBe("123");
112
+ expect(route.matched.length).toBeGreaterThan(0);
113
+ expect(route.config).not.toBeNull();
114
+ });
115
+ test("should correctly resolve object configuration", () => {
116
+ const route = router.resolve({
117
+ path: "/user/456",
118
+ query: { tab: "profile", active: "true" },
119
+ hash: "#section1"
120
+ });
121
+ expect(route.path).toBe("/user/456");
122
+ expect(route.params.id).toBe("456");
123
+ expect(route.query.tab).toBe("profile");
124
+ expect(route.query.active).toBe("true");
125
+ expect(route.url.hash).toBe("#section1");
126
+ expect(route.fullPath).toBe(
127
+ "/user/456?tab=profile&active=true#section1"
128
+ );
129
+ });
130
+ });
131
+ describe("Path resolution and parameter extraction", () => {
132
+ test("should correctly resolve single path parameter", () => {
133
+ const route = router.resolve("/user/123");
134
+ expect(route.params.id).toBe("123");
135
+ expect(route.path).toBe("/user/123");
136
+ expect(route.matched.length).toBe(1);
137
+ });
138
+ test("should correctly resolve multiple path parameters", () => {
139
+ const route = router.resolve(
140
+ "/products/electronics/laptop-123"
141
+ );
142
+ expect(route.params.category).toBe("electronics");
143
+ expect(route.params.id).toBe("laptop-123");
144
+ expect(route.path).toBe("/products/electronics/laptop-123");
145
+ });
146
+ test("should correctly resolve query parameters", () => {
147
+ const route = router.resolve(
148
+ "/about?lang=en&theme=dark&debug=true"
149
+ );
150
+ expect(route.query.lang).toBe("en");
151
+ expect(route.query.theme).toBe("dark");
152
+ expect(route.query.debug).toBe("true");
153
+ expect(route.queryArray.lang).toEqual(["en"]);
154
+ expect(route.queryArray.theme).toEqual(["dark"]);
155
+ });
156
+ test("should correctly handle duplicate query parameters", () => {
157
+ const route = router.resolve(
158
+ "/about?tags=vue&tags=router&tags=test"
159
+ );
160
+ expect(route.query.tags).toBe("vue");
161
+ expect(route.queryArray.tags).toEqual(["vue", "router", "test"]);
162
+ });
163
+ test("should correctly resolve hash fragment", () => {
164
+ const route = router.resolve("/about#introduction");
165
+ expect(route.url.hash).toBe("#introduction");
166
+ expect(route.fullPath).toBe("/about#introduction");
167
+ });
168
+ test("should correctly handle complex URL combination", () => {
169
+ const route = router.resolve(
170
+ "/user/123?tab=profile&edit=true#personal-info"
171
+ );
172
+ expect(route.params.id).toBe("123");
173
+ expect(route.query.tab).toBe("profile");
174
+ expect(route.query.edit).toBe("true");
175
+ expect(route.url.hash).toBe("#personal-info");
176
+ expect(route.fullPath).toBe(
177
+ "/user/123?tab=profile&edit=true#personal-info"
178
+ );
179
+ });
180
+ });
181
+ describe("Nested route resolution", () => {
182
+ test("should correctly resolve nested routes", () => {
183
+ var _a, _b;
184
+ const route = router.resolve("/user/123/profile");
185
+ expect(route.params.id).toBe("123");
186
+ expect(route.path).toBe("/user/123/profile");
187
+ expect(route.matched.length).toBe(2);
188
+ expect((_b = (_a = route.config) == null ? void 0 : _a.meta) == null ? void 0 : _b.section).toBe("profile");
189
+ });
190
+ test("should correctly resolve deeply nested routes", () => {
191
+ var _a, _b;
192
+ const route = router.resolve("/admin/users");
193
+ expect(route.path).toBe("/admin/users");
194
+ expect(route.matched.length).toBe(2);
195
+ expect((_b = (_a = route.config) == null ? void 0 : _a.meta) == null ? void 0 : _b.section).toBe("users");
196
+ });
197
+ test("should return last matched route configuration", () => {
198
+ var _a, _b;
199
+ const route = router.resolve("/user/123/settings");
200
+ expect((_b = (_a = route.config) == null ? void 0 : _a.meta) == null ? void 0 : _b.section).toBe("settings");
201
+ expect(route.meta.section).toBe("settings");
202
+ expect(route.meta.title).toBeUndefined();
203
+ });
204
+ });
205
+ describe("Meta information handling", () => {
206
+ test("should correctly return route meta information", () => {
207
+ const route = router.resolve("/about");
208
+ expect(route.meta.title).toBe("About Page");
209
+ expect(route.meta.requiresAuth).toBe(false);
210
+ });
211
+ test("should return last matched route meta in nested routes", () => {
212
+ const route = router.resolve("/user/123/profile");
213
+ expect(route.meta.section).toBe("profile");
214
+ expect(route.meta.title).toBeUndefined();
215
+ expect(route.meta.requiresAuth).toBeUndefined();
216
+ });
217
+ test("should return empty object when no meta information exists", () => {
218
+ const testRouter = new Router({
219
+ mode: RouterMode.memory,
220
+ base: new URL("http://localhost:3000/"),
221
+ routes: [
222
+ {
223
+ path: "/no-meta",
224
+ component: () => "NoMeta"
225
+ }
226
+ ]
227
+ });
228
+ const route = testRouter.resolve("/no-meta");
229
+ expect(route.meta).toEqual({});
230
+ testRouter.destroy();
231
+ });
232
+ });
233
+ describe("Error handling and edge cases", () => {
234
+ test("should correctly handle non-existent routes", () => {
235
+ const route = router.resolve("/non-existent");
236
+ expect(route.matched).toEqual([]);
237
+ expect(route.config).toBeNull();
238
+ expect(route.meta).toEqual({});
239
+ expect(route.params).toEqual({});
240
+ expect(route.path).toBe("/non-existent");
241
+ });
242
+ test("should correctly handle root path", () => {
243
+ const route = router.resolve("/");
244
+ expect(route.path).toBe("/");
245
+ expect(route.matched.length).toBe(1);
246
+ expect(route.meta.title).toBe("Home Page");
247
+ });
248
+ test("should correctly handle empty string path", () => {
249
+ const route = router.resolve("");
250
+ expect(route.path).toBe("/");
251
+ expect(route.matched.length).toBe(1);
252
+ });
253
+ test("should correctly handle relative path", () => {
254
+ const route = router.resolve("about");
255
+ expect(route.path).toBe("/about");
256
+ expect(route.matched.length).toBe(1);
257
+ });
258
+ test("should correctly handle paths with special characters", () => {
259
+ const route = router.resolve("/user/test%20user");
260
+ expect(route.params.id).toBe("test%20user");
261
+ expect(route.path).toBe("/user/test%20user");
262
+ });
263
+ test("should correctly handle URL encoded parameters", () => {
264
+ const route = router.resolve("/user/john%40example.com");
265
+ expect(route.params.id).toBe("john%40example.com");
266
+ expect(route.path).toBe("/user/john%40example.com");
267
+ });
268
+ });
269
+ describe("Object parameter resolution", () => {
270
+ test("should correctly handle object with params", () => {
271
+ const route = router.resolve({
272
+ path: "/user/789"
273
+ });
274
+ expect(route.params.id).toBe("789");
275
+ expect(route.path).toBe("/user/789");
276
+ });
277
+ test("should correctly handle object with query", () => {
278
+ const route = router.resolve({
279
+ path: "/about",
280
+ query: { lang: "zh", version: "2.0" }
281
+ });
282
+ expect(route.query.lang).toBe("zh");
283
+ expect(route.query.version).toBe("2.0");
284
+ expect(route.fullPath).toBe("/about?lang=zh&version=2.0");
285
+ });
286
+ test("should correctly handle object with hash", () => {
287
+ const route = router.resolve({
288
+ path: "/about",
289
+ hash: "#features"
290
+ });
291
+ expect(route.url.hash).toBe("#features");
292
+ expect(route.fullPath).toBe("/about#features");
293
+ });
294
+ test("should correctly handle object with state", () => {
295
+ const customState = {
296
+ from: "navigation",
297
+ timestamp: 1234567890
298
+ };
299
+ const route = router.resolve({
300
+ path: "/about",
301
+ state: customState
302
+ });
303
+ expect(route.state).toEqual(customState);
304
+ });
305
+ test("should correctly handle keepScrollPosition option", () => {
306
+ const route = router.resolve({
307
+ path: "/about",
308
+ keepScrollPosition: true
309
+ });
310
+ expect(route.keepScrollPosition).toBe(true);
311
+ });
312
+ });
313
+ describe("URL handling", () => {
314
+ test("should correctly handle complete URL", () => {
315
+ const route = router.resolve("http://localhost:3000/about");
316
+ expect(route.path).toBe("/about");
317
+ expect(route.url.href).toBe("http://localhost:3000/about");
318
+ });
319
+ test("should correctly handle different domain URL", () => {
320
+ const route = router.resolve("https://example.com/external");
321
+ expect(route.matched).toEqual([]);
322
+ expect(route.config).toBeNull();
323
+ });
324
+ test("should correctly handle URL with different port", () => {
325
+ const route = router.resolve("http://localhost:8080/about");
326
+ expect(route.matched).toEqual([]);
327
+ expect(route.config).toBeNull();
328
+ });
329
+ });
330
+ describe("Type and status validation", () => {
331
+ test("resolved route should have correct type", () => {
332
+ const route = router.resolve("/about");
333
+ expect(route.type).toBe("push");
334
+ expect(route.isPush).toBe(true);
335
+ });
336
+ test("resolved route should have correct handle state", () => {
337
+ const route = router.resolve("/about");
338
+ expect(route.handle).toBe(null);
339
+ });
340
+ test("resolved route should have correct URL object properties", () => {
341
+ const route = router.resolve("/about?lang=en#intro");
342
+ expect(route.url).toBeInstanceOf(URL);
343
+ expect(route.url.pathname).toBe("/about");
344
+ expect(route.url.search).toBe("?lang=en");
345
+ expect(route.url.hash).toBe("#intro");
346
+ });
347
+ test("resolved route should have frozen matched array", () => {
348
+ const route = router.resolve("/about");
349
+ expect(Object.isFrozen(route.matched)).toBe(true);
350
+ });
351
+ });
352
+ describe("Practical use case scenarios", () => {
353
+ test("should support generating link URL without triggering navigation", () => {
354
+ const route = router.resolve("/user/123?tab=profile");
355
+ const linkUrl = route.url.href;
356
+ expect(linkUrl).toBe("http://localhost:3000/user/123?tab=profile");
357
+ expect(router.route.path).toBe("/");
358
+ });
359
+ test("should support pre-checking route matching status", () => {
360
+ const validRoute = router.resolve("/about");
361
+ const invalidRoute = router.resolve("/non-existent");
362
+ expect(validRoute.matched.length).toBeGreaterThan(0);
363
+ expect(invalidRoute.matched.length).toBe(0);
364
+ });
365
+ test("should support extracting route parameters and meta information", () => {
366
+ var _a;
367
+ const route = router.resolve("/user/123/profile");
368
+ expect(route.params.id).toBe("123");
369
+ expect(route.meta.section).toBe("profile");
370
+ expect((_a = route.config) == null ? void 0 : _a.path).toBe("/profile");
371
+ });
372
+ test("should support testing route configuration validity with valid paths", () => {
373
+ const testCases = createTestCases().validPaths;
374
+ testCases.forEach(({ path, shouldMatch }) => {
375
+ const route = router.resolve(path);
376
+ if (shouldMatch) {
377
+ expect(route.matched.length).toBeGreaterThan(0);
378
+ expect(route.config).not.toBeNull();
379
+ }
380
+ });
381
+ });
382
+ test("should support testing route configuration validity with invalid paths", () => {
383
+ const testCases = createTestCases().invalidPaths;
384
+ testCases.forEach(({ path, shouldMatch }) => {
385
+ const route = router.resolve(path);
386
+ if (!shouldMatch) {
387
+ expect(route.matched.length).toBe(0);
388
+ expect(route.config).toBeNull();
389
+ }
390
+ });
391
+ });
392
+ });
393
+ });
@@ -0,0 +1 @@
1
+ export {};