@modern-js/server 1.3.2 → 1.4.2

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 (74) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/js/modern/dev-tools/babel/register.js +1 -0
  3. package/dist/js/modern/dev-tools/dev-server-plugin.js +1 -2
  4. package/dist/js/modern/dev-tools/mock/getMockData.js +24 -1
  5. package/dist/js/modern/dev-tools/mock/index.js +1 -26
  6. package/dist/js/modern/dev-tools/socket-server.js +65 -46
  7. package/dist/js/modern/dev-tools/watcher/index.js +3 -4
  8. package/dist/js/modern/dev-tools/watcher/stats-cache.js +32 -20
  9. package/dist/js/modern/libs/context/context.js +6 -0
  10. package/dist/js/modern/libs/hook-api/route.js +6 -4
  11. package/dist/js/modern/libs/render/index.js +1 -0
  12. package/dist/js/modern/libs/render/reader.js +1 -2
  13. package/dist/js/modern/libs/render/ssr.js +7 -2
  14. package/dist/js/modern/libs/route/index.js +0 -1
  15. package/dist/js/modern/libs/route/matcher.js +15 -3
  16. package/dist/js/modern/libs/route/route.js +1 -0
  17. package/dist/js/modern/server/dev-server/dev-server.js +7 -0
  18. package/dist/js/modern/server/index.js +5 -4
  19. package/dist/js/modern/server/modern-server-split.js +1 -1
  20. package/dist/js/modern/server/modern-server.js +13 -34
  21. package/dist/js/modern/utils.js +39 -0
  22. package/dist/js/node/dev-tools/babel/register.js +1 -0
  23. package/dist/js/node/dev-tools/dev-server-plugin.js +1 -2
  24. package/dist/js/node/dev-tools/mock/getMockData.js +29 -2
  25. package/dist/js/node/dev-tools/mock/index.js +5 -26
  26. package/dist/js/node/dev-tools/socket-server.js +65 -46
  27. package/dist/js/node/dev-tools/watcher/index.js +6 -2
  28. package/dist/js/node/dev-tools/watcher/stats-cache.js +33 -20
  29. package/dist/js/node/libs/context/context.js +6 -0
  30. package/dist/js/node/libs/hook-api/route.js +6 -4
  31. package/dist/js/node/libs/render/index.js +1 -0
  32. package/dist/js/node/libs/render/reader.js +2 -1
  33. package/dist/js/node/libs/render/ssr.js +8 -2
  34. package/dist/js/node/libs/route/index.js +0 -1
  35. package/dist/js/node/libs/route/matcher.js +16 -3
  36. package/dist/js/node/libs/route/route.js +1 -0
  37. package/dist/js/node/server/dev-server/dev-server.js +7 -0
  38. package/dist/js/node/server/index.js +9 -6
  39. package/dist/js/node/server/modern-server-split.js +1 -1
  40. package/dist/js/node/server/modern-server.js +12 -33
  41. package/dist/js/node/utils.js +51 -2
  42. package/dist/types/dev-tools/mock/getMockData.d.ts +2 -1
  43. package/dist/types/dev-tools/socket-server.d.ts +4 -1
  44. package/dist/types/dev-tools/watcher/index.d.ts +2 -1
  45. package/dist/types/dev-tools/watcher/stats-cache.d.ts +3 -2
  46. package/dist/types/libs/context/context.d.ts +2 -0
  47. package/dist/types/libs/hook-api/route.d.ts +3 -2
  48. package/dist/types/libs/render/reader.d.ts +13 -0
  49. package/dist/types/libs/render/ssr.d.ts +1 -0
  50. package/dist/types/libs/route/matcher.d.ts +1 -1
  51. package/dist/types/libs/route/route.d.ts +1 -0
  52. package/dist/types/server/dev-server/dev-server-split.d.ts +3 -3
  53. package/dist/types/server/modern-server-split.d.ts +3 -3
  54. package/dist/types/server/modern-server.d.ts +1 -2
  55. package/dist/types/type.d.ts +5 -3
  56. package/dist/types/utils.d.ts +5 -1
  57. package/package.json +9 -8
  58. package/tests/context.test.ts +12 -1
  59. package/tests/dev.test.ts +316 -5
  60. package/tests/fixtures/mock/exist/config/mock/index.ts +11 -0
  61. package/tests/fixtures/mock/zero/config/mock/index.ts +1 -0
  62. package/tests/fixtures/reader/index.ts +3 -0
  63. package/tests/fixtures/route-spec/dynamic.json +13 -0
  64. package/tests/fixtures/ssr/bundle.js +5 -0
  65. package/tests/fixtures/static-dir/bar.html +11 -0
  66. package/tests/fixtures/static-dir/baz/index.html +11 -0
  67. package/tests/fixtures/static-dir/foo/index.html +11 -0
  68. package/tests/fixtures/watch/a.ts +3 -0
  69. package/tests/fixtures/watch/index.ts +5 -0
  70. package/tests/fixtures/watch/stats.txt +1 -0
  71. package/tests/hook.test.ts +1 -1
  72. package/tests/render.test.ts +102 -0
  73. package/tests/route.test.ts +26 -3
  74. package/tests/utils.test.ts +35 -0
