@contrast/route-coverage 1.22.1 → 1.23.1

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.d.ts CHANGED
@@ -24,9 +24,10 @@ export { RouteInfo };
24
24
 
25
25
  export interface RouteCoverage extends Installable {
26
26
  discover(info: RouteInfo): void;
27
- delete(info: RouteInfo): void;
28
27
  discoveryFinished(): void;
29
- observe(info: Pick<RouteInfo>): void;
28
+ queue(info: RouteInfo): void;
29
+ queuingFinished(): void;
30
+ observe(info: RouteInfo): void;
30
31
  }
31
32
 
32
33
  export interface Core {
package/lib/index.js CHANGED
@@ -34,18 +34,38 @@ module.exports = function init(core) {
34
34
  const routeInfo = new Map();
35
35
  const recentlyObserved = new Set();
36
36
 
37
+ const routeQueue = new Map();
37
38
  const routeCoverage = core.routeCoverage = {
38
39
  discover(info) {
39
40
  routeInfo.set(routeIdentifier(info), info);
40
41
  },
41
42
 
42
- delete(info) {
43
- routeInfo.delete(routeIdentifier(info));
44
- },
45
-
46
43
  discoveryFinished() {
47
44
  const routes = Array.from(routeInfo.values());
48
45
  messages.emit(Event.ROUTE_COVERAGE_DISCOVERY_FINISHED, routes);
46
+
47
+ this.discover = this.queue;
48
+ this.discoveryFinished = this.queuingFinished;
49
+ },
50
+
51
+ // See NODE-3548: routes defined "lazily" will be discovered here after startup, queued, and reported
52
+ queue(info) {
53
+ const id = routeIdentifier(info);
54
+ if (routeInfo.has(id)) return;
55
+
56
+ routeInfo.set(id, info);
57
+ routeQueue.set(id, info);
58
+ if (routeQueue.size === 1) {
59
+ setTimeout(() => {
60
+ this.discoveryFinished();
61
+ }, 10000);
62
+ }
63
+ },
64
+
65
+ queuingFinished() {
66
+ const routes = Array.from(routeQueue.values());
67
+ messages.emit(Event.ROUTE_COVERAGE_DISCOVERY_FINISHED, routes);
68
+ routeQueue.clear();
49
69
  },
50
70
 
51
71
  observe(info) {
package/lib/index.test.js CHANGED
@@ -11,11 +11,12 @@ const { installsComponents } = require('@contrast/test/utils');
11
11
  const MODULES = ['express', 'fastify', 'hapi', 'koa'];
12
12
 
13
13
  describe('route coverage', function () {
14
- let core, simulateRequestScope, routeCoverage;
14
+ let core, simulateRequestScope, routeCoverage, clock;
15
15
 
16
16
  beforeEach(function () {
17
17
  ({ core, simulateRequestScope } = initAssessFixture());
18
18
 
19
+ clock = sinon.useFakeTimers();
19
20
  sinon.spy(core.messages, 'emit');
20
21
 
21
22
  const moduleMock = (moduleName) => (deps) => {
@@ -59,6 +60,27 @@ describe('route coverage', function () {
59
60
  [eventA, eventB],
60
61
  );
61
62
  });
63
+
64
+ it('queues new events after initial discovery is finished', function () {
65
+ const eventA = { signature: 'hello', url: 'url', method: 'get' };
66
+ core.routeCoverage.discover(eventA);
67
+ core.routeCoverage.discoveryFinished();
68
+ expect(core.messages.emit).to.have.been.calledWith(
69
+ Event.ROUTE_COVERAGE_DISCOVERY_FINISHED,
70
+ [eventA],
71
+ );
72
+
73
+ const eventB = { signature: 'hello', url: 'url', method: 'post' };
74
+ core.routeCoverage.discover(eventA); // check that we dedupe routes discoverd on startup
75
+ core.routeCoverage.discover(eventB);
76
+ core.routeCoverage.discover(eventB); // check that we dedupe routes defined lazily
77
+ clock.tick(10000); //queuingFinished
78
+
79
+ expect(core.messages.emit).to.have.been.calledWith(
80
+ Event.ROUTE_COVERAGE_DISCOVERY_FINISHED,
81
+ [eventB],
82
+ );
83
+ });
62
84
  });
63
85
 
64
86
  describe('.observe()', function () {
@@ -116,10 +116,6 @@ module.exports = function init(core) {
116
116
  },
117
117
  });
118
118
  });
119
- server.addHook('onReady', (done) => {
120
- routeCoverage.discoveryFinished();
121
- return done();
122
- });
123
119
  }
124
120
  }));
125
121
  }
@@ -154,12 +154,6 @@ describe('route-coverage fastify', function () {
154
154
  expect(core.routeCoverage.discover).to.have.callCount(2);
155
155
  });
156
156
 
157
- it('signals that discovery is finished when the onReady hook is triggered', function () {
158
- serverMock.addHook.withArgs('onReady').yield(sinon.stub());
159
-
160
- expect(core.routeCoverage.discoveryFinished).to.have.been.calledOnce;
161
- });
162
-
163
157
  it('observes a route when the route handler is called', function () {
164
158
  const routeOptions = {
165
159
  method: 'GET',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/route-coverage",
3
- "version": "1.22.1",
3
+ "version": "1.23.1",
4
4
  "description": "Handles route discovery and observation",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
@@ -17,7 +17,12 @@
17
17
  "test": "../scripts/test.sh"
18
18
  },
19
19
  "dependencies": {
20
- "@contrast/common": "1.23.0",
21
- "@contrast/fn-inspect": "^4.3.0"
20
+ "@contrast/common": "1.24.0",
21
+ "@contrast/config": "1.31.0",
22
+ "@contrast/dep-hooks": "1.3.4",
23
+ "@contrast/fn-inspect": "^4.3.0",
24
+ "@contrast/logger": "1.8.5",
25
+ "@contrast/patcher": "1.7.5",
26
+ "@contrast/scopes": "1.4.2"
22
27
  }
23
28
  }