@villedemontreal/correlation-id 5.3.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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/src/config/configs.d.ts +16 -0
  4. package/dist/src/config/configs.js +26 -0
  5. package/dist/src/config/configs.js.map +1 -0
  6. package/dist/src/config/constants.d.ts +27 -0
  7. package/dist/src/config/constants.js +27 -0
  8. package/dist/src/config/constants.js.map +1 -0
  9. package/dist/src/config/init.d.ts +15 -0
  10. package/dist/src/config/init.js +34 -0
  11. package/dist/src/config/init.js.map +1 -0
  12. package/dist/src/index.d.ts +3 -0
  13. package/dist/src/index.js +25 -0
  14. package/dist/src/index.js.map +1 -0
  15. package/dist/src/middleware/correlationIdMiddleware.d.ts +8 -0
  16. package/dist/src/middleware/correlationIdMiddleware.js +43 -0
  17. package/dist/src/middleware/correlationIdMiddleware.js.map +1 -0
  18. package/dist/src/middleware/correlationIdMiddleware.test.d.ts +1 -0
  19. package/dist/src/middleware/correlationIdMiddleware.test.js +306 -0
  20. package/dist/src/middleware/correlationIdMiddleware.test.js.map +1 -0
  21. package/dist/src/services/correlationIdService.d.ts +68 -0
  22. package/dist/src/services/correlationIdService.js +166 -0
  23. package/dist/src/services/correlationIdService.js.map +1 -0
  24. package/dist/src/services/correlationIdService.test.d.ts +1 -0
  25. package/dist/src/services/correlationIdService.test.js +215 -0
  26. package/dist/src/services/correlationIdService.test.js.map +1 -0
  27. package/dist/src/utils/logger.d.ts +11 -0
  28. package/dist/src/utils/logger.js +54 -0
  29. package/dist/src/utils/logger.js.map +1 -0
  30. package/dist/src/utils/testingConfigurations.d.ts +9 -0
  31. package/dist/src/utils/testingConfigurations.js +18 -0
  32. package/dist/src/utils/testingConfigurations.js.map +1 -0
  33. package/package.json +62 -0
  34. package/src/config/configs.ts +26 -0
  35. package/src/config/constants.ts +40 -0
  36. package/src/config/init.ts +33 -0
  37. package/src/index.ts +9 -0
  38. package/src/middleware/correlationIdMiddleware.test.ts +335 -0
  39. package/src/middleware/correlationIdMiddleware.ts +45 -0
  40. package/src/services/correlationIdService.test.ts +255 -0
  41. package/src/services/correlationIdService.ts +255 -0
  42. package/src/utils/logger.ts +53 -0
  43. package/src/utils/testingConfigurations.ts +14 -0