package/tests/dev.test.ts CHANGED
@@ -1,5 +1,19 @@
1
1
  import http from 'http';
2
+ import path from 'path';
3
+ import { webpack } from 'webpack';
4
+ import { fs, LAUNCH_EDITOR_ENDPOINT } from '@modern-js/utils';
2
5
  import SocketServer from '../src/dev-tools/socket-server';
6
+ import DevServerPlugin from '../src/dev-tools/dev-server-plugin';
7
+ import Watcher, { getWatchedFiles } from '../src/dev-tools/watcher';
8
+ import { StatsCache } from '../src/dev-tools/watcher/stats-cache';
9
+ import { createMockHandler } from '../src/dev-tools/mock';
10
+ import getMockData, { getMatched } from '../src/dev-tools/mock/getMockData';
11
+ import { createLaunchEditorHandler } from '../src/dev-tools/launch-editor';
12
+ import { genHttpsOptions } from '../src/dev-tools/https';
13
+
14
+ const noop = () => {
15
+ // empty
16
+ };
3
17
 
4
18
  function getRandomPort() {
5
19
  return Math.floor(Math.random() * (8000 - 1024)) + 1024;
@@ -23,11 +37,9 @@ describe('test dev tools', () => {
23
37
  hot: true,
24
38
  liveReload: true,
25
39
  });
26
- const app = http
27
- .createServer((req, res) => {
28
- res.end();
29
- })
30
- .listen(port);
40
+ const app = http.createServer((req, res) => {
41
+ res.end();
42
+ });
31
43
 
32
44
  socketServer.prepare(app);
33
45
  expect(socketServer.app).toBe(app);
@@ -39,6 +51,305 @@ describe('test dev tools', () => {
39
51
  socketServer.updateStats(mockStats);
40
52
  expect(socketServer.stats).toBe(mockStats);
41
53
 
54
+ const socket = {
55
+ state: 1,
56
+ readyState: 1,
57
+ data: '',
58
+ close() {
59
+ socket.state = 0;
60
+ },
61
+ send(data: string) {
62
+ socket.data = data;
63
+ },
64
+ on() {
65
+ // empty
66
+ },
67
+ };
68
+
69
+ socketServer.onConnect(socket);
70
+
71
+ socketServer.sockets = [socket];
72
+ socketServer.sockWrite('test');
73
+ expect(socket.data).toBe(JSON.stringify({ type: 'test' }));
74
+
75
+ socketServer.singleWrite(socket, 'single');
76
+ expect(socket.data).toBe(JSON.stringify({ type: 'single' }));
77
+
78
+ socketServer.close();
79
+ expect(socket.state).toBe(0);
42
80
  app.close();
43
81
  });
82
+
83
+ test('should dev server plugin work correctly', () => {
84
+ const compiler = webpack({});
85
+ new DevServerPlugin({
86
+ client: {
87
+ port: '8080',
88
+ overlay: false,
89
+ logging: 'error',
90
+ path: '/',
91
+ host: '127.0.0.1',
92
+ },
93
+ dev: {
94
+ writeToDisk: false,
95
+ },
96
+ watch: true,
97
+ hot: true,
98
+ liveReload: true,
99
+ }).apply(compiler);
100
+
101
+ // expect(compiler.options.entry)
102
+ const entryPluginHook = compiler.hooks.compilation.taps.filter(
103
+ tap => tap.name === 'EntryPlugin',
104
+ );
105
+ const hotPluginHook = compiler.hooks.compilation.taps.filter(
106
+ tap => tap.name === 'HotModuleReplacementPlugin',
107
+ );
108
+ expect(entryPluginHook.length).toBe(3);
109
+ expect(hotPluginHook.length).toBe(1);
110
+ });
111
+
112
+ describe('test watcher', () => {
113
+ let watcher: any;
114
+ const baseDir = path.join(__dirname, 'fixtures');
115
+ const watchDir = path.join(baseDir, 'watch/**');
116
+ const filepath = path.join(baseDir, 'watch', 'index.ts');
117
+ const filepatha = path.join(baseDir, 'watch', 'a.ts');
118
+ const txt = path.join(baseDir, 'watch', 'stats.txt');
119
+
120
+ afterEach(() => {
121
+ if (watcher) {
122
+ watcher.close();
123
+ }
124
+ fs.writeFileSync(txt, '1');
125
+ });
126
+
127
+ it('should create watcher instance correctly', resolve => {
128
+ watcher = new Watcher();
129
+ expect(watcher.dependencyTree).toBeNull();
130
+ watcher.createDepTree();
131
+ expect(watcher.dependencyTree).not.toBeNull();
132
+
133
+ expect(watcher.watcher).toBeUndefined();
134
+ watcher.listen([watchDir], {}, () => {
135
+ // empty
136
+ });
137
+
138
+ expect(watcher.watcher).toBeDefined();
139
+ require(filepath);
140
+ expect(watcher.dependencyTree.getNode(filepath)).toBeUndefined();
141
+ watcher.updateDepTree();
142
+ expect(watcher.dependencyTree.getNode(filepath)).toBeDefined();
143
+ watcher.cleanDepCache(filepath);
144
+ expect(watcher.dependencyTree.getNode(filepath)).toBeDefined();
145
+
146
+ jest.resetModules();
147
+ watcher.updateDepTree();
148
+ expect(watcher.dependencyTree.getNode(filepath)).toBeUndefined();
149
+
150
+ setTimeout(() => {
151
+ const fl = getWatchedFiles(watcher.watcher);
152
+ expect(fl.includes(filepatha)).toBeTruthy();
153
+ expect(fl.includes(filepath)).toBeTruthy();
154
+ expect(fl.includes(txt)).toBeTruthy();
155
+ resolve();
156
+ }, 1000);
157
+ });
158
+
159
+ it('should stats cache instance work correctly', () => {
160
+ const statsCache = new StatsCache();
161
+
162
+ // should not exist false before add
163
+ expect(statsCache.has(txt)).toBeFalsy();
164
+
165
+ // should exist true after add
166
+ statsCache.add([txt]);
167
+ expect(statsCache.has(txt)).toBeTruthy();
168
+
169
+ // should diff correctly
170
+ fs.writeFileSync(txt, 'foo');
171
+ expect(statsCache.isDiff(txt)).toBeTruthy();
172
+
173
+ // should not diff if not refresh
174
+ fs.writeFileSync(txt, '1');
175
+ expect(statsCache.isDiff(txt)).toBeFalsy();
176
+
177
+ // should diff after refresh
178
+ fs.writeFileSync(txt, 'foo');
179
+ statsCache.refresh(txt);
180
+ fs.writeFileSync(txt, '1');
181
+ expect(statsCache.isDiff(txt)).toBeTruthy();
182
+
183
+ // should diff when content change
184
+ statsCache.refresh(txt);
185
+ fs.writeFileSync(txt, '2');
186
+ expect(statsCache.isDiff(txt)).toBeTruthy();
187
+
188
+ // should not exist after del
189
+ statsCache.del(txt);
190
+ expect(statsCache.has(txt)).toBeFalsy();
191
+ });
192
+ });
193
+
194
+ describe('should mock middleware work correctly', () => {
195
+ const pwd = path.join(__dirname, './fixtures/mock');
196
+
197
+ it('should return null if no config mock dir', () => {
198
+ expect(createMockHandler({ pwd: path.join(pwd, 'empty') })).toBeNull();
199
+ });
200
+
201
+ it('should return null if no api dir', () => {
202
+ expect(createMockHandler({ pwd: path.join(pwd, 'zero') })).toBeNull();
203
+ });
204
+
205
+ it('should return middleware if mock api exist', async () => {
206
+ const middleware = createMockHandler({ pwd: path.join(pwd, 'exist') });
207
+
208
+ expect(middleware).not.toBeNull();
209
+
210
+ let response: any;
211
+ const context: any = {
212
+ path: '/api/getInfo',
213
+ method: 'get',
214
+ res: {
215
+ setHeader: noop,
216
+ end: (data: any) => {
217
+ response = JSON.parse(data);
218
+ },
219
+ },
220
+ };
221
+ await middleware?.(context, noop);
222
+ expect(response).toEqual({
223
+ data: [1, 2, 3, 4],
224
+ });
225
+ });
226
+
227
+ it('should get api list correctly', () => {
228
+ const apiList = getMockData(path.join(pwd, 'exist/config/mock/index.ts'));
229
+ expect(apiList.length).toBe(3);
230
+
231
+ const pathList = apiList.map(api => api.path);
232
+ expect(pathList).toEqual([
233
+ '/api/getInfo',
234
+ '/api/getExample',
235
+ '/api/addInfo',
236
+ ]);
237
+
238
+ let response: any;
239
+ const context: any = {
240
+ res: {
241
+ setHeader: noop,
242
+ end: (data: any) => {
243
+ response = JSON.parse(data);
244
+ },
245
+ },
246
+ };
247
+
248
+ apiList[0].handler(context, noop as any);
249
+ expect(response).toEqual({
250
+ data: [1, 2, 3, 4],
251
+ });
252
+ apiList[1].handler(context, noop as any);
253
+ expect(response).toEqual({ id: 1 });
254
+ });
255
+
256
+ it('should match api correctly', () => {
257
+ const apiList = [
258
+ {
259
+ method: 'get',
260
+ path: '/api/getInfo',
261
+ handler: noop,
262
+ },
263
+ {
264
+ method: 'get',
265
+ path: '/api/getExample',
266
+ handler: noop,
267
+ },
268
+ {
269
+ method: 'get',
270
+ path: '/api/addInfo',
271
+ handler: noop,
272
+ },
273
+ ];
274
+ const matched = getMatched(
275
+ { path: '/api/getInfo', method: 'get' } as any,
276
+ apiList,
277
+ );
278
+ expect(matched).toBe(apiList[0]);
279
+
280
+ const missMethod = getMatched(
281
+ { path: '/api/getModern', method: 'post' } as any,
282
+ apiList,
283
+ );
284
+ expect(missMethod).toBeUndefined();
285
+ });
286
+ });
287
+
288
+ describe('should createLaunchEditorHandler work correctly', () => {
289
+ const middleware = createLaunchEditorHandler();
290
+
291
+ it('should return 200 if filename exist', () => {
292
+ let response: any;
293
+ const context: any = {
294
+ url: LAUNCH_EDITOR_ENDPOINT,
295
+ query: {
296
+ filename: 'test.ts',
297
+ },
298
+ res: {
299
+ end: (data: any) => {
300
+ response = data;
301
+ },
302
+ },
303
+ };
304
+ middleware(context, noop);
305
+ expect(context.status).toBe(200);
306
+ expect(response).toBeUndefined();
307
+ });
308
+
309
+ it('should return 500 if filename not exist', () => {
310
+ let response: any;
311
+ const context: any = {
312
+ url: LAUNCH_EDITOR_ENDPOINT,
313
+ query: {
314
+ filename: '',
315
+ },
316
+ res: {
317
+ end: (data: any) => {
318
+ response = data;
319
+ },
320
+ },
321
+ };
322
+ middleware(context, noop);
323
+ expect(context.status).toBe(500);
324
+ expect(typeof response === 'string').toBeTruthy();
325
+ });
326
+
327
+ it('should invoke next if not launch editor url', () => {
328
+ let response: any;
329
+ const context: any = {
330
+ url: '',
331
+ res: {
332
+ end: (data: any) => {
333
+ response = data;
334
+ },
335
+ },
336
+ };
337
+ middleware(context, noop);
338
+ expect(context.status).toBeUndefined();
339
+ expect(response).toBeUndefined();
340
+ });
341
+ });
342
+
343
+ test('should get http cert correctly', async () => {
344
+ // const options = await genHttpsOptions(true);
345
+ // expect(options.key).toBeDefined();
346
+ // expect(options.cert).toBeDefined();
347
+
348
+ const useOpt = await genHttpsOptions({
349
+ key: 'foo',
350
+ cert: 'baz',
351
+ });
352
+ expect(useOpt.key).toBe('foo');
353
+ expect(useOpt.cert).toBe('baz');
354
+ });
44
355
  });
