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 { DingusError
} = require('../../lib/errors');
10 const noExpectedException
= 'did not get expected exception';
12 describe('Router', function () {
13 const router
= new Router();
14 let _its
; // Save and restore ignoreTrailingSlash
16 beforeEach(function () {
17 _its
= router
.ignoreTrailingSlash
;
20 afterEach(function () {
22 router
.ignoreTrailingSlash
= _its
;
25 describe('_pathDefinitionToPathMatch', function () {
26 it('defines a simple path', function () {
28 const expected
= ['', 'a', 'b', 'c'];
29 expected
[router
.METHODS
] = {};
30 const r
= router
._pathDefinitionToPathMatch(p
);
31 assert
.deepStrictEqual(r
, expected
);
33 it('defines a path with parameter', function () {
35 const expected
= ['', 'a', 'b', { [router
.PARAM
]: 'c' }];
36 expected
[router
.METHODS
] = {};
37 const r
= router
._pathDefinitionToPathMatch(p
);
38 assert
.deepStrictEqual(r
, expected
);
40 it('defines a path with trailing slash', function () {
41 router
.ignoreTrailingSlash
= true;
43 const expected
= ['', 'a', 'b', { [router
.PARAM
]: 'c' }];
44 expected
[router
.METHODS
] = {};
45 const r
= router
._pathDefinitionToPathMatch(p
);
46 assert
.deepStrictEqual(r
, expected
);
48 }); // _pathDefinitionToPathMatch
50 describe('_pathCompareExact', function () {
51 let fixedPath
, checkPath
;
53 it('compares static paths which match', function () {
54 fixedPath
= router
._pathDefinitionToPathMatch('/a/b/c');
55 checkPath
= router
._pathDefinitionToPathMatch('/a/b/c');
56 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
57 assert
.strictEqual(r
, true);
59 it('compares static paths which do not match', function () {
60 fixedPath
= router
._pathDefinitionToPathMatch('/a/b/c');
61 checkPath
= router
._pathDefinitionToPathMatch('/a/b/d');
62 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
63 assert
.strictEqual(r
, false);
65 it('compares unequal static paths', function () {
66 fixedPath
= router
._pathDefinitionToPathMatch('/a/b/c');
67 checkPath
= router
._pathDefinitionToPathMatch('/a/b');
68 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
69 assert
.strictEqual(r
, false);
71 it('compares param paths which match', function () {
72 fixedPath
= router
._pathDefinitionToPathMatch('/a/:b/c');
73 checkPath
= router
._pathDefinitionToPathMatch('/a/:b/c');
74 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
75 assert
.strictEqual(r
, true);
77 it('compares param paths which do not match', function () {
78 fixedPath
= router
._pathDefinitionToPathMatch('/a/:b/c');
79 checkPath
= router
._pathDefinitionToPathMatch('/a/:g/c');
80 const r
= Router
._pathCompareExact(fixedPath
, checkPath
);
81 assert
.strictEqual(r
, false);
83 }); // _pathCompareExact
85 describe('_pathCompareParam', function () {
86 let fixedPath
, checkPath
;
88 it('compares static paths which match', function () {
90 const expectedParams
= {};
91 fixedPath
= router
._pathDefinitionToPathMatch('/a/b/c');
92 checkPath
= router
._pathDefinitionToPathMatch('/a/b/c');
93 const r
= Router
._pathCompareParam(fixedPath
, checkPath
);
94 assert
.strictEqual(r
, true);
95 assert
.deepStrictEqual(params
, expectedParams
);
97 it('compares static paths which do not match', function () {
99 const expectedParams
= {};
100 fixedPath
= router
._pathDefinitionToPathMatch('/a/b/c');
101 checkPath
= router
._pathDefinitionToPathMatch('/a/b/d');
102 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
103 assert
.strictEqual(r
, false);
104 assert
.deepStrictEqual(params
, expectedParams
);
106 it('compares unequal static paths', function () {
108 const expectedParams
= {};
109 fixedPath
= router
._pathDefinitionToPathMatch('/a/b/c');
110 checkPath
= router
._pathDefinitionToPathMatch('/a/b');
111 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
112 assert
.strictEqual(r
, false);
113 assert
.deepStrictEqual(params
, expectedParams
);
115 it('compares param paths which match', function () {
117 const expectedParams
= {
120 fixedPath
= router
._pathDefinitionToPathMatch('/a/:b/c');
121 checkPath
= router
._pathDefinitionToPathMatch('/a/bar/c');
122 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
123 assert
.strictEqual(r
, true);
124 assert
.deepStrictEqual(params
, expectedParams
);
126 it('compares multi param path which match', function () {
128 const expectedParams
= {
132 fixedPath
= router
._pathDefinitionToPathMatch('/a/:b/:c');
133 checkPath
= router
._pathDefinitionToPathMatch('/a/gaz/123');
134 const r
= Router
._pathCompareParam(fixedPath
, checkPath
, params
);
135 assert
.strictEqual(r
, true);
136 assert
.deepStrictEqual(params
, expectedParams
);
138 }); // _pathCompareParam
140 describe('_pathFind / _pathFindExact', function () {
141 let pathsByLengthOrig
;
143 beforeEach(function () {
144 pathsByLengthOrig
= router
.pathsByLength
;
145 router
.pathsByLength
= {
146 2: [ router
._pathDefinitionToPathMatch('/:id') ],
147 3: [ router
._pathDefinitionToPathMatch('/a/b') ],
150 afterEach(function () {
151 router
.pathsByLength
= pathsByLengthOrig
;
154 describe('_pathFind', function () {
155 it('finds a path', function () {
156 const pathParts
= ['', '46123f1e-bdca-40ee-9f62-93ad38647aa1'];
157 const { matchedPath
, pathParams
} = router
._pathFind(pathParts
);
158 assert
.strictEqual(matchedPath
, router
.pathsByLength
[2][0]);
159 assert
.deepStrictEqual(pathParams
, { id: pathParts
[1] });
161 it('does not find a path', function () {
162 const pathParts
= ['', 'flarp', 'baz'];
163 const { matchedPath
} = router
._pathFind(pathParts
);
164 assert
.strictEqual(matchedPath
, undefined);
168 describe('_pathFindExact', function () {
169 it('finds a path', function () {
170 const pathParts
= ['', { [router
.PARAM
]: 'id' }];
171 const r
= router
._pathFindExact(pathParts
);
172 assert
.strictEqual(r
, router
.pathsByLength
[2][0]);
174 it('does not find a path', function () {
175 const pathParts
= ['', 'flarp', 'baz'];
176 const r
= router
._pathFindExact(pathParts
);
177 assert
.strictEqual(r
, undefined);
179 }); // _pathFindExact
181 }); // _pathFind / _pathFindExact
183 describe('on', function () {
184 let pathsByLengthOrig
;
185 const stubHandler
= () => {};
187 handler: stubHandler
,
191 beforeEach(function () {
192 pathsByLengthOrig
= router
.pathsByLength
;
193 router
.pathsByLength
= {
194 2: [ router
._pathDefinitionToPathMatch('/:id') ],
197 afterEach(function () {
198 router
.pathsByLength
= pathsByLengthOrig
;
201 it('adds new path', function () {
202 const urlPath
= '/a/:id';
203 const expected
= router
._pathDefinitionToPathMatch(urlPath
);
204 expected
[router
.METHODS
]['GET'] = stubEntry
;
205 router
.on('GET', urlPath
, stubHandler
);
206 assert
.deepStrictEqual(router
.pathsByLength
[3][0], expected
);
209 it('adds new method to path', function () {
210 const urlPath
= '/a/:id';
211 const expected
= router
._pathDefinitionToPathMatch(urlPath
);
212 expected
[router
.METHODS
]['GET'] = stubEntry
;
213 expected
[router
.METHODS
]['POST'] = stubEntry
;
214 router
.on('GET', urlPath
, stubHandler
);
216 router
.on('POST', urlPath
, stubHandler
);
217 assert
.deepStrictEqual(router
.pathsByLength
[3][0], expected
);
220 it('add some more paths', function () {
221 let urlPath
= '/a/b/c/d';
222 const expected
= router
._pathDefinitionToPathMatch(urlPath
);
223 expected
[router
.METHODS
]['GET'] = stubEntry
;
224 router
.on('GET', urlPath
, stubHandler
);
225 urlPath
= '/a/b/x/y';
226 router
.on('GET', urlPath
, stubHandler
);
228 assert
.strictEqual(router
.pathsByLength
[5].length
, 2);
231 it('adds multiple methods', function () {
232 const urlPath
= '/:id';
233 const expected
= router
._pathDefinitionToPathMatch(urlPath
);
234 expected
[router
.METHODS
]['GET'] = stubEntry
;
235 expected
[router
.METHODS
]['HEAD'] = stubEntry
;
237 router
.on(['GET', 'HEAD'], urlPath
, stubHandler
);
238 assert
.deepStrictEqual(router
.pathsByLength
[2][0], expected
);
241 it('adds new wildcard path', function () {
242 const urlPath
= '/a/:id';
243 const expected
= router
._pathDefinitionToPathMatch(urlPath
);
244 expected
[router
.METHODS
]['*'] = stubEntry
;
245 router
.on('*', urlPath
, stubHandler
);
246 assert
.deepStrictEqual(router
.pathsByLength
[3][0], expected
);
249 it('fails to add unknown method path', function () {
250 const urlPath
= '/a/:id';
252 router
.on('FLARP', urlPath
, stubHandler
);
253 assert
.fail('expected an exception');
255 assert
.strictEqual(e
.name
, 'DingusError');
256 assert
.strictEqual(e
.message
, 'invalid method \'FLARP\'');
260 it('requires args to be array', function () {
261 const urlPath
= '/a';
263 router
.on('GET', urlPath
, stubHandler
, {});
264 assert
.fail('expected an exception');
266 assert(e
instanceof TypeError
);
271 describe('lookup', function () {
272 let pathsByLengthOrig
;
276 beforeEach(function () {
278 pathsByLengthOrig
= router
.pathsByLength
;
279 stubHandler
= sinon
.stub();
281 afterEach(function () {
282 router
.pathsByLength
= pathsByLengthOrig
;
285 it('finds handler', function () {
286 const urlPath
= '/:id';
287 const method
= 'GET';
288 router
.on(method
, urlPath
, stubHandler
);
291 const { handler
} = router
.lookup(method
, path
, ctx
);
292 assert
.strictEqual(handler
, stubHandler
);
294 it('does not find handler with trailing slash', function () {
295 router
.ignoreTrailingSlash
= false;
296 const urlPath
= '/:id';
297 const method
= 'GET';
298 router
.on(method
, urlPath
, stubHandler
);
299 const path
= '/abc/';
302 router
.lookup(method
, path
, ctx
);
303 assert
.fail(noExpectedException
);
305 assert(e
instanceof DingusError
);
306 assert
.strictEqual(e
.message
, 'NoPath');
309 it('finds handler', function () {
310 router
.ignoreTrailingSlash
= true;
311 const urlPath
= '/:id';
312 const method
= 'GET';
313 router
.on(method
, urlPath
, stubHandler
);
314 const path
= '/abc/';
316 const { handler
} = router
.lookup(method
, path
, ctx
);
317 assert
.strictEqual(handler
, stubHandler
);
319 it('finds handler without context', async
function () {
320 const urlPath
= '/:id';
321 const method
= 'GET';
322 router
.on(method
, urlPath
, stubHandler
);
325 const { handler
} = router
.lookup(method
, path
);
326 assert
.strictEqual(handler
, stubHandler
);
328 it('finds fallback handler', async
function () {
329 const urlPath
= '/abc/:id';
330 const method
= 'GET';
331 router
.on('*', urlPath
, stubHandler
);
332 const path
= '/abc/def';
334 const { handler
} = router
.lookup(method
, path
, ctx
);
335 assert
.strictEqual(handler
, stubHandler
);
337 it('calls unsupported method', async
function () {
338 const urlPath
= '/:id';
339 const method
= 'POST';
340 router
.on('GET', urlPath
, stubHandler
);
344 router
.lookup(method
, path
, ctx
);
345 assert
.fail(noExpectedException
);
347 assert(e
instanceof DingusError
);
348 assert
.strictEqual(e
.message
, 'NoMethod');
351 it('does not lookup non-existent path', async
function () {
352 const path
= '/foo/bar';
353 const method
= 'GET';
356 router
.lookup(method
, path
, ctx
);
357 assert
.fail(noExpectedException
);
359 assert(e
instanceof DingusError
);
360 assert
.strictEqual(e
.message
, 'NoPath');