@contrast/route-coverage 1.33.0 → 1.35.0
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/lib/index.js +13 -4
- package/lib/index.test.js +6 -6
- package/lib/install/{express.js → express/express4.js} +2 -3
- package/lib/install/{express.test.js → express/express4.test.js} +1 -1
- package/lib/install/express/express5.js +256 -0
- package/lib/install/express/express5.test.js +813 -0
- package/lib/install/express/index.js +31 -0
- package/lib/install/graphql.js +115 -0
- package/lib/install/graphql.test.js +175 -0
- package/lib/install/hapi.js +6 -3
- package/lib/install/hapi.test.js +2 -0
- package/lib/utils/route-info.js +5 -10
- package/package.json +9 -8
|
@@ -0,0 +1,813 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { expect } = require('chai');
|
|
4
|
+
const sinon = require('sinon');
|
|
5
|
+
const scopes = require('@contrast/scopes');
|
|
6
|
+
const patcher = require('@contrast/patcher');
|
|
7
|
+
const mocks = require('@contrast/test/mocks');
|
|
8
|
+
|
|
9
|
+
const METHODS = [
|
|
10
|
+
'all',
|
|
11
|
+
'get',
|
|
12
|
+
'post',
|
|
13
|
+
'put',
|
|
14
|
+
'delete',
|
|
15
|
+
'patch',
|
|
16
|
+
'options',
|
|
17
|
+
'head',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
describe('route-coverage express5', function () {
|
|
21
|
+
let core, application, Router, express, framework;
|
|
22
|
+
|
|
23
|
+
beforeEach(function () {
|
|
24
|
+
core = mocks.core();
|
|
25
|
+
core.logger = mocks.logger();
|
|
26
|
+
core.routeCoverage = mocks.routeCoverage();
|
|
27
|
+
core.scopes = scopes(core);
|
|
28
|
+
core.depHooks = mocks.depHooks();
|
|
29
|
+
core.patcher = patcher(core);
|
|
30
|
+
|
|
31
|
+
framework = 'express';
|
|
32
|
+
application = {};
|
|
33
|
+
Router = () => Router.prototype;
|
|
34
|
+
Router.prototype = {};
|
|
35
|
+
METHODS.forEach((method) => {
|
|
36
|
+
application[method] = sinon.stub();
|
|
37
|
+
Router.prototype[method] = sinon.stub();
|
|
38
|
+
});
|
|
39
|
+
application.use = sinon.stub();
|
|
40
|
+
Router.prototype.use = sinon.stub();
|
|
41
|
+
Router.prototype.name = 'Router';
|
|
42
|
+
express = () => application;
|
|
43
|
+
express.application = application;
|
|
44
|
+
express.Router = Router;
|
|
45
|
+
|
|
46
|
+
sinon.spy(core.patcher, 'patch');
|
|
47
|
+
core.depHooks.resolve.withArgs({ name: 'express', version: '5' }).yields(express);
|
|
48
|
+
|
|
49
|
+
require('./express5')(core).install();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('app', function () {
|
|
53
|
+
METHODS.forEach((method) => {
|
|
54
|
+
describe(`${method}`, function () {
|
|
55
|
+
|
|
56
|
+
it('does not report an empty route', function () {
|
|
57
|
+
const app = express();
|
|
58
|
+
app[method]();
|
|
59
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('does not report an invalid route', function () {
|
|
63
|
+
const app = express();
|
|
64
|
+
app[method](42);
|
|
65
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('does not report a route missing a handler', function () {
|
|
69
|
+
const app = express();
|
|
70
|
+
app[method]('/test/route');
|
|
71
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('does not report a route with an invalid handler', function () {
|
|
75
|
+
const app = express();
|
|
76
|
+
app[method]('/test/route', {});
|
|
77
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('does not report an empty path', function () {
|
|
81
|
+
const fn = function() {};
|
|
82
|
+
const app = express();
|
|
83
|
+
app[method]('', fn);
|
|
84
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('discovers a route', function () {
|
|
88
|
+
const fn = function() {};
|
|
89
|
+
const app = express();
|
|
90
|
+
app[method]('/test/route', fn);
|
|
91
|
+
|
|
92
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
93
|
+
signature: `app.${method}('/test/route', fn)`,
|
|
94
|
+
url: '/test/route',
|
|
95
|
+
normalizedUrl: '/test/route',
|
|
96
|
+
method,
|
|
97
|
+
framework
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('removes a trailing slash from a route', function () {
|
|
102
|
+
const fn = function() {};
|
|
103
|
+
const app = express();
|
|
104
|
+
app[method]('/test/route/', fn);
|
|
105
|
+
|
|
106
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
107
|
+
signature: `app.${method}('/test/route', fn)`,
|
|
108
|
+
url: '/test/route',
|
|
109
|
+
normalizedUrl: '/test/route',
|
|
110
|
+
method,
|
|
111
|
+
framework
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('discovers a route with an anonymous function handler', function () {
|
|
116
|
+
const app = express();
|
|
117
|
+
app[method]('/test/route', () => {});
|
|
118
|
+
|
|
119
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
120
|
+
signature: `app.${method}('/test/route', (anonymous express5.test.js 116:37))`, //TODO make consistent
|
|
121
|
+
url: '/test/route',
|
|
122
|
+
normalizedUrl: '/test/route',
|
|
123
|
+
method,
|
|
124
|
+
framework
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('discovers an array route', function () {
|
|
129
|
+
const app = express();
|
|
130
|
+
const fn = function() {};
|
|
131
|
+
app[method](['/test/foo', '/test/bar'], fn);
|
|
132
|
+
|
|
133
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
134
|
+
signature: `app.${method}('/[/test/foo,/test/bar]', fn)`,
|
|
135
|
+
url: '/[/test/foo,/test/bar]',
|
|
136
|
+
normalizedUrl: '/[/test/foo,/test/bar]',
|
|
137
|
+
method,
|
|
138
|
+
framework
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('discovers a route for each handler', function () {
|
|
143
|
+
const fn1 = function() {};
|
|
144
|
+
const fn2 = function() {};
|
|
145
|
+
const app = express();
|
|
146
|
+
app[method]('/test/route', fn1, fn2);
|
|
147
|
+
|
|
148
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
149
|
+
signature: `app.${method}('/test/route', fn1)`,
|
|
150
|
+
url: '/test/route',
|
|
151
|
+
normalizedUrl: '/test/route',
|
|
152
|
+
method,
|
|
153
|
+
framework
|
|
154
|
+
});
|
|
155
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
156
|
+
signature: `app.${method}('/test/route', fn2)`,
|
|
157
|
+
url: '/test/route',
|
|
158
|
+
normalizedUrl: '/test/route',
|
|
159
|
+
method,
|
|
160
|
+
framework
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('discovers a route for each handler in an array', function () {
|
|
165
|
+
const fn1 = function() {};
|
|
166
|
+
const fn2 = function() {};
|
|
167
|
+
const app = express();
|
|
168
|
+
app[method]('/test/route', [fn1, fn2]);
|
|
169
|
+
|
|
170
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
171
|
+
signature: `app.${method}('/test/route', fn1)`,
|
|
172
|
+
url: '/test/route',
|
|
173
|
+
normalizedUrl: '/test/route',
|
|
174
|
+
method,
|
|
175
|
+
framework
|
|
176
|
+
});
|
|
177
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
178
|
+
signature: `app.${method}('/test/route', fn2)`,
|
|
179
|
+
url: '/test/route',
|
|
180
|
+
normalizedUrl: '/test/route',
|
|
181
|
+
method,
|
|
182
|
+
framework
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('observes a route when a handler is exercised', function () {
|
|
187
|
+
const app = express();
|
|
188
|
+
const fn = function() {};
|
|
189
|
+
core.patcher.patch.resetHistory();
|
|
190
|
+
app[method]('/test/route', fn);
|
|
191
|
+
|
|
192
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
193
|
+
patchedFn({
|
|
194
|
+
method,
|
|
195
|
+
originalUrl: '/test/route?input=foo'
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
199
|
+
signature: `app.${method}('/test/route', fn)`,
|
|
200
|
+
url: '/test/route',
|
|
201
|
+
normalizedUrl: '/test/route',
|
|
202
|
+
method,
|
|
203
|
+
framework
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('observes an array route', function () {
|
|
208
|
+
const app = express();
|
|
209
|
+
const fn = function() {};
|
|
210
|
+
core.patcher.patch.resetHistory();
|
|
211
|
+
app[method](['/test/route', '/test/route2'], fn);
|
|
212
|
+
|
|
213
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
214
|
+
patchedFn({
|
|
215
|
+
method,
|
|
216
|
+
originalUrl: '/test/route?input=foo'
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
220
|
+
signature: `app.${method}('/[/test/route,/test/route2]', fn)`,
|
|
221
|
+
url: '/test/route',
|
|
222
|
+
normalizedUrl: '/[/test/route,/test/route2]',
|
|
223
|
+
method,
|
|
224
|
+
framework
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('observes a route when only one handler is exercised', function () {
|
|
229
|
+
const app = express();
|
|
230
|
+
const fn1 = function() {};
|
|
231
|
+
const fn2 = function() {};
|
|
232
|
+
core.patcher.patch.resetHistory();
|
|
233
|
+
app[method]('/test/route', fn1, fn2);
|
|
234
|
+
|
|
235
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
236
|
+
patchedFn({
|
|
237
|
+
method,
|
|
238
|
+
originalUrl: '/test/route?input=foo'
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
242
|
+
signature: `app.${method}('/test/route', fn1)`,
|
|
243
|
+
url: '/test/route',
|
|
244
|
+
normalizedUrl: '/test/route',
|
|
245
|
+
method,
|
|
246
|
+
framework
|
|
247
|
+
});
|
|
248
|
+
expect(core.routeCoverage.observe).not.to.have.been.calledWith({
|
|
249
|
+
signature: `app.${method}('/test/route', fn2)`,
|
|
250
|
+
url: '/test/route',
|
|
251
|
+
normalizedUrl: '/test/route',
|
|
252
|
+
method,
|
|
253
|
+
framework
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('observes a route when multiple handlers are exercised', function () {
|
|
258
|
+
const app = express();
|
|
259
|
+
const fn1 = function() {};
|
|
260
|
+
const fn2 = function() {};
|
|
261
|
+
core.patcher.patch.resetHistory();
|
|
262
|
+
app[method]('/test/route', fn1, fn2);
|
|
263
|
+
|
|
264
|
+
const patchedFn1 = core.patcher.patch.getCall(0).returnValue;
|
|
265
|
+
const patchedFn2 = core.patcher.patch.getCall(1).returnValue;
|
|
266
|
+
|
|
267
|
+
patchedFn1({
|
|
268
|
+
method,
|
|
269
|
+
originalUrl: '/test/route?input=foo'
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
patchedFn2({
|
|
273
|
+
method,
|
|
274
|
+
originalUrl: '/test/route?input=bar'
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
278
|
+
signature: `app.${method}('/test/route', fn1)`,
|
|
279
|
+
url: '/test/route',
|
|
280
|
+
normalizedUrl: '/test/route',
|
|
281
|
+
method,
|
|
282
|
+
framework
|
|
283
|
+
});
|
|
284
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
285
|
+
signature: `app.${method}('/test/route', fn2)`,
|
|
286
|
+
url: '/test/route',
|
|
287
|
+
normalizedUrl: '/test/route',
|
|
288
|
+
method,
|
|
289
|
+
framework
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('does not discover and App.use route with no path and no router', function () {
|
|
297
|
+
const app = express();
|
|
298
|
+
const fn = function() {};
|
|
299
|
+
app.use(fn);
|
|
300
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('discovers a route when declared with app.use', function () {
|
|
304
|
+
const app = express();
|
|
305
|
+
const fn = function() {};
|
|
306
|
+
app.use('/test/route', fn);
|
|
307
|
+
|
|
308
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
309
|
+
signature: 'app.use(\'/test/route\', fn)',
|
|
310
|
+
url: '/test/route',
|
|
311
|
+
normalizedUrl: '/test/route',
|
|
312
|
+
method: 'use',
|
|
313
|
+
framework
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('discovers a route with an array path when declared with app.use', function () {
|
|
318
|
+
const app = express();
|
|
319
|
+
const fn = function() {};
|
|
320
|
+
app.use(['/test/route', '/test/route2'], fn);
|
|
321
|
+
|
|
322
|
+
//TODO add space
|
|
323
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
324
|
+
signature: 'app.use(\'/[/test/route,/test/route2]\', fn)',
|
|
325
|
+
url: '/[/test/route,/test/route2]',
|
|
326
|
+
normalizedUrl: '/[/test/route,/test/route2]',
|
|
327
|
+
method: 'use',
|
|
328
|
+
framework
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('discovers a route for each handler for app.use', function () {
|
|
333
|
+
const app = express();
|
|
334
|
+
const fn1 = function() {};
|
|
335
|
+
const fn2 = function() {};
|
|
336
|
+
app.use('/test/route', fn1, fn2);
|
|
337
|
+
|
|
338
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
339
|
+
signature: 'app.use(\'/test/route\', fn1)',
|
|
340
|
+
url: '/test/route',
|
|
341
|
+
normalizedUrl: '/test/route',
|
|
342
|
+
method: 'use',
|
|
343
|
+
framework
|
|
344
|
+
});
|
|
345
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
346
|
+
signature: 'app.use(\'/test/route\', fn2)',
|
|
347
|
+
url: '/test/route',
|
|
348
|
+
normalizedUrl: '/test/route',
|
|
349
|
+
method: 'use',
|
|
350
|
+
framework
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it('observes a route when app.use handler exercised', function () {
|
|
355
|
+
const app = express();
|
|
356
|
+
const fn = function() {};
|
|
357
|
+
core.patcher.patch.resetHistory();
|
|
358
|
+
app.use('/test/route', fn);
|
|
359
|
+
|
|
360
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
361
|
+
patchedFn({
|
|
362
|
+
method: 'GET',
|
|
363
|
+
originalUrl: '/test/route?input=foo'
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
367
|
+
signature: 'app.use(\'/test/route\', fn)',
|
|
368
|
+
url: '/test/route',
|
|
369
|
+
normalizedUrl: '/test/route',
|
|
370
|
+
method: 'get',
|
|
371
|
+
framework
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
describe('router', function () {
|
|
377
|
+
METHODS.forEach((method) => {
|
|
378
|
+
describe(`${method}`, function () {
|
|
379
|
+
it('does not report an empty route', function () {
|
|
380
|
+
const app = express();
|
|
381
|
+
const Router = express.Router();
|
|
382
|
+
Router[method]();
|
|
383
|
+
app.use(Router);
|
|
384
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('does not report an invalid route', function () {
|
|
388
|
+
const app = express();
|
|
389
|
+
const Router = express.Router();
|
|
390
|
+
Router[method](42);
|
|
391
|
+
app.use(Router);
|
|
392
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it('does not report a route missing a handler', function () {
|
|
396
|
+
const app = express();
|
|
397
|
+
const Router = express.Router();
|
|
398
|
+
Router[method]('/test/route');
|
|
399
|
+
app.use(Router);
|
|
400
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it('does not report a route with an invalid handler', function () {
|
|
404
|
+
const app = express();
|
|
405
|
+
const Router = express.Router();
|
|
406
|
+
Router[method]('/test/route', {});
|
|
407
|
+
app.use(Router);
|
|
408
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('does not report an empty path', function () {
|
|
412
|
+
const fn = function() {};
|
|
413
|
+
const app = express();
|
|
414
|
+
const Router = express.Router();
|
|
415
|
+
Router[method]('', fn);
|
|
416
|
+
app.use(Router);
|
|
417
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('discovers a route', function () {
|
|
421
|
+
const fn = function() {};
|
|
422
|
+
const app = express();
|
|
423
|
+
const Router = express.Router();
|
|
424
|
+
Router[method]('/test/route', fn);
|
|
425
|
+
|
|
426
|
+
app.use(Router);
|
|
427
|
+
|
|
428
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
429
|
+
signature: `router.${method}('/test/route', fn)`,
|
|
430
|
+
url: '/test/route',
|
|
431
|
+
normalizedUrl: '/test/route',
|
|
432
|
+
method,
|
|
433
|
+
framework
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('discovers a route with an anonymous function handler', function () {
|
|
438
|
+
const app = express();
|
|
439
|
+
const Router = express.Router();
|
|
440
|
+
Router[method]('/test/route', () => {});
|
|
441
|
+
|
|
442
|
+
app.use(Router);
|
|
443
|
+
|
|
444
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
445
|
+
signature: `router.${method}('/test/route', (anonymous express5.test.js 439:40))`, //TODO make consistent
|
|
446
|
+
url: '/test/route',
|
|
447
|
+
normalizedUrl: '/test/route',
|
|
448
|
+
method,
|
|
449
|
+
framework
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
it('discovers an array route', function () {
|
|
454
|
+
const app = express();
|
|
455
|
+
const fn = function() {};
|
|
456
|
+
const Router = express.Router();
|
|
457
|
+
Router[method](['/test/foo', '/test/bar'], fn);
|
|
458
|
+
|
|
459
|
+
app.use(Router);
|
|
460
|
+
|
|
461
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
462
|
+
signature: `router.${method}('/[/test/foo,/test/bar]', fn)`,
|
|
463
|
+
url: '/[/test/foo,/test/bar]',
|
|
464
|
+
normalizedUrl: '/[/test/foo,/test/bar]',
|
|
465
|
+
method,
|
|
466
|
+
framework
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('discovers a route for each handler', function () {
|
|
471
|
+
const fn1 = function() {};
|
|
472
|
+
const fn2 = function() {};
|
|
473
|
+
const app = express();
|
|
474
|
+
const Router = express.Router();
|
|
475
|
+
Router[method]('/test/route', fn1, fn2);
|
|
476
|
+
|
|
477
|
+
app.use(Router);
|
|
478
|
+
|
|
479
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
480
|
+
signature: `router.${method}('/test/route', fn1)`,
|
|
481
|
+
url: '/test/route',
|
|
482
|
+
normalizedUrl: '/test/route',
|
|
483
|
+
method,
|
|
484
|
+
framework
|
|
485
|
+
});
|
|
486
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
487
|
+
signature: `router.${method}('/test/route', fn2)`,
|
|
488
|
+
url: '/test/route',
|
|
489
|
+
normalizedUrl: '/test/route',
|
|
490
|
+
method,
|
|
491
|
+
framework
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it('discovers a route for each handler in an array', function () {
|
|
496
|
+
const fn1 = function() {};
|
|
497
|
+
const fn2 = function() {};
|
|
498
|
+
const app = express();
|
|
499
|
+
const Router = express.Router();
|
|
500
|
+
Router[method]('/test/route', [fn1, fn2]);
|
|
501
|
+
|
|
502
|
+
app.use(Router);
|
|
503
|
+
|
|
504
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
505
|
+
signature: `router.${method}('/test/route', fn1)`,
|
|
506
|
+
url: '/test/route',
|
|
507
|
+
normalizedUrl: '/test/route',
|
|
508
|
+
method,
|
|
509
|
+
framework
|
|
510
|
+
});
|
|
511
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
512
|
+
signature: `router.${method}('/test/route', fn2)`,
|
|
513
|
+
url: '/test/route',
|
|
514
|
+
normalizedUrl: '/test/route',
|
|
515
|
+
method,
|
|
516
|
+
framework
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
it('observes a route when a handler is exercised', function () {
|
|
521
|
+
const app = express();
|
|
522
|
+
const fn = function() {};
|
|
523
|
+
const Router = express.Router();
|
|
524
|
+
core.patcher.patch.resetHistory();
|
|
525
|
+
Router[method]('/test/route', fn);
|
|
526
|
+
|
|
527
|
+
app.use(Router);
|
|
528
|
+
|
|
529
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
530
|
+
patchedFn({
|
|
531
|
+
method,
|
|
532
|
+
originalUrl: '/test/route?input=foo'
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
536
|
+
signature: `router.${method}('/test/route', fn)`,
|
|
537
|
+
url: '/test/route',
|
|
538
|
+
normalizedUrl: '/test/route',
|
|
539
|
+
method,
|
|
540
|
+
framework
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it('observes an array route', function () {
|
|
545
|
+
const app = express();
|
|
546
|
+
const fn = function() {};
|
|
547
|
+
const Router = express.Router();
|
|
548
|
+
core.patcher.patch.resetHistory();
|
|
549
|
+
Router[method](['/test/route', '/test/route2'], fn);
|
|
550
|
+
|
|
551
|
+
app.use(Router);
|
|
552
|
+
|
|
553
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
554
|
+
patchedFn({
|
|
555
|
+
method,
|
|
556
|
+
originalUrl: '/test/route?input=foo'
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
560
|
+
signature: `router.${method}('/[/test/route,/test/route2]', fn)`,
|
|
561
|
+
url: '/test/route',
|
|
562
|
+
normalizedUrl: '/[/test/route,/test/route2]',
|
|
563
|
+
method,
|
|
564
|
+
framework
|
|
565
|
+
});
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
it('observes an updated array route', function () {
|
|
569
|
+
const app = express();
|
|
570
|
+
const fn = function() {};
|
|
571
|
+
const Router = express.Router();
|
|
572
|
+
core.patcher.patch.resetHistory();
|
|
573
|
+
Router[method](['/test/route', '/test/route2'], fn);
|
|
574
|
+
|
|
575
|
+
app.use('/p1', Router);
|
|
576
|
+
|
|
577
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
578
|
+
patchedFn({
|
|
579
|
+
method,
|
|
580
|
+
originalUrl: '/p1/test/route?input=foo'
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
584
|
+
signature: `router.${method}('/p1/[/test/route,/test/route2]', fn)`,
|
|
585
|
+
url: '/p1/test/route',
|
|
586
|
+
normalizedUrl: '/p1/[/test/route,/test/route2]',
|
|
587
|
+
method,
|
|
588
|
+
framework
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it('observes a route when only one handler is exercised', function () {
|
|
593
|
+
const app = express();
|
|
594
|
+
const fn1 = function() {};
|
|
595
|
+
const fn2 = function() {};
|
|
596
|
+
const Router = express.Router();
|
|
597
|
+
core.patcher.patch.resetHistory();
|
|
598
|
+
Router[method]('/test/route', fn1, fn2);
|
|
599
|
+
|
|
600
|
+
app.use(Router);
|
|
601
|
+
|
|
602
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
603
|
+
patchedFn({
|
|
604
|
+
method,
|
|
605
|
+
originalUrl: '/test/route?input=foo'
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
609
|
+
signature: `router.${method}('/test/route', fn1)`,
|
|
610
|
+
url: '/test/route',
|
|
611
|
+
normalizedUrl: '/test/route',
|
|
612
|
+
method,
|
|
613
|
+
framework
|
|
614
|
+
});
|
|
615
|
+
expect(core.routeCoverage.observe).not.to.have.been.calledWith({
|
|
616
|
+
signature: `router.${method}('/test/route', fn2)`,
|
|
617
|
+
url: '/test/route',
|
|
618
|
+
normalizedUrl: '/test/route',
|
|
619
|
+
method,
|
|
620
|
+
framework
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('observes a route when multiple handlers are exercised', function () {
|
|
625
|
+
const app = express();
|
|
626
|
+
const fn1 = function() {};
|
|
627
|
+
const fn2 = function() {};
|
|
628
|
+
const Router = express.Router();
|
|
629
|
+
core.patcher.patch.resetHistory();
|
|
630
|
+
Router[method]('/test/route', fn1, fn2);
|
|
631
|
+
|
|
632
|
+
app.use(Router);
|
|
633
|
+
|
|
634
|
+
const patchedFn1 = core.patcher.patch.getCall(0).returnValue;
|
|
635
|
+
const patchedFn2 = core.patcher.patch.getCall(1).returnValue;
|
|
636
|
+
|
|
637
|
+
patchedFn1({
|
|
638
|
+
method,
|
|
639
|
+
originalUrl: '/test/route?input=foo'
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
patchedFn2({
|
|
643
|
+
method,
|
|
644
|
+
originalUrl: '/test/route?input=bar'
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
648
|
+
signature: `router.${method}('/test/route', fn1)`,
|
|
649
|
+
url: '/test/route',
|
|
650
|
+
normalizedUrl: '/test/route',
|
|
651
|
+
method,
|
|
652
|
+
framework
|
|
653
|
+
});
|
|
654
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
655
|
+
signature: `router.${method}('/test/route', fn2)`,
|
|
656
|
+
url: '/test/route',
|
|
657
|
+
normalizedUrl: '/test/route',
|
|
658
|
+
method,
|
|
659
|
+
framework
|
|
660
|
+
});
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
it('does not discover and router.use route with no path and no router', function () {
|
|
666
|
+
const app = express();
|
|
667
|
+
const fn = function() {};
|
|
668
|
+
const Router = express.Router();
|
|
669
|
+
|
|
670
|
+
Router.use(fn);
|
|
671
|
+
app.use(Router);
|
|
672
|
+
expect(core.routeCoverage.discover).not.to.have.been.called;
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it('discovers a route when declared with router.use', function () {
|
|
676
|
+
const app = express();
|
|
677
|
+
const fn = function() {};
|
|
678
|
+
const Router = express.Router();
|
|
679
|
+
Router.use('/test/route', fn);
|
|
680
|
+
app.use(Router);
|
|
681
|
+
|
|
682
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
683
|
+
signature: 'router.use(\'/test/route\', fn)',
|
|
684
|
+
url: '/test/route',
|
|
685
|
+
normalizedUrl: '/test/route',
|
|
686
|
+
method: 'use',
|
|
687
|
+
framework
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
it('discovers a route with an array path when declared with router.use', function () {
|
|
692
|
+
const app = express();
|
|
693
|
+
const fn = function() {};
|
|
694
|
+
const Router = express.Router();
|
|
695
|
+
Router.use(['/test/route', '/test/route2'], fn);
|
|
696
|
+
app.use(Router);
|
|
697
|
+
|
|
698
|
+
//TODO add space
|
|
699
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
700
|
+
signature: 'router.use(\'/[/test/route,/test/route2]\', fn)',
|
|
701
|
+
url: '/[/test/route,/test/route2]',
|
|
702
|
+
normalizedUrl: '/[/test/route,/test/route2]',
|
|
703
|
+
method: 'use',
|
|
704
|
+
framework
|
|
705
|
+
});
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
it('discovers a route for each handler for router.use', function () {
|
|
709
|
+
const app = express();
|
|
710
|
+
const fn1 = function() {};
|
|
711
|
+
const fn2 = function() {};
|
|
712
|
+
const Router = express.Router();
|
|
713
|
+
Router.use('/test/route', fn1, fn2);
|
|
714
|
+
app.use(Router);
|
|
715
|
+
|
|
716
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
717
|
+
signature: 'router.use(\'/test/route\', fn1)',
|
|
718
|
+
url: '/test/route',
|
|
719
|
+
normalizedUrl: '/test/route',
|
|
720
|
+
method: 'use',
|
|
721
|
+
framework
|
|
722
|
+
});
|
|
723
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
724
|
+
signature: 'router.use(\'/test/route\', fn2)',
|
|
725
|
+
url: '/test/route',
|
|
726
|
+
normalizedUrl: '/test/route',
|
|
727
|
+
method: 'use',
|
|
728
|
+
framework
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
it('observes a route when router.use handler exercised', function () {
|
|
733
|
+
const app = express();
|
|
734
|
+
const fn = function() {};
|
|
735
|
+
core.patcher.patch.resetHistory();
|
|
736
|
+
const Router = express.Router();
|
|
737
|
+
Router.use('/test/route', fn);
|
|
738
|
+
app.use(Router);
|
|
739
|
+
|
|
740
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
741
|
+
patchedFn({
|
|
742
|
+
method: 'GET',
|
|
743
|
+
originalUrl: '/test/route?input=foo'
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
747
|
+
signature: 'router.use(\'/test/route\', fn)',
|
|
748
|
+
url: '/test/route',
|
|
749
|
+
normalizedUrl: '/test/route',
|
|
750
|
+
method: 'get',
|
|
751
|
+
framework
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
it('updates a route when prefix is declared', function () {
|
|
756
|
+
const app = express();
|
|
757
|
+
const fn = function() {};
|
|
758
|
+
const Router = express.Router();
|
|
759
|
+
const Router2 = { ...Router };
|
|
760
|
+
Router.get('/test/route', fn);
|
|
761
|
+
Router2.use('/p1', Router);
|
|
762
|
+
app.use(Router2);
|
|
763
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
764
|
+
signature: 'router.get(\'/p1/test/route\', fn)',
|
|
765
|
+
url: '/p1/test/route',
|
|
766
|
+
normalizedUrl: '/p1/test/route',
|
|
767
|
+
method: 'get',
|
|
768
|
+
framework
|
|
769
|
+
});
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
it('correctly formats an updated route when router mounted on itself', function () {
|
|
773
|
+
const app = express();
|
|
774
|
+
const fn = function() {};
|
|
775
|
+
const Router = express.Router();
|
|
776
|
+
Router.get('/test/route', fn);
|
|
777
|
+
Router.use('/p1', Router);
|
|
778
|
+
app.use(Router);
|
|
779
|
+
expect(core.routeCoverage.discover).to.have.been.calledWith({
|
|
780
|
+
signature: 'router.get(\'/*p1/test/route\', fn)',
|
|
781
|
+
url: '/*p1/test/route',
|
|
782
|
+
normalizedUrl: '/*p1/test/route',
|
|
783
|
+
method: 'get',
|
|
784
|
+
framework
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
it('observes an updated route', function () {
|
|
789
|
+
const app = express();
|
|
790
|
+
const fn = function() {};
|
|
791
|
+
const Router = express.Router();
|
|
792
|
+
const Router2 = { ...Router };
|
|
793
|
+
core.patcher.patch.resetHistory();
|
|
794
|
+
Router.get('/test/route', fn);
|
|
795
|
+
Router2.use('/p1', Router);
|
|
796
|
+
app.use(Router2);
|
|
797
|
+
|
|
798
|
+
const patchedFn = core.patcher.patch.getCall(0).returnValue;
|
|
799
|
+
patchedFn({
|
|
800
|
+
method: 'GET',
|
|
801
|
+
originalUrl: '/p1/test/route?input=foo'
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
expect(core.routeCoverage.observe).to.have.been.calledWith({
|
|
805
|
+
signature: 'router.get(\'/p1/test/route\', fn)',
|
|
806
|
+
url: '/p1/test/route',
|
|
807
|
+
normalizedUrl: '/p1/test/route',
|
|
808
|
+
method: 'get',
|
|
809
|
+
framework
|
|
810
|
+
});
|
|
811
|
+
});
|
|
812
|
+
});
|
|
813
|
+
});
|