@@ -0,0 +1,335 @@
1
+ import { assert } from 'chai';
2
+ import * as express from 'express';
3
+ import httpHeaderFieldsTyped from 'http-header-fields-typed';
4
+ import * as request from 'supertest';
5
+ import { correlationIdService } from '../services/correlationIdService';
6
+ import { setTestingConfigurations } from '../utils/testingConfigurations';
7
+ import { createCorrelationIdMiddleware } from './correlationIdMiddleware';
8
+
9
+ function delay(millis: number): Promise<void> {
10
+ return new Promise<void>(resolve =>
11
+ setTimeout(() => {
12
+ resolve();
13
+ }, millis)
14
+ );
15
+ }
16
+
17
+ // ==========================================
18
+ // Set Testing configurations
19
+ // ==========================================
20
+ setTestingConfigurations();
21
+
22
+ const uuidMatcher: RegExp = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
23
+
24
+ // ==========================================
25
+ // Correlation ID service
26
+ // ==========================================
27
+ // tslint:disable-next-line: max-func-body-length
28
+ describe('Correlation ID Middleware', () => {
29
+ it('should generate correlation id if it doesnt exists', async () => {
30
+ const app: express.Application = express();
31
+ app.use(createCorrelationIdMiddleware());
32
+ app.get('/', (req, res) => {
33
+ const actual = correlationIdService.getId();
34
+ assert.match(actual, uuidMatcher);
35
+ res.end();
36
+ });
37
+
38
+ await request(app)
39
+ .get('/')
40
+ .send();
41
+ });
42
+
43
+ it('should get correlation id from incoming request', async () => {
44
+ const testId: string = 'correlation-id-123';
45
+
46
+ const app: express.Application = express();
47
+ app.use(createCorrelationIdMiddleware());
48
+ app.get('/', (req, res) => {
49
+ const actual = correlationIdService.getId();
50
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
51
+ res.end();
52
+ });
53
+
54
+ await request(app)
55
+ .get('/')
56
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
57
+ .send();
58
+ });
59
+
60
+ it('should maintain correlation id with async callbacks', async () => {
61
+ const testId: string = 'correlation-id-123';
62
+
63
+ let actual = '';
64
+ let actual2 = '';
65
+ const app: express.Application = express();
66
+ app.use(createCorrelationIdMiddleware());
67
+ app.get('/', async (req, res, next) => {
68
+ actual = correlationIdService.getId();
69
+ setTimeout(() => {
70
+ actual2 = correlationIdService.getId();
71
+ res.end();
72
+ }, 250);
73
+ });
74
+
75
+ assert.isUndefined(correlationIdService.getId());
76
+ await request(app)
77
+ .get('/')
78
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
79
+ .send();
80
+
81
+ assert.isUndefined(correlationIdService.getId());
82
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
83
+ assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
84
+ });
85
+
86
+ it('should maintain correlation id with async/await operations', async () => {
87
+ const testId: string = 'correlation-id-123';
88
+
89
+ let actual = '';
90
+ let actual2 = '';
91
+ const app: express.Application = express();
92
+ app.use(createCorrelationIdMiddleware());
93
+ app.get('/', async (req, res, next) => {
94
+ try {
95
+ actual = correlationIdService.getId();
96
+ await delay(250);
97
+ actual2 = correlationIdService.getId();
98
+ } catch (e) {
99
+ next(e);
100
+ } finally {
101
+ res.end();
102
+ }
103
+ });
104
+
105
+ assert.isUndefined(correlationIdService.getId());
106
+ await request(app)
107
+ .get('/')
108
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
109
+ .send();
110
+
111
+ assert.isUndefined(correlationIdService.getId());
112
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
113
+ assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
114
+ });
115
+
116
+ it('should keep correlation ids in nested requests', async () => {
117
+ const testId: string = 'correlation-id-123';
118
+ const testId2: string = 'correlation-id-456';
119
+
120
+ let actual = '';
121
+ let actual2 = '';
122
+ let actual3 = '';
123
+ let actual4 = '';
124
+ let actual5 = '';
125
+ const app: express.Application = express();
126
+ app.use(createCorrelationIdMiddleware());
127
+ app.get('/', async (req, res, next) => {
128
+ try {
129
+ actual = correlationIdService.getId();
130
+ await delay(250);
131
+ actual2 = correlationIdService.getId();
132
+ await request(app)
133
+ .get('/foo')
134
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId2)
135
+ .send();
136
+ actual3 = correlationIdService.getId();
137
+ } catch (e) {
138
+ next(e);
139
+ } finally {
140
+ res.end();
141
+ }
142
+ });
143
+ app.get('/foo', async (req, res, next) => {
144
+ try {
145
+ actual4 = correlationIdService.getId();
146
+ await delay(250);
147
+ actual5 = correlationIdService.getId();
148
+ } catch (e) {
149
+ next(e);
150
+ } finally {
151
+ res.end();
152
+ }
153
+ });
154
+
155
+ assert.isUndefined(correlationIdService.getId());
156
+ await request(app)
157
+ .get('/')
158
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
159
+ .send();
160
+
161
+ assert.isUndefined(correlationIdService.getId());
162
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
163
+ assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
164
+ assert.strictEqual(actual3, testId, 'getId() should return id from x-correlation-id header of inbound request');
165
+ assert.strictEqual(actual4, testId2, 'getId() should return id from x-correlation-id header of inbound request');
166
+ assert.strictEqual(actual5, testId2, 'getId() should return id from x-correlation-id header of inbound request');
167
+ });
168
+
169
+ // tslint:disable: no-console
170
+ it('should keep correlation ids separated in parallel requests', async function() {
171
+ this.timeout(5000);
172
+ const testId: string = 'correlation-id-123';
173
+ const testId2: string = 'correlation-id-456';
174
+
175
+ let actual = '';
176
+ let actual2 = '';
177
+ let actual4 = '';
178
+ let actual5 = '';
179
+ let unlock: any;
180
+ const lock = new Promise(async (resolve, reject) => {
181
+ unlock = resolve;
182
+ });
183
+ const app: express.Application = express();
184
+ app.use(createCorrelationIdMiddleware());
185
+ app.get('/', async (req, res, next) => {
186
+ try {
187
+ actual = correlationIdService.getId();
188
+ console.log('start of req1', actual);
189
+ await lock;
190
+ actual2 = correlationIdService.getId();
191
+ console.log('end of req1', actual2);
192
+ } catch (e) {
193
+ next(e);
194
+ } finally {
195
+ res.end();
196
+ }
197
+ });
198
+ app.get('/foo', async (req, res, next) => {
199
+ try {
200
+ actual4 = correlationIdService.getId();
201
+ console.log('start of req2', actual4);
202
+ unlock();
203
+ await this.timeout(200);
204
+ actual5 = correlationIdService.getId();
205
+ console.log('end of req2', actual5);
206
+ } catch (e) {
207
+ next(e);
208
+ } finally {
209
+ res.end();
210
+ }
211
+ });
212
+
213
+ console.log('send req1');
214
+ assert.isUndefined(correlationIdService.getId());
215
+ const req1 = request(app)
216
+ .get('/')
217
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
218
+ .send();
219
+ console.log('send req2');
220
+ assert.isUndefined(correlationIdService.getId());
221
+ const req2 = request(app)
222
+ .get('/foo')
223
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId2)
224
+ .send();
225
+ await Promise.all([req1, req2]);
226
+ assert.isUndefined(correlationIdService.getId());
227
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
228
+ assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
229
+ assert.strictEqual(actual4, testId2, 'getId() should return id from x-correlation-id header of inbound request');
230
+ assert.strictEqual(actual5, testId2, 'getId() should return id from x-correlation-id header of inbound request');
231
+ });
232
+
233
+ it('should work with operations causing errors', async () => {
234
+ const testId: string = 'correlation-id-123';
235
+
236
+ let actual = '';
237
+ const app: express.Application = express();
238
+ app.use(createCorrelationIdMiddleware());
239
+ app.get('/', (req, res, next) => {
240
+ actual = correlationIdService.getId();
241
+ throw new Error('some error');
242
+ });
243
+
244
+ assert.isUndefined(correlationIdService.getId());
245
+ const result = await request(app)
246
+ .get('/')
247
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
248
+ .send();
249
+ assert.strictEqual(result.status, 500);
250
+ assert.isUndefined(correlationIdService.getId());
251
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
252
+ });
253
+
254
+ it('a filter can be specified', async () => {
255
+ const testId: string = 'correlation-id-123';
256
+
257
+ const filter = (req: express.Request): boolean => {
258
+ if (req.path.startsWith('/ok/')) {
259
+ return true;
260
+ }
261
+ return false;
262
+ };
263
+
264
+ const app: express.Application = express();
265
+ app.use(createCorrelationIdMiddleware(filter));
266
+
267
+ app.get('/ok/1', (req, res) => {
268
+ const actual = correlationIdService.getId();
269
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
270
+ res.end();
271
+ });
272
+ app.get('/ok/2', (req, res) => {
273
+ const actual = correlationIdService.getId();
274
+ assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
275
+ res.end();
276
+ });
277
+ app.get('/notok/1', (req, res) => {
278
+ const actual = correlationIdService.getId();
279
+ assert.isUndefined(actual);
280
+ res.end();
281
+ });
282
+
283
+ await request(app)
284
+ .get('/ok/1')
285
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
286
+ .send();
287
+
288
+ await request(app)
289
+ .get('/ok/2')
290
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
291
+ .send();
292
+
293
+ await request(app)
294
+ .get('/notok/1')
295
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
296
+ .send();
297
+ });
298
+
299
+ it('getCidInfo() cid received', async () => {
300
+ const testId: string = 'correlation-id-123';
301
+
302
+ const app: express.Application = express();
303
+ app.use(createCorrelationIdMiddleware());
304
+ app.get('/', (req, res) => {
305
+ const info = correlationIdService.getCidInfo(req);
306
+ assert.strictEqual(info.current, testId);
307
+ assert.strictEqual(info.receivedInRequest, testId);
308
+ assert.isUndefined(info.generated);
309
+
310
+ res.end();
311
+ });
312
+
313
+ await request(app)
314
+ .get('/')
315
+ .set(httpHeaderFieldsTyped.X_CORRELATION_ID, testId)
316
+ .send();
317
+ });
318
+
319
+ it('getCidInfo() cid generated', async () => {
320
+ const app: express.Application = express();
321
+ app.use(createCorrelationIdMiddleware());
322
+ app.get('/', (req, res) => {
323
+ const info = correlationIdService.getCidInfo(req);
324
+ assert.match(info.current, uuidMatcher);
325
+ assert.strictEqual(info.current, info.generated);
326
+ assert.isUndefined(info.receivedInRequest);
327
+
328
+ res.end();
329
+ });
330
+
331
+ await request(app)
332
+ .get('/')
333
+ .send();
334
+ });
335
+ });
@@ -0,0 +1,45 @@
1
+ import * as express from 'express';
2
+ import httpHeaderFieldsTyped from 'http-header-fields-typed';
3
+ import { constants } from '../config/constants';
4
+ import { correlationIdService } from '../services/correlationIdService';
5
+
6
+ /**
7
+ * Correlation ID Middleware
8
+ *
9
+ * @param filter a filter which is going to be called with the request to see if a
10
+ * colleration id scope must be managed or not.
11
+ */
12
+ export let createCorrelationIdMiddleware = (
13
+ filter?: (req: express.Request) => boolean
14
+ ): ((req: express.Request, res: express.Response, next: express.NextFunction) => Promise<void>) => {
15
+ const correlationIdMiddleware = (
16
+ req: express.Request,
17
+ res: express.Response,
18
+ next: express.NextFunction
19
+ ): Promise<void> => {
20
+ if (filter && !filter(req)) {
21
+ next();
22
+ } else {
23
+ // ==========================================
24
+ // If a Correlation ID (cid) exists in the request
25
+ // it will be used. Otherwise, a new one is created.
26
+ //
27
+ // We add the cid to the response!
28
+ // ==========================================
29
+ let correlationId = req.get(httpHeaderFieldsTyped.X_CORRELATION_ID);
30
+ if (!correlationId) {
31
+ correlationId = correlationIdService.createNewId();
32
+ req[constants.requestExtraVariables.cidNew] = correlationId;
33
+ } else {
34
+ req[constants.requestExtraVariables.cidReceivedInRequest] = correlationId;
35
+ }
36
+ if (!res.headersSent) {
37
+ res.set(httpHeaderFieldsTyped.X_CORRELATION_ID, correlationId);
38
+ }
39
+ correlationIdService.withId(next, correlationId);
40
+ }
41
+ return null;
42
+ };
43
+
44
+ return correlationIdMiddleware;
45
+ };
@@ -0,0 +1,255 @@
1
+ // tslint:disable max-func-body-length
2
+
3
+ import { assert } from 'chai';
4
+ import { EventEmitter } from 'events';
5
+ import { setTestingConfigurations } from '../utils/testingConfigurations';
6
+ import { correlationIdService } from './correlationIdService';
7
+
8
+ setTestingConfigurations();
9
+
10
+ const uuidMatcher: RegExp = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
11
+
12
+ async function timeout(work: (params?: any) => any, ms: number = 50) {
13
+ return new Promise<void>(resolve =>
14
+ setTimeout(() => {
15
+ work();
16
+ resolve();
17
+ }, ms)
18
+ );
19
+ }
20
+
21
+ describe('Correlation Id Service', () => {
22
+ describe('createNewId', () => {
23
+ it('should return UUID', () => {
24
+ const cid = correlationIdService.createNewId();
25
+ assert.match(cid, uuidMatcher);
26
+ });
27
+ });
28
+
29
+ describe('withId correlator', () => {
30
+ it('with sync function', () => {
31
+ // GIVEN
32
+ const expectedResult: string = '⭐';
33
+
34
+ // WHEN
35
+ const result = correlationIdService.withId(() => {
36
+ const actual = correlationIdService.getId();
37
+ assert.match(actual, uuidMatcher, 'getId() should return a uuid');
38
+ return expectedResult;
39
+ });
40
+
41
+ // THEN
42
+ assert.strictEqual(result, expectedResult);
43
+ });
44
+
45
+ it('with async function', async () => {
46
+ let done: boolean = false;
47
+
48
+ const promise = correlationIdService.withId(async () => {
49
+ await timeout(() => {
50
+ const actual = correlationIdService.getId();
51
+ assert.match(actual, uuidMatcher, 'getId() should return a uuid');
52
+ done = true;
53
+ });
54
+ });
55
+
56
+ // "withId" doesn't care about a promise to be floating or not
57
+ assert.isFalse(done);
58
+ await promise;
59
+ });
60
+
61
+ it('with supplied id', () => {
62
+ const testId = 'id-1';
63
+ correlationIdService.withId(() => {
64
+ const actual = correlationIdService.getId();
65
+ assert.strictEqual(actual, testId, 'getId() should return supplied id');
66
+ }, testId);
67
+ });
68
+
69
+ it('with bound emitter', () => {
70
+ // GIVEN
71
+ const emitter = new EventEmitter();
72
+ let receivedValue = 0;
73
+ let receivedCid = '';
74
+ emitter.on('test', value => {
75
+ receivedValue = value;
76
+ receivedCid = correlationIdService.getId();
77
+ });
78
+
79
+ // WHEN
80
+ let boundEmitter: EventEmitter;
81
+ correlationIdService.withId(() => {
82
+ boundEmitter = correlationIdService.bind(emitter);
83
+ assert.strictEqual(boundEmitter, emitter);
84
+ }, 'foo');
85
+
86
+ // THEN
87
+ boundEmitter.emit('test', 33);
88
+ assert.equal(receivedValue, 33);
89
+ assert.equal(receivedCid, 'foo');
90
+ });
91
+
92
+ it('with bound function', () => {
93
+ // GIVEN
94
+ const func = (msg: string) => msg + correlationIdService.getId();
95
+
96
+ // WHEN
97
+ let boundFunc: (msg: string) => string;
98
+ correlationIdService.withId(() => {
99
+ boundFunc = correlationIdService.bind(func);
100
+ }, 'foo');
101
+
102
+ // THEN
103
+ const result = boundFunc('Bar-');
104
+ assert.equal(result, 'Bar-foo');
105
+ });
106
+
107
+ it('with bound method', () => {
108
+ // GIVEN
109
+ const instance = {
110
+ title: 'Hello-',
111
+ say(msg: string): string {
112
+ return this.title + msg + correlationIdService.getId();
113
+ }
114
+ };
115
+
116
+ // WHEN
117
+ correlationIdService.withId(() => {
118
+ instance.say = correlationIdService.bind(instance.say);
119
+ }, 'foo');
120
+
121
+ // THEN
122
+ const result = instance.say('Bar-');
123
+ assert.equal(result, 'Hello-Bar-foo');
124
+ });
125
+
126
+ it('with resolved promise', async () => {
127
+ let done: boolean = false;
128
+
129
+ const promise = correlationIdService.withId(() =>
130
+ Promise.resolve(correlationIdService.getId()).then(id => {
131
+ assert.match(id, uuidMatcher, 'Promise should resolve correlation id');
132
+ done = true;
133
+ })
134
+ );
135
+
136
+ // "withId" doesn't care about a promise to be floating or not
137
+ assert.isFalse(done);
138
+ await promise;
139
+ });
140
+
141
+ it('with nested functions', () => {
142
+ correlationIdService.withId(() => {
143
+ const cid1 = correlationIdService.getId();
144
+ assert.match(cid1, uuidMatcher, 'correlationIdService.getId() should return a UUID');
145
+
146
+ correlationIdService.withId(() => {
147
+ const cid2 = correlationIdService.getId();
148
+ assert.notEqual(cid2, cid1, 'correlationIdService.getId() should return a different id for every scope');
149
+ assert.match(cid2, uuidMatcher, 'correlationIdService.getId() should return a UUID');
150
+ });
151
+
152
+ const cid3 = correlationIdService.getId();
153
+ assert.strictEqual(cid3, cid1, 'correlationIdService.getId() should return the same id for the same scope');
154
+ assert.match(cid3, uuidMatcher, 'correlationIdService.getId() should return a UUID');
155
+ });
156
+ });
157
+
158
+ it('with async function', async function() {
159
+ const duration = 25;
160
+ setSlowThreshold(this, duration);
161
+
162
+ // GIVEN
163
+ const expectedResult: string = '⭐';
164
+
165
+ // WHEN
166
+ const result = await correlationIdService.withId(async () => {
167
+ assert.equal(correlationIdService.getId(), 'foo');
168
+ await timeout(() => {
169
+ assert.equal(correlationIdService.getId(), 'foo');
170
+ }, duration);
171
+ assert.equal(correlationIdService.getId(), 'foo');
172
+ return expectedResult;
173
+ }, 'foo');
174
+
175
+ // THEN
176
+ assert.strictEqual(result, expectedResult);
177
+ });
178
+ });
179
+
180
+ describe('withIdAsync correlator', () => {
181
+ it('with async function', async function() {
182
+ const duration = 25;
183
+ setSlowThreshold(this, duration);
184
+
185
+ // GIVEN
186
+ const expectedResult: string = '⭐';
187
+
188
+ // WHEN
189
+ const result = await correlationIdService.withIdAsync(async () => {
190
+ assert.equal(correlationIdService.getId(), 'foo');
191
+ await timeout(() => {
192
+ assert.equal(correlationIdService.getId(), 'foo');
193
+ }, duration);
194
+ assert.equal(correlationIdService.getId(), 'foo');
195
+ return expectedResult;
196
+ }, 'foo');
197
+
198
+ // THEN
199
+ assert.strictEqual(result, expectedResult);
200
+ });
201
+
202
+ it('with error in callback', async () => {
203
+ try {
204
+ await correlationIdService.withIdAsync(async () => {
205
+ assert.equal(correlationIdService.getId(), 'foo');
206
+ throw new Error('some error...');
207
+ }, 'foo');
208
+ assert.fail('expected error');
209
+ } catch (err) {
210
+ assert.equal(err.message, 'some error...');
211
+ }
212
+ });
213
+
214
+ it('with error after await', async function() {
215
+ const duration = 25;
216
+ setSlowThreshold(this, duration);
217
+
218
+ try {
219
+ await correlationIdService.withIdAsync(async () => {
220
+ assert.equal(correlationIdService.getId(), 'foo');
221
+ // tslint:disable-next-line: no-empty
222
+ await timeout(() => {}, duration);
223
+ throw new Error('some error...');
224
+ }, 'foo');
225
+ assert.fail('expected error');
226
+ } catch (err) {
227
+ assert.equal(err.message, 'some error...');
228
+ }
229
+ });
230
+
231
+ it('with nested async functions', async function() {
232
+ const duration = 25;
233
+ setSlowThreshold(this, 2 * duration);
234
+
235
+ await correlationIdService.withIdAsync(async () => {
236
+ assert.equal(correlationIdService.getId(), 'foo');
237
+ await timeout(async () => {
238
+ await correlationIdService.withIdAsync(async () => {
239
+ await timeout(() => {
240
+ assert.equal(correlationIdService.getId(), 'bar');
241
+ }, duration);
242
+ }, 'bar');
243
+ }, duration);
244
+ assert.equal(correlationIdService.getId(), 'foo');
245
+ }, 'foo');
246
+ });
247
+ });
248
+
249
+ function setSlowThreshold(context: Mocha.Context, expectedTestDuration: number) {
250
+ // Cf. https://mochajs.org/#test-duration
251
+ // 10: budgeted test case own processing time
252
+ // ×2: for the estimation to sit around "slow/2" in Mocha scale (and no warning shows up)
253
+ context.slow((expectedTestDuration + 10) * 2);
254
+ }
255
+ });