1 /* eslint-disable capitalized-comments */
5 const assert
= require('assert');
6 const sinon
= require('sinon'); // eslint-disable-line node/no-unpublished-require
7 const Router
= require('../../lib/router');
8 const PathParameter
= require('../../lib/router/path-parameter')
9 const { DingusError
} = require('../../lib/errors');
11 const noExpectedException
= 'did not get expected exception';
13 describe('Router', function () {
14 const router
= new Router();
15 let _its
; // Save and restore ignoreTrailingSlash
17 beforeEach(function () {
18 _its
= router
.ignoreTrailingSlash
;
21 afterEach(function () {
23 router
.ignoreTrailingSlash
= _its
;
26 describe('_pathToRoutePath', function () {
27 it('defines a simple path', function () {
29 const expected
= ['', 'a', 'b', 'c'];
30 expected
[Router
.kPathMethods
] = {};
31 const r
= router
._pathToRoutePath(p
);
32 assert
.deepStrictEqual(r
, expected
);
34 it('defines a path with parameter', function () {
36 const expected
= ['', 'a', 'b', new PathParameter('c')];
37 expected
[Router
.kPathMethods
] = {};
38 const r
= router
._pathToRoutePath(p
);
39 assert
.deepStrictEqual(r
, expected
);
41 it('defines a path with trailing slash', function () {
42 router
.ignoreTrailingSlash
= true;
44 const expected
= ['', 'a', 'b', new PathParameter('c')];
45 expected
[Router
.kPathMethods
] = {};
46 const r
= router
._pathToRoutePath(p
);
47 assert
.deepStrictEqual(r
, expected
);
49 }); // _pathToRoutePath
51 describe('_pathCompareExact', function () {
52 let fixedPath
, checkPath
;
54 it('compares static paths which match', function () {
55 fixedPath
= router
._pathToRoutePath('/a/b/c');
56 checkPath
= router
._pathToRoutePath('/a/b/c');
57 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
58 assert
.strictEqual(r
, true);
60 it('compares static paths which do not match', function () {
61 fixedPath
= router
._pathToRoutePath('/a/b/c');
62 checkPath
= router
._pathToRoutePath('/a/b/d');
63 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
64 assert
.strictEqual(r
, false);
66 it('compares unequal static paths', function () {
67 fixedPath
= router
._pathToRoutePath('/a/b/c');
68 checkPath
= router
._pathToRoutePath('/a/b');
69 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
70 assert
.strictEqual(r
, false);
72 it('compares param paths which match', function () {
73 fixedPath
= router
._pathToRoutePath('/a/:b/c');
74 checkPath
= router
._pathToRoutePath('/a/:b/c');
75 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
76 assert
.strictEqual(r
, true);
78 it('compares param paths which do not match', function () {
79 fixedPath
= router
._pathToRoutePath('/a/:b/c');
80 checkPath
= router
._pathToRoutePath('/a/:g/c');
81 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
82 assert
.strictEqual(r
, false);
84 }); // _pathCompareExact
86 describe('_pathCompareParam', function () {
87 let fixedPath
, checkPath
;
89 it('compares static paths which match', function () {
91 const expectedParams
= {};
92 fixedPath
= router
._pathToRoutePath('/a/b/c');
93 checkPath
= router
._pathToRoutePath('/a/b/c');
94 const r
= Router
._pathCompareParam(fixedPath
, checkPath
);
95 assert
.strictEqual(r
, true);
96 assert
.deepStrictEqual(params
, expectedParams
);
98 it('compares static paths which do not match', function () {
100 const expectedParams
= {};
101 fixedPath
= router
._pathToRoutePath('/a/b/c');
102 checkPath
= router
._pathToRoutePath('/a/b/d');
103 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
104 assert
.strictEqual(r
, false);
105 assert
.deepStrictEqual(params
, expectedParams
);
107 it('compares unequal static paths', function () {
109 const expectedParams
= {};
110 fixedPath
= router
._pathToRoutePath('/a/b/c');
111 checkPath
= router
._pathToRoutePath('/a/b');
112 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
113 assert
.strictEqual(r
, false);
114 assert
.deepStrictEqual(params
, expectedParams
);
116 it('compares param paths which match', function () {
118 const expectedParams
= {
121 fixedPath
= router
._pathToRoutePath('/a/:b/c');
122 checkPath
= router
._pathToRoutePath('/a/bar/c');
123 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
124 assert
.strictEqual(r
, true);
125 assert
.deepStrictEqual(params
, expectedParams
);
127 it('compares multi param path which match', function () {
129 const expectedParams
= {
133 fixedPath
= router
._pathToRoutePath('/a/:b/:c');
134 checkPath
= router
._pathToRoutePath('/a/gaz/123');
135 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
136 assert
.strictEqual(r
, true);
137 assert
.deepStrictEqual(params
, expectedParams
);
139 }); // _pathCompareParam
141 describe('_pathFind / _pathFindExact', function () {
142 let pathsByLengthOrig
;
144 beforeEach(function () {
145 pathsByLengthOrig
= router
.pathsByLength
;
146 router
.pathsByLength
= {
147 2: [ router
._pathToRoutePath('/:id') ],
148 3: [ router
._pathToRoutePath('/a/b') ],
151 afterEach(function () {
152 router
.pathsByLength
= pathsByLengthOrig
;
155 describe('_pathFind', function () {
156 it('finds a path', function () {
157 const pathParts
= ['', '46123f1e-bdca-40ee-9f62-93ad38647aa1'];
158 const { matchedPath
, pathParams
} = router
._pathFind(pathParts
);
159 assert
.strictEqual(matchedPath
, router
.pathsByLength
[2][0]);
160 assert
.deepStrictEqual(pathParams
, { id: pathParts
[1] });
162 it('does not find a path', function () {
163 const pathParts
= ['', 'flarp', 'baz'];
164 const { matchedPath
} = router
._pathFind(pathParts
);
165 assert
.strictEqual(matchedPath
, undefined);
169 describe('_pathFindExact', function () {
170 it('finds a path', function () {
171 const pathParts
= ['', new PathParameter('id')];
172 const r
= router
._pathFindExact(pathParts
);
173 assert
.strictEqual(r
, router
.pathsByLength
[2][0]);
175 it('does not find a path', function () {
176 const pathParts
= ['', 'flarp', 'baz'];
177 const r
= router
._pathFindExact(pathParts
);
178 assert
.strictEqual(r
, undefined);
180 }); // _pathFindExact
182 }); // _pathFind / _pathFindExact
184 describe('on', function () {
185 let pathsByLengthOrig
;
186 const stubHandler
= () => {};
188 handler: stubHandler
,
192 beforeEach(function () {
193 pathsByLengthOrig
= router
.pathsByLength
;
194 router
.pathsByLength
= {
195 2: [ router
._pathToRoutePath('/:id') ],
198 afterEach(function () {
199 router
.pathsByLength
= pathsByLengthOrig
;
202 it('adds new path', function () {
203 const urlPath
= '/a/:id';
204 const expected
= router
._pathToRoutePath(urlPath
);
205 expected
[Router
.kPathMethods
]['GET'] = stubEntry
;
206 router
.on('GET', urlPath
, stubHandler
);
207 assert
.deepStrictEqual(router
.pathsByLength
[3][0], expected
);
210 it('adds new method to path', function () {
211 const urlPath
= '/a/:id';
212 const expected
= router
._pathToRoutePath(urlPath
);
213 expected
[Router
.kPathMethods
]['GET'] = stubEntry
;
214 expected
[Router
.kPathMethods
]['POST'] = stubEntry
;
215 router
.on('GET', urlPath
, stubHandler
);
217 router
.on('POST', urlPath
, stubHandler
);
218 assert
.deepStrictEqual(router
.pathsByLength
[3][0], expected
);
221 it('add some more paths', function () {
222 let urlPath
= '/a/b/c/d';
223 const expected
= router
._pathToRoutePath(urlPath
);
224 expected
[Router
.kPathMethods
]['GET'] = stubEntry
;
225 router
.on('GET', urlPath
, stubHandler
);
226 urlPath
= '/a/b/x/y';
227 router
.on('GET', urlPath
, stubHandler
);
229 assert
.strictEqual(router
.pathsByLength
[5].length
, 2);
232 it('adds multiple methods', function () {
233 const urlPath
= '/:id';
234 const expected
= router
._pathToRoutePath(urlPath
);
235 expected
[Router
.kPathMethods
]['GET'] = stubEntry
;
236 expected
[Router
.kPathMethods
]['HEAD'] = stubEntry
;
238 router
.on(['GET', 'HEAD'], urlPath
, stubHandler
);
239 assert
.deepStrictEqual(router
.pathsByLength
[2][0], expected
);
242 it('adds new wildcard path', function () {
243 const urlPath
= '/a/:id';
244 const expected
= router
._pathToRoutePath(urlPath
);
245 expected
[Router
.kPathMethods
]['*'] = stubEntry
;
246 router
.on('*', urlPath
, stubHandler
);
247 assert
.deepStrictEqual(router
.pathsByLength
[3][0], expected
);
250 it('fails to add unknown method path', function () {
251 const urlPath
= '/a/:id';
253 router
.on('FLARP', urlPath
, stubHandler
);
254 assert
.fail('expected an exception');
256 assert
.strictEqual(e
.name
, 'DingusError');
257 assert
.strictEqual(e
.message
, 'invalid method \'FLARP\'');
261 it('requires args to be array', function () {
262 const urlPath
= '/a';
264 router
.on('GET', urlPath
, stubHandler
, {});
265 assert
.fail('expected an exception');
267 assert(e
instanceof TypeError
);
272 describe('lookup', function () {
273 let pathsByLengthOrig
;
277 beforeEach(function () {
279 pathsByLengthOrig
= router
.pathsByLength
;
280 stubHandler
= sinon
.stub();
282 afterEach(function () {
283 router
.pathsByLength
= pathsByLengthOrig
;
286 it('finds handler', function () {
287 const urlPath
= '/:id';
288 const method
= 'GET';
289 router
.on(method
, urlPath
, stubHandler
);
292 const { handler
} = router
.lookup(method
, path
, ctx
);
293 assert
.strictEqual(handler
, stubHandler
);
295 it('does not find handler with trailing slash', function () {
296 router
.ignoreTrailingSlash
= false;
297 const urlPath
= '/:id';
298 const method
= 'GET';
299 router
.on(method
, urlPath
, stubHandler
);
300 const path
= '/abc/';
303 router
.lookup(method
, path
, ctx
);
304 assert
.fail(noExpectedException
);
306 assert(e
instanceof DingusError
);
307 assert
.strictEqual(e
.message
, 'NoPath');
310 it('finds handler', function () {
311 router
.ignoreTrailingSlash
= true;
312 const urlPath
= '/:id';
313 const method
= 'GET';
314 router
.on(method
, urlPath
, stubHandler
);
315 const path
= '/abc/';
317 const { handler
} = router
.lookup(method
, path
, ctx
);
318 assert
.strictEqual(handler
, stubHandler
);
320 it('finds handler without context', async
function () {
321 const urlPath
= '/:id';
322 const method
= 'GET';
323 router
.on(method
, urlPath
, stubHandler
);
326 const { handler
} = router
.lookup(method
, path
);
327 assert
.strictEqual(handler
, stubHandler
);
329 it('finds fallback handler', async
function () {
330 const urlPath
= '/abc/:id';
331 const method
= 'GET';
332 router
.on('*', urlPath
, stubHandler
);
333 const path
= '/abc/def';
335 const { handler
} = router
.lookup(method
, path
, ctx
);
336 assert
.strictEqual(handler
, stubHandler
);
338 it('calls unsupported method', async
function () {
339 const urlPath
= '/:id';
340 const method
= 'POST';
341 router
.on('GET', urlPath
, stubHandler
);
345 router
.lookup(method
, path
, ctx
);
346 assert
.fail(noExpectedException
);
348 assert(e
instanceof DingusError
);
349 assert
.strictEqual(e
.message
, 'NoMethod');
352 it('does not lookup non-existent path', async
function () {
353 const path
= '/foo/bar';
354 const method
= 'GET';
357 router
.lookup(method
, path
, ctx
);
358 assert
.fail(noExpectedException
);
360 assert(e
instanceof DingusError
);
361 assert
.strictEqual(e
.message
, 'NoPath');