@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.
- package/README.zh-CN.md +82 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.mjs +0 -1
- package/dist/navigation.mjs +4 -4
- package/package.json +3 -3
- package/src/index.ts +0 -3
- package/src/navigation.ts +4 -4
- package/dist/index.test.d.ts +0 -1
- package/dist/index.test.mjs +0 -8
- package/dist/location.test.d.ts +0 -8
- package/dist/location.test.mjs +0 -370
- package/dist/matcher.test.d.ts +0 -1
- package/dist/matcher.test.mjs +0 -1492
- package/dist/micro-app.dom.test.d.ts +0 -1
- package/dist/micro-app.dom.test.mjs +0 -532
- package/dist/navigation.test.d.ts +0 -1
- package/dist/navigation.test.mjs +0 -681
- package/dist/route-task.test.d.ts +0 -1
- package/dist/route-task.test.mjs +0 -673
- package/dist/route-transition.test.d.ts +0 -1
- package/dist/route-transition.test.mjs +0 -146
- package/dist/route.test.d.ts +0 -1
- package/dist/route.test.mjs +0 -1664
- package/dist/router-back.test.d.ts +0 -1
- package/dist/router-back.test.mjs +0 -361
- package/dist/router-forward.test.d.ts +0 -1
- package/dist/router-forward.test.mjs +0 -376
- package/dist/router-go.test.d.ts +0 -1
- package/dist/router-go.test.mjs +0 -73
- package/dist/router-guards-cleanup.test.d.ts +0 -1
- package/dist/router-guards-cleanup.test.mjs +0 -437
- package/dist/router-push.test.d.ts +0 -1
- package/dist/router-push.test.mjs +0 -115
- package/dist/router-replace.test.d.ts +0 -1
- package/dist/router-replace.test.mjs +0 -114
- package/dist/router-resolve.test.d.ts +0 -1
- package/dist/router-resolve.test.mjs +0 -393
- package/dist/router-restart-app.dom.test.d.ts +0 -1
- package/dist/router-restart-app.dom.test.mjs +0 -616
- package/dist/router-window-navigation.test.d.ts +0 -1
- package/dist/router-window-navigation.test.mjs +0 -359
- package/dist/util.test.d.ts +0 -1
- package/dist/util.test.mjs +0 -1020
- package/src/index.test.ts +0 -9
- package/src/location.test.ts +0 -406
- package/src/matcher.test.ts +0 -1685
- package/src/micro-app.dom.test.ts +0 -708
- package/src/navigation.test.ts +0 -858
- package/src/route-task.test.ts +0 -901
- package/src/route-transition.test.ts +0 -178
- package/src/route.test.ts +0 -2014
- package/src/router-back.test.ts +0 -487
- package/src/router-forward.test.ts +0 -506
- package/src/router-go.test.ts +0 -91
- package/src/router-guards-cleanup.test.ts +0 -595
- package/src/router-push.test.ts +0 -140
- package/src/router-replace.test.ts +0 -139
- package/src/router-resolve.test.ts +0 -475
- package/src/router-restart-app.dom.test.ts +0 -783
- package/src/router-window-navigation.test.ts +0 -457
- package/src/util.test.ts +0 -1262
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,361 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
-
import { Router } from "./router.mjs";
|
|
3
|
-
import { RouteType, RouterMode } from "./types.mjs";
|
|
4
|
-
describe("Router.back Tests", () => {
|
|
5
|
-
let router;
|
|
6
|
-
let executionLog;
|
|
7
|
-
beforeEach(async () => {
|
|
8
|
-
executionLog = [];
|
|
9
|
-
router = new Router({
|
|
10
|
-
mode: RouterMode.memory,
|
|
11
|
-
base: new URL("http://localhost:3000/"),
|
|
12
|
-
fallback: (to, from) => {
|
|
13
|
-
executionLog.push("location-handler-".concat(to.path));
|
|
14
|
-
},
|
|
15
|
-
routes: [
|
|
16
|
-
{
|
|
17
|
-
path: "/",
|
|
18
|
-
component: () => "Home"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
path: "/about",
|
|
22
|
-
component: () => "About"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
path: "/user/:id",
|
|
26
|
-
component: () => "User",
|
|
27
|
-
beforeEnter: (to) => {
|
|
28
|
-
if (to.params.id === "blocked") {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
if (to.params.id === "redirect") {
|
|
32
|
-
return "/about";
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
path: "/async",
|
|
38
|
-
asyncComponent: () => new Promise((resolve) => {
|
|
39
|
-
setTimeout(() => resolve("AsyncComponent"), 10);
|
|
40
|
-
})
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
path: "/async-error",
|
|
44
|
-
asyncComponent: () => new Promise((_, reject) => {
|
|
45
|
-
setTimeout(
|
|
46
|
-
() => reject(new Error("Load failed")),
|
|
47
|
-
10
|
|
48
|
-
);
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
});
|
|
53
|
-
await router.push("/");
|
|
54
|
-
});
|
|
55
|
-
afterEach(() => {
|
|
56
|
-
router.destroy();
|
|
57
|
-
});
|
|
58
|
-
describe("\u{1F3AF} Core Behavior", () => {
|
|
59
|
-
test("back should return Promise<Route | null>", async () => {
|
|
60
|
-
await router.push("/about");
|
|
61
|
-
const route = await router.back();
|
|
62
|
-
expect(route).toBeInstanceOf(Object);
|
|
63
|
-
expect(route == null ? void 0 : route.path).toBe("/");
|
|
64
|
-
expect(route == null ? void 0 : route.handle).not.toBeNull();
|
|
65
|
-
});
|
|
66
|
-
test("back should navigate to previous route", async () => {
|
|
67
|
-
await router.push("/about");
|
|
68
|
-
await router.push("/user/123");
|
|
69
|
-
const backRoute = await router.back();
|
|
70
|
-
expect(backRoute == null ? void 0 : backRoute.path).toBe("/about");
|
|
71
|
-
expect(router.route.path).toBe("/about");
|
|
72
|
-
});
|
|
73
|
-
test("back should update router state", async () => {
|
|
74
|
-
await router.push("/about");
|
|
75
|
-
await router.back();
|
|
76
|
-
expect(router.route.path).toBe("/");
|
|
77
|
-
expect(router.route.handle).not.toBeNull();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
describe("\u{1F504} History Navigation Logic", () => {
|
|
81
|
-
test("back should navigate based on history stack", async () => {
|
|
82
|
-
await router.push("/about");
|
|
83
|
-
await router.push("/user/123");
|
|
84
|
-
const route1 = await router.back();
|
|
85
|
-
expect(route1 == null ? void 0 : route1.path).toBe("/about");
|
|
86
|
-
expect(router.route.path).toBe("/about");
|
|
87
|
-
const route2 = await router.back();
|
|
88
|
-
expect(route2 == null ? void 0 : route2.path).toBe("/");
|
|
89
|
-
expect(router.route.path).toBe("/");
|
|
90
|
-
});
|
|
91
|
-
test("back beyond history boundaries should return null", async () => {
|
|
92
|
-
const testRouter = new Router({
|
|
93
|
-
mode: RouterMode.memory,
|
|
94
|
-
base: new URL("http://localhost:3000/"),
|
|
95
|
-
routes: [
|
|
96
|
-
{ path: "/", component: "Home" },
|
|
97
|
-
{ path: "/about", component: "About" }
|
|
98
|
-
]
|
|
99
|
-
});
|
|
100
|
-
await testRouter.replace("/about");
|
|
101
|
-
const route = await testRouter.back();
|
|
102
|
-
expect(route).toBe(null);
|
|
103
|
-
expect(testRouter.route.path).toBe("/about");
|
|
104
|
-
testRouter.destroy();
|
|
105
|
-
});
|
|
106
|
-
test("back should return correct RouteType", async () => {
|
|
107
|
-
await router.push("/about");
|
|
108
|
-
const route = await router.back();
|
|
109
|
-
expect(route == null ? void 0 : route.type).toBe(RouteType.back);
|
|
110
|
-
});
|
|
111
|
-
test("back should keep isPush as false", async () => {
|
|
112
|
-
await router.push("/about");
|
|
113
|
-
const route = await router.back();
|
|
114
|
-
expect(route == null ? void 0 : route.isPush).toBe(false);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
describe("\u{1F3C3} Concurrency Control", () => {
|
|
118
|
-
test("later initiated back should cancel earlier back", async () => {
|
|
119
|
-
await router.push("/about");
|
|
120
|
-
await router.push("/user/123");
|
|
121
|
-
const [firstResult, secondResult] = await Promise.all([
|
|
122
|
-
router.back(),
|
|
123
|
-
// First operation, should succeed
|
|
124
|
-
router.back()
|
|
125
|
-
// Second operation, returns null due to first one in progress
|
|
126
|
-
]);
|
|
127
|
-
expect(firstResult == null ? void 0 : firstResult.handle).not.toBeNull();
|
|
128
|
-
expect(secondResult).toBe(null);
|
|
129
|
-
expect(router.route.path).toBe("/about");
|
|
130
|
-
});
|
|
131
|
-
test("cancelled tasks should not affect micro-app state", async () => {
|
|
132
|
-
const updateSpy = vi.spyOn(router.microApp, "_update");
|
|
133
|
-
await router.push("/about");
|
|
134
|
-
await router.push("/user/123");
|
|
135
|
-
updateSpy.mockClear();
|
|
136
|
-
const [firstResult, secondResult] = await Promise.all([
|
|
137
|
-
router.back(),
|
|
138
|
-
// First operation succeeds
|
|
139
|
-
router.back()
|
|
140
|
-
// Second operation returns null
|
|
141
|
-
]);
|
|
142
|
-
expect(firstResult == null ? void 0 : firstResult.handle).not.toBeNull();
|
|
143
|
-
expect(secondResult).toBe(null);
|
|
144
|
-
expect(updateSpy).toHaveBeenCalledTimes(1);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
describe("\u{1F3AD} Micro-app Integration", () => {
|
|
148
|
-
test("back should trigger micro-app update", async () => {
|
|
149
|
-
const updateSpy = vi.spyOn(router.microApp, "_update");
|
|
150
|
-
await router.push("/about");
|
|
151
|
-
await router.back();
|
|
152
|
-
expect(updateSpy).toHaveBeenCalled();
|
|
153
|
-
});
|
|
154
|
-
test("micro-app update should happen after route state update", async () => {
|
|
155
|
-
let routePathWhenUpdated = null;
|
|
156
|
-
vi.spyOn(router.microApp, "_update").mockImplementation(() => {
|
|
157
|
-
routePathWhenUpdated = router.route.path;
|
|
158
|
-
});
|
|
159
|
-
await router.push("/about");
|
|
160
|
-
await router.back();
|
|
161
|
-
expect(routePathWhenUpdated).toBe("/");
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
describe("\u26A1 Async Components & Back", () => {
|
|
165
|
-
test("back to async component route should wait for component loading", async () => {
|
|
166
|
-
await router.push("/about");
|
|
167
|
-
await router.push("/async");
|
|
168
|
-
const route = await router.back();
|
|
169
|
-
expect(route == null ? void 0 : route.path).toBe("/about");
|
|
170
|
-
expect(route == null ? void 0 : route.handle).not.toBeNull();
|
|
171
|
-
});
|
|
172
|
-
test("back to failed async component route should handle error correctly", async () => {
|
|
173
|
-
await router.push("/about");
|
|
174
|
-
await expect(router.push("/async-error")).rejects.toThrow();
|
|
175
|
-
expect(router.route.path).toBe("/about");
|
|
176
|
-
const route = await router.back();
|
|
177
|
-
expect(route == null ? void 0 : route.path).toBe("/");
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
describe("\u{1F6E1}\uFE0F Back Guard Behavior", () => {
|
|
181
|
-
test("back navigation should work normally after blocked route attempt", async () => {
|
|
182
|
-
await router.push("/about");
|
|
183
|
-
await router.push("/user/123");
|
|
184
|
-
const blockedResult = await router.push("/user/blocked");
|
|
185
|
-
expect(blockedResult.path).toBe("/user/blocked");
|
|
186
|
-
expect(router.route.path).toBe("/user/blocked");
|
|
187
|
-
const route = await router.back();
|
|
188
|
-
expect(route == null ? void 0 : route.path).toBe("/user/123");
|
|
189
|
-
});
|
|
190
|
-
test("redirect guard should work during navigation", async () => {
|
|
191
|
-
const route = await router.push("/user/redirect");
|
|
192
|
-
expect(route.path).toBe("/about");
|
|
193
|
-
expect(router.route.path).toBe("/about");
|
|
194
|
-
const backRoute = await router.back();
|
|
195
|
-
expect(backRoute == null ? void 0 : backRoute.path).toBe("/");
|
|
196
|
-
});
|
|
197
|
-
test("afterEach only executes when navigation succeeds", async () => {
|
|
198
|
-
let afterEachCalled = false;
|
|
199
|
-
const testRouter = new Router({
|
|
200
|
-
mode: RouterMode.memory,
|
|
201
|
-
base: new URL("http://localhost:3000/"),
|
|
202
|
-
routes: [
|
|
203
|
-
{ path: "/", component: "Home" },
|
|
204
|
-
{ path: "/about", component: "About" },
|
|
205
|
-
{
|
|
206
|
-
path: "/blocked",
|
|
207
|
-
component: "Blocked",
|
|
208
|
-
beforeEnter: () => false
|
|
209
|
-
}
|
|
210
|
-
]
|
|
211
|
-
});
|
|
212
|
-
testRouter.afterEach(() => {
|
|
213
|
-
afterEachCalled = true;
|
|
214
|
-
});
|
|
215
|
-
await testRouter.push("/about");
|
|
216
|
-
afterEachCalled = false;
|
|
217
|
-
await expect(testRouter.push("/blocked")).rejects.toThrow();
|
|
218
|
-
expect(afterEachCalled).toBe(false);
|
|
219
|
-
testRouter.destroy();
|
|
220
|
-
});
|
|
221
|
-
test("beforeEach guard should be called during back operation", async () => {
|
|
222
|
-
let beforeEachCalled = false;
|
|
223
|
-
router.beforeEach(() => {
|
|
224
|
-
beforeEachCalled = true;
|
|
225
|
-
});
|
|
226
|
-
await router.push("/about");
|
|
227
|
-
await router.back();
|
|
228
|
-
expect(beforeEachCalled).toBe(true);
|
|
229
|
-
});
|
|
230
|
-
});
|
|
231
|
-
describe("\u{1F4BE} History Management", () => {
|
|
232
|
-
test("back should navigate correctly in history stack", async () => {
|
|
233
|
-
await router.push("/about");
|
|
234
|
-
await router.push("/user/123");
|
|
235
|
-
const route = await router.back();
|
|
236
|
-
expect(route == null ? void 0 : route.path).toBe("/about");
|
|
237
|
-
expect(router.route.path).toBe("/about");
|
|
238
|
-
});
|
|
239
|
-
test("back operation should not create new history entries", async () => {
|
|
240
|
-
await router.push("/about");
|
|
241
|
-
await router.push("/user/123");
|
|
242
|
-
await router.back();
|
|
243
|
-
const forwardRoute = await router.forward();
|
|
244
|
-
expect(forwardRoute == null ? void 0 : forwardRoute.path).toBe("/user/123");
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
describe("\u274C Error Handling", () => {
|
|
248
|
-
test("back to non-existent route should trigger location handling", async () => {
|
|
249
|
-
const fallbackSpy = vi.fn();
|
|
250
|
-
const testRouter = new Router({
|
|
251
|
-
mode: RouterMode.memory,
|
|
252
|
-
base: new URL("http://localhost:3000/"),
|
|
253
|
-
fallback: fallbackSpy,
|
|
254
|
-
routes: [{ path: "/", component: "Home" }]
|
|
255
|
-
});
|
|
256
|
-
await testRouter.replace("/");
|
|
257
|
-
const result = await testRouter.back();
|
|
258
|
-
expect(result).toBe(null);
|
|
259
|
-
testRouter.destroy();
|
|
260
|
-
});
|
|
261
|
-
test("exceptions during back process should propagate correctly", async () => {
|
|
262
|
-
const testRouter = new Router({
|
|
263
|
-
mode: RouterMode.memory,
|
|
264
|
-
base: new URL("http://localhost:3000/"),
|
|
265
|
-
routes: [
|
|
266
|
-
{ path: "/", component: "Home" },
|
|
267
|
-
{ path: "/about", component: "About" }
|
|
268
|
-
]
|
|
269
|
-
});
|
|
270
|
-
await testRouter.push("/about");
|
|
271
|
-
testRouter.beforeEach(() => {
|
|
272
|
-
throw new Error("Guard error");
|
|
273
|
-
});
|
|
274
|
-
await expect(testRouter.back()).rejects.toThrow("Guard error");
|
|
275
|
-
testRouter.destroy();
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
describe("\u{1F50D} Edge Cases", () => {
|
|
279
|
-
test("back should handle special character paths correctly", async () => {
|
|
280
|
-
const testRouter = new Router({
|
|
281
|
-
mode: RouterMode.memory,
|
|
282
|
-
base: new URL("http://localhost:3000/"),
|
|
283
|
-
routes: [
|
|
284
|
-
{ path: "/", component: "Home" },
|
|
285
|
-
{ path: "/special", component: "Special" }
|
|
286
|
-
]
|
|
287
|
-
});
|
|
288
|
-
await testRouter.push("/");
|
|
289
|
-
await testRouter.push("/special");
|
|
290
|
-
const route = await testRouter.back();
|
|
291
|
-
expect(route == null ? void 0 : route.path).toBe("/");
|
|
292
|
-
expect(testRouter.route.path).toBe("/");
|
|
293
|
-
testRouter.destroy();
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
describe("\u{1F517} Integration with Other Navigation Methods", () => {
|
|
297
|
-
test("back should behave consistently with go(-1)", async () => {
|
|
298
|
-
await router.push("/about");
|
|
299
|
-
await router.push("/user/123");
|
|
300
|
-
const backRoute = await router.back();
|
|
301
|
-
const goRoute = await router.go(-1);
|
|
302
|
-
expect(backRoute == null ? void 0 : backRoute.path).toBe("/about");
|
|
303
|
-
expect(goRoute == null ? void 0 : goRoute.path).toBe("/");
|
|
304
|
-
});
|
|
305
|
-
test("push after back should handle history correctly", async () => {
|
|
306
|
-
await router.push("/about");
|
|
307
|
-
await router.push("/user/123");
|
|
308
|
-
await router.back();
|
|
309
|
-
await router.push("/user/456");
|
|
310
|
-
expect(router.route.path).toBe("/user/456");
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
describe("\u{1F527} handleBackBoundary Callback Tests", () => {
|
|
314
|
-
test("should trigger handleBackBoundary when Navigation returns null", async () => {
|
|
315
|
-
let handleBackBoundaryCalled = false;
|
|
316
|
-
const testRouter = new Router({
|
|
317
|
-
mode: RouterMode.memory,
|
|
318
|
-
base: new URL("http://localhost:3000/"),
|
|
319
|
-
routes: [{ path: "/", component: "Home" }],
|
|
320
|
-
handleBackBoundary: () => {
|
|
321
|
-
handleBackBoundaryCalled = true;
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
await testRouter.replace("/");
|
|
325
|
-
const result = await testRouter.back();
|
|
326
|
-
expect(result).toBe(null);
|
|
327
|
-
expect(handleBackBoundaryCalled).toBe(true);
|
|
328
|
-
testRouter.destroy();
|
|
329
|
-
});
|
|
330
|
-
test("should not error when no handleBackBoundary callback", async () => {
|
|
331
|
-
const testRouter = new Router({
|
|
332
|
-
mode: RouterMode.memory,
|
|
333
|
-
base: new URL("http://localhost:3000/"),
|
|
334
|
-
routes: [{ path: "/", component: "Home" }]
|
|
335
|
-
});
|
|
336
|
-
await testRouter.replace("/");
|
|
337
|
-
const result = await testRouter.back();
|
|
338
|
-
expect(result).toBe(null);
|
|
339
|
-
testRouter.destroy();
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
describe("\u{1F504} Navigation Result Handling", () => {
|
|
343
|
-
test("should correctly handle successful navigation result", async () => {
|
|
344
|
-
await router.push("/about");
|
|
345
|
-
const route = await router.back();
|
|
346
|
-
expect(route == null ? void 0 : route.path).toBe("/");
|
|
347
|
-
expect(router.route.path).toBe("/");
|
|
348
|
-
});
|
|
349
|
-
test("should return null directly when Navigation returns null", async () => {
|
|
350
|
-
const testRouter = new Router({
|
|
351
|
-
mode: RouterMode.memory,
|
|
352
|
-
base: new URL("http://localhost:3000/"),
|
|
353
|
-
routes: [{ path: "/", component: "Home" }]
|
|
354
|
-
});
|
|
355
|
-
await testRouter.replace("/");
|
|
356
|
-
const result = await testRouter.back();
|
|
357
|
-
expect(result).toBe(null);
|
|
358
|
-
testRouter.destroy();
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|