@@ -0,0 +1,11 @@
1
+ export default {
2
+ 'GET /api/getInfo': { data: [1, 2, 3, 4] },
3
+
4
+ '/api/getExample': { id: 1 },
5
+
6
+ 'GET /api/addInfo': (req: any, res: any) => {
7
+ setTimeout(() => {
8
+ res.end('delay 2000ms');
9
+ }, 2000);
10
+ },
11
+ };
@@ -0,0 +1 @@
1
+ export default {};
@@ -0,0 +1,3 @@
1
+ export default {
2
+ name: 'modern',
3
+ };
@@ -0,0 +1,13 @@
1
+ {
2
+ "routes": [
3
+ {
4
+ "urlPath": "/entry/:id",
5
+ "entryName": "entry",
6
+ "entryPath": "html/entry/index.html",
7
+ "isSPA": true,
8
+ "isSSR": true,
9
+ "enableModernMode": false,
10
+ "bundle": "bundles/entry.js"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,5 @@
1
+ const { SERVER_RENDER_FUNCTION_NAME } = require('@modern-js/utils');
2
+
3
+ module.exports = {
4
+ [SERVER_RENDER_FUNCTION_NAME]: () => '<div>Modern.js</div>',
5
+ };
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>bar</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>baz</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>foo</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,3 @@
1
+ export default {
2
+ name: 'a',
3
+ };
@@ -0,0 +1,5 @@
1
+ import a from './a';
2
+
3
+ export default {
4
+ a,
5
+ };
@@ -0,0 +1 @@
1
+ 1
@@ -10,7 +10,7 @@ describe('test hook api', () => {
10
10
  manager.reset(spec.routes);
11
11
  const matcher = manager.match('/home');
12
12
 
13
- const routeAPI = createRouteAPI(matcher!, manager);
13
+ const routeAPI = createRouteAPI(matcher!, manager, '');
14
14
  expect(routeAPI.cur().entryName).toBe('home');
15
15
  expect(routeAPI.get('entry')?.entryPath).toBe('html/entry/index.html');
16
16
 
@@ -0,0 +1,102 @@
1
+ import path from 'path';
2
+ import { render } from '../src/libs/render/ssr';
3
+ import { handleDirectory } from '../src/libs/render/static';
4
+ import { LruReader } from '../src/libs/render/reader';
5
+
6
+ describe('test render function', () => {
7
+ test('should return content correctly ', async () => {
8
+ const renderResult = await render(
9
+ {
10
+ params: {},
11
+ pathname: '/foo',
12
+ host: 'localhost:8080',
13
+ query: {},
14
+ url: 'localhost:8080/foo',
15
+ cookieMap: {},
16
+ headers: {},
17
+ } as any,
18
+ {
19
+ urlPath: '/foo',
20
+ bundle: 'bundle.js',
21
+ distDir: path.join(__dirname, 'fixtures', 'ssr'),
22
+ template: 'tpl.html',
23
+ entryName: 'foo',
24
+ staticGenerate: false,
25
+ } as any,
26
+ {
27
+ extendSSRContext: () => {
28
+ // empty
29
+ },
30
+ } as any,
31
+ );
32
+
33
+ expect(renderResult.content).toMatch('Modern.js');
34
+ expect(renderResult.contentType).toMatch('text/html; charset=utf-8');
35
+ });
36
+
37
+ test('should handle directory for .html correctly', async () => {
38
+ const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
39
+
40
+ const res1 = await handleDirectory(
41
+ {
42
+ path: '/modern/bar',
43
+ } as any,
44
+ entryPath,
45
+ '/modern',
46
+ );
47
+
48
+ expect(res1?.content.toString()).toMatch('bar');
49
+ });
50
+
51
+ test('should handle directory for index.html correctly', async () => {
52
+ const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
53
+
54
+ const res1 = await handleDirectory(
55
+ {
56
+ path: '/modern/foo',
57
+ } as any,
58
+ entryPath,
59
+ '/modern',
60
+ );
61
+
62
+ expect(res1?.content.toString()).toMatch('foo');
63
+ });
64
+
65
+ test('should handle directory for /index.html correctly', async () => {
66
+ const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
67
+
68
+ const res1 = await handleDirectory(
69
+ {
70
+ path: '/modern/baz/',
71
+ } as any,
72
+ entryPath,
73
+ '/modern',
74
+ );
75
+
76
+ expect(res1?.content.toString()).toMatch('baz');
77
+ });
78
+
79
+ test('should reader work correctly', async () => {
80
+ const reader = new LruReader();
81
+ const dir = path.join(__dirname, 'fixtures', 'reader');
82
+
83
+ const nullRes = await reader.read(path.join(dir, 'foo.ts'));
84
+ expect(nullRes).toBeNull();
85
+
86
+ const dirRes = await reader.read(path.join(dir, 'test-dir'));
87
+ expect(dirRes).toBeNull();
88
+
89
+ const res = await reader.read(path.join(dir, 'index.ts'));
90
+ expect(res).not.toBeNull();
91
+ expect(res?.content.toString()).toMatch('modern');
92
+
93
+ const res1 = await reader.read(path.join(dir, 'index.ts'));
94
+ expect(res1).not.toBeNull();
95
+ expect(res1?.content.toString()).toMatch('modern');
96
+
97
+ reader.update();
98
+ const res2 = await reader.read(path.join(dir, 'index.ts'));
99
+ expect(res2).not.toBeNull();
100
+ expect(res2?.content.toString()).toMatch('modern');
101
+ });
102
+ });
@@ -1,5 +1,6 @@
1
1
  import { RouteMatchManager, RouteMatcher } from '../src/libs/route';
2
2
  import spec from './fixtures/route-spec/index.json';
3
+ import dynamic from './fixtures/route-spec/dynamic.json';
3
4
 
4
5
  describe('test route', () => {
5
6
  describe('test route matcher', () => {
@@ -12,7 +13,7 @@ describe('test route', () => {
12
13
  expect(matcher.urlMatcher).toBeUndefined();
13
14
 
14
15
  const { isSSR, isApi, isSPA, urlPath, entryName, entryPath } =
15
- matcher.generate();
16
+ matcher.generate('');
16
17
 
17
18
  expect(isSSR).toBeTruthy();
18
19
  expect(isApi).toBeFalsy();
@@ -38,11 +39,11 @@ describe('test route', () => {
38
39
 
39
40
  const matchedByEntry = manager.matchEntry('home');
40
41
  expect(matchedByEntry).toBeDefined();
41
- expect(matchedByEntry?.generate().entryName).toBe('home');
42
+ expect(matchedByEntry?.generate('').entryName).toBe('home');
42
43
 
43
44
  const matchedByUrl = manager.match('/entry');
44
45
  expect(matchedByUrl).toBeDefined();
45
- expect(matchedByUrl?.generate().entryName).toBe('entry');
46
+ expect(matchedByUrl?.generate('').entryName).toBe('entry');
46
47
 
47
48
  const SSRUrlBundles = manager.getBundles();
48
49
  expect(SSRUrlBundles).toEqual(['bundles/entry.js', 'bundles/home.js']);
@@ -50,5 +51,27 @@ describe('test route', () => {
50
51
  manager.reset([]);
51
52
  expect(manager.matchers.length).toBe(0);
52
53
  });
54
+
55
+ test('should manager work correctly with dynamic spec', async () => {
56
+ const manager = new RouteMatchManager();
57
+ expect(manager.matchers.length).toBe(0);
58
+ manager.reset(dynamic.routes);
59
+ expect(manager.matchers.length).toBe(1);
60
+
61
+ const matched = manager.match('/entry/001');
62
+ expect(matched).toBeDefined();
63
+ const route = matched?.generate('/entry/001');
64
+ expect(route?.entryName).toBe('entry');
65
+ expect(route?.params).toEqual({ id: '001' });
66
+
67
+ const matchedWithTrail = manager.match('/entry/001/a');
68
+ expect(matchedWithTrail).toBeDefined();
69
+ const routeWithTrail = matchedWithTrail?.generate('/entry/001/a');
70
+ expect(routeWithTrail?.entryName).toBe('entry');
71
+ expect(routeWithTrail?.params).toEqual({ id: '001' });
72
+
73
+ const miss = manager.match('/entry');
74
+ expect(miss).toBeUndefined();
75
+ });
53
76
  });
54
77
  });
@@ -1,9 +1,11 @@
1
+ import { compile } from 'path-to-regexp';
1
2
  import {
2
3
  noop,
3
4
  mergeExtension,
4
5
  toMessage,
5
6
  createErrorDocument,
6
7
  createMiddlewareCollecter,
8
+ getStaticReg,
7
9
  } from '../src/utils';
8
10
 
9
11
  describe('test server utils', () => {
@@ -68,4 +70,37 @@ describe('test server utils', () => {
68
70
  expect(after.api).toEqual([middleware]);
69
71
  });
70
72
  });
73
+
74
+ test('should return full path', () => {
75
+ const fn = compile('/home/:id', { encode: encodeURIComponent });
76
+ expect(fn({ id: 2 })).toBe('/home/2');
77
+ });
78
+
79
+ describe('test create static reg', () => {
80
+ test('should test static path correctly', () => {
81
+ const reg = getStaticReg();
82
+ expect(reg.test('/static')).toBeTruthy();
83
+ expect(reg.test('/upload')).toBeTruthy();
84
+ });
85
+
86
+ test('should test custom static path correctly', () => {
87
+ const reg = getStaticReg({
88
+ cssPath: 'static-css',
89
+ });
90
+ expect(reg.test('/static-css')).toBeTruthy();
91
+ });
92
+
93
+ test('should test favicon path correctly', () => {
94
+ const reg = getStaticReg({
95
+ favicon: 'index.icon',
96
+ faviconByEntries: {
97
+ foo: 'foo.icon',
98
+ baz: 'baz.icon',
99
+ },
100
+ });
101
+ expect(reg.test('/index.icon')).toBeTruthy();
102
+ expect(reg.test('/foo.icon')).toBeTruthy();
103
+ expect(reg.test('/baz.icon')).toBeTruthy();
104
+ });
105
+ });
71
106
  });