@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.
- package/LICENSE +1 -1
- package/README.md +70 -0
- package/README.zh-CN.md +70 -0
- package/dist/error.d.ts +23 -0
- package/dist/error.mjs +61 -0
- package/dist/increment-id.d.ts +7 -0
- package/dist/increment-id.mjs +11 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +14 -3
- package/dist/index.test.mjs +8 -0
- package/dist/location.d.ts +15 -0
- package/dist/location.mjs +53 -0
- package/dist/location.test.d.ts +8 -0
- package/dist/location.test.mjs +370 -0
- package/dist/matcher.d.ts +3 -0
- package/dist/matcher.mjs +44 -0
- package/dist/matcher.test.mjs +1492 -0
- package/dist/micro-app.d.ts +18 -0
- package/dist/micro-app.dom.test.d.ts +1 -0
- package/dist/micro-app.dom.test.mjs +532 -0
- package/dist/micro-app.mjs +80 -0
- package/dist/navigation.d.ts +43 -0
- package/dist/navigation.mjs +143 -0
- package/dist/navigation.test.d.ts +1 -0
- package/dist/navigation.test.mjs +681 -0
- package/dist/options.d.ts +4 -0
- package/dist/options.mjs +88 -0
- package/dist/route-task.d.ts +40 -0
- package/dist/route-task.mjs +75 -0
- package/dist/route-task.test.d.ts +1 -0
- package/dist/route-task.test.mjs +673 -0
- package/dist/route-transition.d.ts +53 -0
- package/dist/route-transition.mjs +307 -0
- package/dist/route-transition.test.d.ts +1 -0
- package/dist/route-transition.test.mjs +146 -0
- package/dist/route.d.ts +72 -0
- package/dist/route.mjs +194 -0
- package/dist/route.test.d.ts +1 -0
- package/dist/route.test.mjs +1664 -0
- package/dist/router-back.test.d.ts +1 -0
- package/dist/router-back.test.mjs +361 -0
- package/dist/router-forward.test.d.ts +1 -0
- package/dist/router-forward.test.mjs +376 -0
- package/dist/router-go.test.d.ts +1 -0
- package/dist/router-go.test.mjs +73 -0
- package/dist/router-guards-cleanup.test.d.ts +1 -0
- package/dist/router-guards-cleanup.test.mjs +437 -0
- package/dist/router-link.d.ts +10 -0
- package/dist/router-link.mjs +126 -0
- package/dist/router-push.test.d.ts +1 -0
- package/dist/router-push.test.mjs +115 -0
- package/dist/router-replace.test.d.ts +1 -0
- package/dist/router-replace.test.mjs +114 -0
- package/dist/router-resolve.test.d.ts +1 -0
- package/dist/router-resolve.test.mjs +393 -0
- package/dist/router-restart-app.dom.test.d.ts +1 -0
- package/dist/router-restart-app.dom.test.mjs +616 -0
- package/dist/router-window-navigation.test.d.ts +1 -0
- package/dist/router-window-navigation.test.mjs +359 -0
- package/dist/router.d.ts +109 -102
- package/dist/router.mjs +260 -361
- package/dist/types.d.ts +246 -0
- package/dist/types.mjs +18 -0
- package/dist/util.d.ts +26 -0
- package/dist/util.mjs +53 -0
- package/dist/util.test.d.ts +1 -0
- package/dist/util.test.mjs +1020 -0
- package/package.json +10 -13
- package/src/error.ts +84 -0
- package/src/increment-id.ts +12 -0
- package/src/index.test.ts +9 -0
- package/src/index.ts +54 -3
- package/src/location.test.ts +406 -0
- package/src/location.ts +96 -0
- package/src/matcher.test.ts +1685 -0
- package/src/matcher.ts +59 -0
- package/src/micro-app.dom.test.ts +708 -0
- package/src/micro-app.ts +101 -0
- package/src/navigation.test.ts +858 -0
- package/src/navigation.ts +195 -0
- package/src/options.ts +131 -0
- package/src/route-task.test.ts +901 -0
- package/src/route-task.ts +105 -0
- package/src/route-transition.test.ts +178 -0
- package/src/route-transition.ts +425 -0
- package/src/route.test.ts +2014 -0
- package/src/route.ts +308 -0
- package/src/router-back.test.ts +487 -0
- package/src/router-forward.test.ts +506 -0
- package/src/router-go.test.ts +91 -0
- package/src/router-guards-cleanup.test.ts +595 -0
- package/src/router-link.ts +235 -0
- package/src/router-push.test.ts +140 -0
- package/src/router-replace.test.ts +139 -0
- package/src/router-resolve.test.ts +475 -0
- package/src/router-restart-app.dom.test.ts +783 -0
- package/src/router-window-navigation.test.ts +457 -0
- package/src/router.ts +289 -470
- package/src/types.ts +341 -0
- package/src/util.test.ts +1262 -0
- package/src/util.ts +116 -0
- package/dist/history/abstract.d.ts +0 -29
- package/dist/history/abstract.mjs +0 -107
- package/dist/history/base.d.ts +0 -79
- package/dist/history/base.mjs +0 -275
- package/dist/history/html.d.ts +0 -30
- package/dist/history/html.mjs +0 -183
- package/dist/history/index.d.ts +0 -7
- package/dist/history/index.mjs +0 -16
- package/dist/matcher/create-matcher.d.ts +0 -5
- package/dist/matcher/create-matcher.mjs +0 -218
- package/dist/matcher/create-matcher.spec.mjs +0 -0
- package/dist/matcher/index.d.ts +0 -1
- package/dist/matcher/index.mjs +0 -1
- package/dist/task-pipe/index.d.ts +0 -1
- package/dist/task-pipe/index.mjs +0 -1
- package/dist/task-pipe/task.d.ts +0 -30
- package/dist/task-pipe/task.mjs +0 -66
- package/dist/types/index.d.ts +0 -694
- package/dist/types/index.mjs +0 -6
- package/dist/utils/bom.d.ts +0 -5
- package/dist/utils/bom.mjs +0 -10
- package/dist/utils/encoding.d.ts +0 -48
- package/dist/utils/encoding.mjs +0 -44
- package/dist/utils/guards.d.ts +0 -9
- package/dist/utils/guards.mjs +0 -12
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.mjs +0 -27
- package/dist/utils/path.d.ts +0 -60
- package/dist/utils/path.mjs +0 -282
- package/dist/utils/path.spec.mjs +0 -27
- package/dist/utils/scroll.d.ts +0 -25
- package/dist/utils/scroll.mjs +0 -59
- package/dist/utils/utils.d.ts +0 -16
- package/dist/utils/utils.mjs +0 -11
- package/dist/utils/warn.d.ts +0 -2
- package/dist/utils/warn.mjs +0 -12
- package/src/history/abstract.ts +0 -149
- package/src/history/base.ts +0 -408
- package/src/history/html.ts +0 -228
- package/src/history/index.ts +0 -20
- package/src/matcher/create-matcher.spec.ts +0 -3
- package/src/matcher/create-matcher.ts +0 -292
- package/src/matcher/index.ts +0 -1
- package/src/task-pipe/index.ts +0 -1
- package/src/task-pipe/task.ts +0 -97
- package/src/types/index.ts +0 -858
- package/src/utils/bom.ts +0 -14
- package/src/utils/encoding.ts +0 -153
- package/src/utils/guards.ts +0 -25
- package/src/utils/index.ts +0 -27
- package/src/utils/path.spec.ts +0 -32
- package/src/utils/path.ts +0 -418
- package/src/utils/scroll.ts +0 -120
- package/src/utils/utils.ts +0 -30
- package/src/utils/warn.ts +0 -13
- /package/dist/{matcher/create-matcher.spec.d.ts → index.test.d.ts} +0 -0
- /package/dist/{utils/path.spec.d.ts → matcher.test.d.ts} +0 -0
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
RouteNavigationAbortedError,
|
|
4
|
+
RouteTaskCancelledError,
|
|
5
|
+
RouteTaskExecutionError
|
|
6
|
+
} from "./error.mjs";
|
|
7
|
+
import { parsedOptions } from "./options.mjs";
|
|
8
|
+
import { Route } from "./route.mjs";
|
|
9
|
+
import { RouteTaskController, createRouteTask } from "./route-task.mjs";
|
|
10
|
+
import { RouteType } from "./types.mjs";
|
|
11
|
+
function createRealOptions() {
|
|
12
|
+
return parsedOptions({
|
|
13
|
+
base: new URL("http://localhost/"),
|
|
14
|
+
routes: [
|
|
15
|
+
{ path: "/test", component: "TestComponent" },
|
|
16
|
+
{ path: "/about", component: "AboutComponent" },
|
|
17
|
+
{ path: "/redirected", component: "RedirectedComponent" },
|
|
18
|
+
{ path: "/admin", component: "AdminComponent" },
|
|
19
|
+
{ path: "/login", component: "LoginComponent" },
|
|
20
|
+
{ path: "/home", component: "HomeComponent" }
|
|
21
|
+
]
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function createMockRouter() {
|
|
25
|
+
const options = createRealOptions();
|
|
26
|
+
return {
|
|
27
|
+
parsedOptions: options
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
describe("createRouteTask", () => {
|
|
31
|
+
it("should return original route when task array is empty", async () => {
|
|
32
|
+
const router = createMockRouter();
|
|
33
|
+
const to = new Route({
|
|
34
|
+
options: router.parsedOptions,
|
|
35
|
+
toType: RouteType.push,
|
|
36
|
+
toInput: "/test"
|
|
37
|
+
});
|
|
38
|
+
const from = new Route({
|
|
39
|
+
options: router.parsedOptions,
|
|
40
|
+
toType: RouteType.push,
|
|
41
|
+
toInput: "/home"
|
|
42
|
+
});
|
|
43
|
+
const tasks = [];
|
|
44
|
+
const result = await createRouteTask({
|
|
45
|
+
to,
|
|
46
|
+
from,
|
|
47
|
+
tasks,
|
|
48
|
+
router
|
|
49
|
+
});
|
|
50
|
+
expect(result).toBe(to);
|
|
51
|
+
});
|
|
52
|
+
it("should execute tasks in sequence", async () => {
|
|
53
|
+
const router = createMockRouter();
|
|
54
|
+
const to = new Route({
|
|
55
|
+
options: router.parsedOptions,
|
|
56
|
+
toType: RouteType.push,
|
|
57
|
+
toInput: "/test"
|
|
58
|
+
});
|
|
59
|
+
const from = new Route({
|
|
60
|
+
options: router.parsedOptions,
|
|
61
|
+
toType: RouteType.push,
|
|
62
|
+
toInput: "/home"
|
|
63
|
+
});
|
|
64
|
+
const executionOrder = [];
|
|
65
|
+
const firstTask = async (route, fromRoute, router2) => {
|
|
66
|
+
executionOrder.push("task1");
|
|
67
|
+
return;
|
|
68
|
+
};
|
|
69
|
+
const secondTask = async (route, fromRoute, router2) => {
|
|
70
|
+
executionOrder.push("task2");
|
|
71
|
+
return async () => ({ success: true });
|
|
72
|
+
};
|
|
73
|
+
const tasks = [
|
|
74
|
+
{
|
|
75
|
+
name: "beforeEach",
|
|
76
|
+
task: firstTask
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "override",
|
|
80
|
+
task: secondTask
|
|
81
|
+
}
|
|
82
|
+
];
|
|
83
|
+
const result = await createRouteTask({
|
|
84
|
+
to,
|
|
85
|
+
from,
|
|
86
|
+
tasks,
|
|
87
|
+
router
|
|
88
|
+
});
|
|
89
|
+
expect(executionOrder).toEqual(["task1", "task2"]);
|
|
90
|
+
expect(result).toBe(to);
|
|
91
|
+
expect(to.handle).toBeTypeOf("function");
|
|
92
|
+
});
|
|
93
|
+
it("should set handle when task returns a function", async () => {
|
|
94
|
+
const router = createMockRouter();
|
|
95
|
+
const to = new Route({
|
|
96
|
+
options: router.parsedOptions,
|
|
97
|
+
toType: RouteType.push,
|
|
98
|
+
toInput: "/test"
|
|
99
|
+
});
|
|
100
|
+
const from = new Route({
|
|
101
|
+
options: router.parsedOptions,
|
|
102
|
+
toType: RouteType.push,
|
|
103
|
+
toInput: "/home"
|
|
104
|
+
});
|
|
105
|
+
const handleFunction = async (to2, from2, router2) => {
|
|
106
|
+
return { message: "Route handled successfully" };
|
|
107
|
+
};
|
|
108
|
+
const successTask = async (route, fromRoute, router2) => {
|
|
109
|
+
return handleFunction;
|
|
110
|
+
};
|
|
111
|
+
const tasks = [
|
|
112
|
+
{
|
|
113
|
+
name: "beforeEach",
|
|
114
|
+
task: successTask
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
const result = await createRouteTask({
|
|
118
|
+
to,
|
|
119
|
+
from,
|
|
120
|
+
tasks,
|
|
121
|
+
router
|
|
122
|
+
});
|
|
123
|
+
expect(result).toBe(to);
|
|
124
|
+
expect(to.handle).toBeTypeOf("function");
|
|
125
|
+
expect(to.handle).not.toBeNull();
|
|
126
|
+
});
|
|
127
|
+
it("should throw RouteNavigationAbortedError when task returns false", async () => {
|
|
128
|
+
const router = createMockRouter();
|
|
129
|
+
const to = new Route({
|
|
130
|
+
options: router.parsedOptions,
|
|
131
|
+
toType: RouteType.push,
|
|
132
|
+
toInput: "/test"
|
|
133
|
+
});
|
|
134
|
+
const from = new Route({
|
|
135
|
+
options: router.parsedOptions,
|
|
136
|
+
toType: RouteType.push,
|
|
137
|
+
toInput: "/home"
|
|
138
|
+
});
|
|
139
|
+
const blockingTask = async (route, fromRoute, router2) => {
|
|
140
|
+
const shouldProceed = false;
|
|
141
|
+
return shouldProceed ? void 0 : false;
|
|
142
|
+
};
|
|
143
|
+
const tasks = [
|
|
144
|
+
{
|
|
145
|
+
name: "beforeEach",
|
|
146
|
+
task: blockingTask
|
|
147
|
+
}
|
|
148
|
+
];
|
|
149
|
+
await expect(
|
|
150
|
+
createRouteTask({
|
|
151
|
+
to,
|
|
152
|
+
from,
|
|
153
|
+
tasks,
|
|
154
|
+
router
|
|
155
|
+
})
|
|
156
|
+
).rejects.toThrow(RouteNavigationAbortedError);
|
|
157
|
+
});
|
|
158
|
+
it("should handle redirection when task returns a route location string", async () => {
|
|
159
|
+
const router = createMockRouter();
|
|
160
|
+
const to = new Route({
|
|
161
|
+
options: router.parsedOptions,
|
|
162
|
+
toType: RouteType.push,
|
|
163
|
+
toInput: "/test"
|
|
164
|
+
});
|
|
165
|
+
const from = new Route({
|
|
166
|
+
options: router.parsedOptions,
|
|
167
|
+
toType: RouteType.push,
|
|
168
|
+
toInput: "/home"
|
|
169
|
+
});
|
|
170
|
+
const redirectTask = async (route, fromRoute, router2) => {
|
|
171
|
+
if (route.path === "/test") {
|
|
172
|
+
return "/redirected";
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
};
|
|
176
|
+
const tasks = [
|
|
177
|
+
{
|
|
178
|
+
name: "beforeEach",
|
|
179
|
+
task: redirectTask
|
|
180
|
+
}
|
|
181
|
+
];
|
|
182
|
+
const result = await createRouteTask({
|
|
183
|
+
to,
|
|
184
|
+
from,
|
|
185
|
+
tasks,
|
|
186
|
+
router
|
|
187
|
+
});
|
|
188
|
+
expect(result).toBeInstanceOf(Route);
|
|
189
|
+
expect(result.path).toBe("/redirected");
|
|
190
|
+
});
|
|
191
|
+
it("should throw RouteTaskExecutionError when task throws an error", async () => {
|
|
192
|
+
const router = createMockRouter();
|
|
193
|
+
const to = new Route({
|
|
194
|
+
options: router.parsedOptions,
|
|
195
|
+
toType: RouteType.push,
|
|
196
|
+
toInput: "/test"
|
|
197
|
+
});
|
|
198
|
+
const from = new Route({
|
|
199
|
+
options: router.parsedOptions,
|
|
200
|
+
toType: RouteType.push,
|
|
201
|
+
toInput: "/home"
|
|
202
|
+
});
|
|
203
|
+
const errorTask = async (route, fromRoute, router2) => {
|
|
204
|
+
throw new Error("Task execution failed");
|
|
205
|
+
};
|
|
206
|
+
const tasks = [
|
|
207
|
+
{
|
|
208
|
+
name: "beforeEach",
|
|
209
|
+
task: errorTask
|
|
210
|
+
}
|
|
211
|
+
];
|
|
212
|
+
await expect(
|
|
213
|
+
createRouteTask({
|
|
214
|
+
to,
|
|
215
|
+
from,
|
|
216
|
+
tasks,
|
|
217
|
+
router
|
|
218
|
+
})
|
|
219
|
+
).rejects.toThrow(RouteTaskExecutionError);
|
|
220
|
+
});
|
|
221
|
+
it("should handle non-Error exceptions and convert them to Error instances", async () => {
|
|
222
|
+
const router = createMockRouter();
|
|
223
|
+
const to = new Route({
|
|
224
|
+
options: router.parsedOptions,
|
|
225
|
+
toType: RouteType.push,
|
|
226
|
+
toInput: "/test"
|
|
227
|
+
});
|
|
228
|
+
const from = new Route({
|
|
229
|
+
options: router.parsedOptions,
|
|
230
|
+
toType: RouteType.push,
|
|
231
|
+
toInput: "/home"
|
|
232
|
+
});
|
|
233
|
+
const stringErrorTask = async (route, fromRoute, router2) => {
|
|
234
|
+
throw "String error message";
|
|
235
|
+
};
|
|
236
|
+
const numberErrorTask = async (route, fromRoute, router2) => {
|
|
237
|
+
throw 404;
|
|
238
|
+
};
|
|
239
|
+
const objectErrorTask = async (route, fromRoute, router2) => {
|
|
240
|
+
throw { code: "CUSTOM_ERROR", message: "Custom error object" };
|
|
241
|
+
};
|
|
242
|
+
const stringTasks = [
|
|
243
|
+
{ name: "stringError", task: stringErrorTask }
|
|
244
|
+
];
|
|
245
|
+
try {
|
|
246
|
+
await createRouteTask({ to, from, tasks: stringTasks, router });
|
|
247
|
+
} catch (error) {
|
|
248
|
+
expect(error).toBeInstanceOf(RouteTaskExecutionError);
|
|
249
|
+
expect(
|
|
250
|
+
error.originalError
|
|
251
|
+
).toBeInstanceOf(Error);
|
|
252
|
+
expect(
|
|
253
|
+
error.originalError.message
|
|
254
|
+
).toBe("String error message");
|
|
255
|
+
}
|
|
256
|
+
const numberTasks = [
|
|
257
|
+
{ name: "numberError", task: numberErrorTask }
|
|
258
|
+
];
|
|
259
|
+
try {
|
|
260
|
+
await createRouteTask({ to, from, tasks: numberTasks, router });
|
|
261
|
+
} catch (error) {
|
|
262
|
+
expect(error).toBeInstanceOf(RouteTaskExecutionError);
|
|
263
|
+
expect(
|
|
264
|
+
error.originalError
|
|
265
|
+
).toBeInstanceOf(Error);
|
|
266
|
+
expect(
|
|
267
|
+
error.originalError.message
|
|
268
|
+
).toBe("404");
|
|
269
|
+
}
|
|
270
|
+
const objectTasks = [
|
|
271
|
+
{ name: "objectError", task: objectErrorTask }
|
|
272
|
+
];
|
|
273
|
+
try {
|
|
274
|
+
await createRouteTask({ to, from, tasks: objectTasks, router });
|
|
275
|
+
} catch (error) {
|
|
276
|
+
expect(error).toBeInstanceOf(RouteTaskExecutionError);
|
|
277
|
+
expect(
|
|
278
|
+
error.originalError
|
|
279
|
+
).toBeInstanceOf(Error);
|
|
280
|
+
expect(
|
|
281
|
+
error.originalError.message
|
|
282
|
+
).toBe("[object Object]");
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
it("should not execute subsequent tasks once an error is thrown", async () => {
|
|
286
|
+
const router = createMockRouter();
|
|
287
|
+
const to = new Route({
|
|
288
|
+
options: router.parsedOptions,
|
|
289
|
+
toType: RouteType.push,
|
|
290
|
+
toInput: "/test"
|
|
291
|
+
});
|
|
292
|
+
const from = new Route({
|
|
293
|
+
options: router.parsedOptions,
|
|
294
|
+
toType: RouteType.push,
|
|
295
|
+
toInput: "/home"
|
|
296
|
+
});
|
|
297
|
+
const executionOrder = [];
|
|
298
|
+
const firstTask = async (route, fromRoute, router2) => {
|
|
299
|
+
executionOrder.push("task1");
|
|
300
|
+
throw new Error("Task failed");
|
|
301
|
+
};
|
|
302
|
+
const secondTask = async (route, fromRoute, router2) => {
|
|
303
|
+
executionOrder.push("task2");
|
|
304
|
+
return;
|
|
305
|
+
};
|
|
306
|
+
const tasks = [
|
|
307
|
+
{
|
|
308
|
+
name: "beforeEach",
|
|
309
|
+
task: firstTask
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: "beforeEnter",
|
|
313
|
+
task: secondTask
|
|
314
|
+
}
|
|
315
|
+
];
|
|
316
|
+
await expect(
|
|
317
|
+
createRouteTask({
|
|
318
|
+
to,
|
|
319
|
+
from,
|
|
320
|
+
tasks,
|
|
321
|
+
router
|
|
322
|
+
})
|
|
323
|
+
).rejects.toThrow(RouteTaskExecutionError);
|
|
324
|
+
expect(executionOrder).toEqual(["task1"]);
|
|
325
|
+
});
|
|
326
|
+
it("should handle null from route parameter", async () => {
|
|
327
|
+
const router = createMockRouter();
|
|
328
|
+
const to = new Route({
|
|
329
|
+
options: router.parsedOptions,
|
|
330
|
+
toType: RouteType.push,
|
|
331
|
+
toInput: "/test"
|
|
332
|
+
});
|
|
333
|
+
const checkFromRouteTask = async (route, fromRoute, router2) => {
|
|
334
|
+
expect(fromRoute).toBeNull();
|
|
335
|
+
return async () => ({ success: true });
|
|
336
|
+
};
|
|
337
|
+
const tasks = [
|
|
338
|
+
{
|
|
339
|
+
name: "beforeEach",
|
|
340
|
+
task: checkFromRouteTask
|
|
341
|
+
}
|
|
342
|
+
];
|
|
343
|
+
const result = await createRouteTask({
|
|
344
|
+
to,
|
|
345
|
+
from: null,
|
|
346
|
+
tasks,
|
|
347
|
+
router
|
|
348
|
+
});
|
|
349
|
+
expect(result).toBe(to);
|
|
350
|
+
expect(to.handle).toBeTypeOf("function");
|
|
351
|
+
});
|
|
352
|
+
it("should pass the correct to and from parameters to tasks", async () => {
|
|
353
|
+
const router = createMockRouter();
|
|
354
|
+
const to = new Route({
|
|
355
|
+
options: router.parsedOptions,
|
|
356
|
+
toType: RouteType.push,
|
|
357
|
+
toInput: "/test"
|
|
358
|
+
});
|
|
359
|
+
const from = new Route({
|
|
360
|
+
options: router.parsedOptions,
|
|
361
|
+
toType: RouteType.push,
|
|
362
|
+
toInput: "/home"
|
|
363
|
+
});
|
|
364
|
+
const firstTask = async (route, fromRoute, router2) => {
|
|
365
|
+
expect(route).toBe(to);
|
|
366
|
+
expect(fromRoute).toBe(from);
|
|
367
|
+
return;
|
|
368
|
+
};
|
|
369
|
+
const secondTask = async (route, fromRoute, router2) => {
|
|
370
|
+
expect(route).toBe(to);
|
|
371
|
+
expect(fromRoute).toBe(from);
|
|
372
|
+
return false;
|
|
373
|
+
};
|
|
374
|
+
const thirdTask = async (route, fromRoute, router2) => {
|
|
375
|
+
throw new Error("This should not be executed");
|
|
376
|
+
};
|
|
377
|
+
const tasks = [
|
|
378
|
+
{
|
|
379
|
+
name: "beforeEach",
|
|
380
|
+
task: firstTask
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: "beforeEnter",
|
|
384
|
+
task: secondTask
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
name: "confirm",
|
|
388
|
+
task: thirdTask
|
|
389
|
+
}
|
|
390
|
+
];
|
|
391
|
+
await expect(
|
|
392
|
+
createRouteTask({
|
|
393
|
+
to,
|
|
394
|
+
from,
|
|
395
|
+
tasks,
|
|
396
|
+
router
|
|
397
|
+
})
|
|
398
|
+
).rejects.toThrow(RouteNavigationAbortedError);
|
|
399
|
+
});
|
|
400
|
+
it("should execute all tasks until one returns a result", async () => {
|
|
401
|
+
const router = createMockRouter();
|
|
402
|
+
const to = new Route({
|
|
403
|
+
options: router.parsedOptions,
|
|
404
|
+
toType: RouteType.push,
|
|
405
|
+
toInput: "/test"
|
|
406
|
+
});
|
|
407
|
+
const from = new Route({
|
|
408
|
+
options: router.parsedOptions,
|
|
409
|
+
toType: RouteType.push,
|
|
410
|
+
toInput: "/home"
|
|
411
|
+
});
|
|
412
|
+
const executionOrder = [];
|
|
413
|
+
const firstTask = async (route, fromRoute, router2) => {
|
|
414
|
+
executionOrder.push("task1");
|
|
415
|
+
return;
|
|
416
|
+
};
|
|
417
|
+
const handleFunction = async (to2, from2, router2) => {
|
|
418
|
+
return { message: "Route handled" };
|
|
419
|
+
};
|
|
420
|
+
const secondTask = async (route, fromRoute, router2) => {
|
|
421
|
+
executionOrder.push("task2");
|
|
422
|
+
return handleFunction;
|
|
423
|
+
};
|
|
424
|
+
const thirdTask = async (route, fromRoute, router2) => {
|
|
425
|
+
executionOrder.push("task3");
|
|
426
|
+
return;
|
|
427
|
+
};
|
|
428
|
+
const tasks = [
|
|
429
|
+
{
|
|
430
|
+
name: "beforeEach",
|
|
431
|
+
task: firstTask
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
name: "beforeEnter",
|
|
435
|
+
task: secondTask
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
name: "confirm",
|
|
439
|
+
task: thirdTask
|
|
440
|
+
}
|
|
441
|
+
];
|
|
442
|
+
const result = await createRouteTask({
|
|
443
|
+
to,
|
|
444
|
+
from,
|
|
445
|
+
tasks,
|
|
446
|
+
router
|
|
447
|
+
});
|
|
448
|
+
expect(result).toBe(to);
|
|
449
|
+
expect(to.handle).toBeTypeOf("function");
|
|
450
|
+
expect(to.handle).not.toBe(null);
|
|
451
|
+
expect(executionOrder).toEqual(["task1", "task2"]);
|
|
452
|
+
});
|
|
453
|
+
describe("Task cancellation with RouteTaskController", () => {
|
|
454
|
+
it("should cancel task when abort is called before task execution", async () => {
|
|
455
|
+
const router = createMockRouter();
|
|
456
|
+
const to = new Route({
|
|
457
|
+
options: router.parsedOptions,
|
|
458
|
+
toType: RouteType.push,
|
|
459
|
+
toInput: "/test"
|
|
460
|
+
});
|
|
461
|
+
const from = new Route({
|
|
462
|
+
options: router.parsedOptions,
|
|
463
|
+
toType: RouteType.push,
|
|
464
|
+
toInput: "/home"
|
|
465
|
+
});
|
|
466
|
+
const controller = new RouteTaskController();
|
|
467
|
+
const firstTask = async (route, fromRoute, router2) => {
|
|
468
|
+
throw new Error("This should not be executed");
|
|
469
|
+
};
|
|
470
|
+
const secondTask = async (route, fromRoute, router2) => {
|
|
471
|
+
throw new Error("This should also not be executed");
|
|
472
|
+
};
|
|
473
|
+
const tasks = [
|
|
474
|
+
{
|
|
475
|
+
name: "beforeEach",
|
|
476
|
+
task: firstTask
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
name: "beforeEnter",
|
|
480
|
+
task: secondTask
|
|
481
|
+
}
|
|
482
|
+
];
|
|
483
|
+
controller.abort();
|
|
484
|
+
await expect(
|
|
485
|
+
createRouteTask({
|
|
486
|
+
to,
|
|
487
|
+
from,
|
|
488
|
+
tasks,
|
|
489
|
+
controller,
|
|
490
|
+
router
|
|
491
|
+
})
|
|
492
|
+
).rejects.toThrow(RouteTaskCancelledError);
|
|
493
|
+
});
|
|
494
|
+
it("should cancel task when abort is called after first task execution", async () => {
|
|
495
|
+
const router = createMockRouter();
|
|
496
|
+
const to = new Route({
|
|
497
|
+
options: router.parsedOptions,
|
|
498
|
+
toType: RouteType.push,
|
|
499
|
+
toInput: "/test"
|
|
500
|
+
});
|
|
501
|
+
const from = new Route({
|
|
502
|
+
options: router.parsedOptions,
|
|
503
|
+
toType: RouteType.push,
|
|
504
|
+
toInput: "/home"
|
|
505
|
+
});
|
|
506
|
+
const controller = new RouteTaskController();
|
|
507
|
+
const firstTask = async (route, fromRoute, router2) => {
|
|
508
|
+
controller.abort();
|
|
509
|
+
return;
|
|
510
|
+
};
|
|
511
|
+
const secondTask = async (route, fromRoute, router2) => {
|
|
512
|
+
throw new Error("This should not be executed");
|
|
513
|
+
};
|
|
514
|
+
const tasks = [
|
|
515
|
+
{
|
|
516
|
+
name: "beforeEach",
|
|
517
|
+
task: firstTask
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
name: "beforeEnter",
|
|
521
|
+
task: secondTask
|
|
522
|
+
}
|
|
523
|
+
];
|
|
524
|
+
await expect(
|
|
525
|
+
createRouteTask({
|
|
526
|
+
to,
|
|
527
|
+
from,
|
|
528
|
+
tasks,
|
|
529
|
+
controller,
|
|
530
|
+
router
|
|
531
|
+
})
|
|
532
|
+
).rejects.toThrow(RouteTaskCancelledError);
|
|
533
|
+
});
|
|
534
|
+
it("should not throw error on shouldCancel if controller is provided", async () => {
|
|
535
|
+
const router = createMockRouter();
|
|
536
|
+
const to = new Route({
|
|
537
|
+
options: router.parsedOptions,
|
|
538
|
+
toType: RouteType.push,
|
|
539
|
+
toInput: "/test"
|
|
540
|
+
});
|
|
541
|
+
const from = new Route({
|
|
542
|
+
options: router.parsedOptions,
|
|
543
|
+
toType: RouteType.push,
|
|
544
|
+
toInput: "/home"
|
|
545
|
+
});
|
|
546
|
+
const handleTask = async (route, fromRoute, router2) => {
|
|
547
|
+
return async () => ({ success: true });
|
|
548
|
+
};
|
|
549
|
+
const tasks = [
|
|
550
|
+
{
|
|
551
|
+
name: "beforeEach",
|
|
552
|
+
task: handleTask
|
|
553
|
+
}
|
|
554
|
+
];
|
|
555
|
+
const result = await createRouteTask({
|
|
556
|
+
to,
|
|
557
|
+
from,
|
|
558
|
+
tasks,
|
|
559
|
+
router
|
|
560
|
+
});
|
|
561
|
+
expect(result).toBe(to);
|
|
562
|
+
expect(result == null ? void 0 : result.handle).toBeTypeOf("function");
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
describe("Real scenario test", () => {
|
|
566
|
+
it("should correctly handle RouteTaskOptions type verification", async () => {
|
|
567
|
+
const router = createMockRouter();
|
|
568
|
+
const to = new Route({
|
|
569
|
+
options: router.parsedOptions,
|
|
570
|
+
toType: RouteType.push,
|
|
571
|
+
toInput: "/test"
|
|
572
|
+
});
|
|
573
|
+
const from = new Route({
|
|
574
|
+
options: router.parsedOptions,
|
|
575
|
+
toType: RouteType.push,
|
|
576
|
+
toInput: "/home"
|
|
577
|
+
});
|
|
578
|
+
const tasks = [];
|
|
579
|
+
const routeTaskOptions = {
|
|
580
|
+
to,
|
|
581
|
+
from,
|
|
582
|
+
tasks,
|
|
583
|
+
router
|
|
584
|
+
};
|
|
585
|
+
const result = await createRouteTask(routeTaskOptions);
|
|
586
|
+
expect(result).toBe(to);
|
|
587
|
+
});
|
|
588
|
+
it("should correctly handle RouteTaskOptions with controller", async () => {
|
|
589
|
+
const router = createMockRouter();
|
|
590
|
+
const to = new Route({
|
|
591
|
+
options: router.parsedOptions,
|
|
592
|
+
toType: RouteType.push,
|
|
593
|
+
toInput: "/test"
|
|
594
|
+
});
|
|
595
|
+
const from = new Route({
|
|
596
|
+
options: router.parsedOptions,
|
|
597
|
+
toType: RouteType.push,
|
|
598
|
+
toInput: "/home"
|
|
599
|
+
});
|
|
600
|
+
const tasks = [];
|
|
601
|
+
const controller = new RouteTaskController();
|
|
602
|
+
const routeTaskOptions = {
|
|
603
|
+
to,
|
|
604
|
+
from,
|
|
605
|
+
tasks,
|
|
606
|
+
router,
|
|
607
|
+
controller
|
|
608
|
+
};
|
|
609
|
+
const result = await createRouteTask(routeTaskOptions);
|
|
610
|
+
expect(result).toBe(to);
|
|
611
|
+
});
|
|
612
|
+
it("should correctly create real task function interface", async () => {
|
|
613
|
+
const router = createMockRouter();
|
|
614
|
+
const to = new Route({
|
|
615
|
+
options: router.parsedOptions,
|
|
616
|
+
toType: RouteType.push,
|
|
617
|
+
toInput: "/test"
|
|
618
|
+
});
|
|
619
|
+
const from = new Route({
|
|
620
|
+
options: router.parsedOptions,
|
|
621
|
+
toType: RouteType.push,
|
|
622
|
+
toInput: "/home"
|
|
623
|
+
});
|
|
624
|
+
const realTaskFunction = async (route, fromRoute, router2) => {
|
|
625
|
+
expect(route).toBeInstanceOf(Route);
|
|
626
|
+
expect(fromRoute).toBeInstanceOf(Route);
|
|
627
|
+
expect(router2).toBeDefined();
|
|
628
|
+
return async () => ({ success: true });
|
|
629
|
+
};
|
|
630
|
+
const tasks = [
|
|
631
|
+
{
|
|
632
|
+
name: "beforeEach",
|
|
633
|
+
task: realTaskFunction
|
|
634
|
+
}
|
|
635
|
+
];
|
|
636
|
+
const result = await createRouteTask({
|
|
637
|
+
to,
|
|
638
|
+
from,
|
|
639
|
+
tasks,
|
|
640
|
+
router
|
|
641
|
+
});
|
|
642
|
+
expect(result).toBe(to);
|
|
643
|
+
expect(to.handle).toBeTypeOf("function");
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
});
|
|
647
|
+
describe("RouteTaskController", () => {
|
|
648
|
+
it("should handle task cancellation", async () => {
|
|
649
|
+
const router = createMockRouter();
|
|
650
|
+
const to = new Route({
|
|
651
|
+
options: router.parsedOptions,
|
|
652
|
+
toType: RouteType.push,
|
|
653
|
+
toInput: "/test"
|
|
654
|
+
});
|
|
655
|
+
const controller = new RouteTaskController();
|
|
656
|
+
controller.abort();
|
|
657
|
+
const tasks = [
|
|
658
|
+
{
|
|
659
|
+
name: "beforeEach",
|
|
660
|
+
task: async () => async () => ({ success: true })
|
|
661
|
+
}
|
|
662
|
+
];
|
|
663
|
+
await expect(
|
|
664
|
+
createRouteTask({
|
|
665
|
+
to,
|
|
666
|
+
from: null,
|
|
667
|
+
tasks,
|
|
668
|
+
router,
|
|
669
|
+
controller
|
|
670
|
+
})
|
|
671
|
+
).rejects.toThrow(RouteTaskCancelledError);
|
|
672
|
+
});
|
|
673
|
+
});
|