UNPKG

@villedemontreal/correlation-id

Version:

Express middleware to set a correlation in Express. The correlation id will be consistent across async calls within the handling of a request.

213 lines 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = require("chai"); const events_1 = require("events"); const testingConfigurations_1 = require("../utils/testingConfigurations"); const correlationIdService_1 = require("./correlationIdService"); (0, testingConfigurations_1.setTestingConfigurations)(); const uuidMatcher = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/; async function timeout(work, ms = 50) { return new Promise((resolve) => setTimeout(() => { work(); resolve(); }, ms)); } describe('Correlation Id Service', () => { describe('createNewId', () => { it('should return UUID', () => { const cid = correlationIdService_1.correlationIdService.createNewId(); chai_1.assert.match(cid, uuidMatcher); }); }); describe('withId correlator', () => { it('with sync function', () => { // GIVEN const expectedResult = '⭐'; // WHEN const result = correlationIdService_1.correlationIdService.withId(() => { const actual = correlationIdService_1.correlationIdService.getId(); chai_1.assert.match(actual, uuidMatcher, 'getId() should return a uuid'); return expectedResult; }); // THEN chai_1.assert.strictEqual(result, expectedResult); }); it('with async function', async () => { let done = false; const promise = correlationIdService_1.correlationIdService.withId(async () => { await timeout(() => { const actual = correlationIdService_1.correlationIdService.getId(); chai_1.assert.match(actual, uuidMatcher, 'getId() should return a uuid'); done = true; }); }); // "withId" doesn't care about a promise to be floating or not chai_1.assert.isFalse(done); await promise; }); it('with supplied id', () => { const testId = 'id-1'; correlationIdService_1.correlationIdService.withId(() => { const actual = correlationIdService_1.correlationIdService.getId(); chai_1.assert.strictEqual(actual, testId, 'getId() should return supplied id'); }, testId); }); it('with bound emitter', () => { // GIVEN const emitter = new events_1.EventEmitter(); let receivedValue = 0; let receivedCid = ''; emitter.on('test', (value) => { receivedValue = value; receivedCid = correlationIdService_1.correlationIdService.getId(); }); // WHEN let boundEmitter; correlationIdService_1.correlationIdService.withId(() => { boundEmitter = correlationIdService_1.correlationIdService.bind(emitter); chai_1.assert.strictEqual(boundEmitter, emitter); }, 'foo'); // THEN boundEmitter.emit('test', 33); chai_1.assert.equal(receivedValue, 33); chai_1.assert.equal(receivedCid, 'foo'); }); it('with bound function', () => { // GIVEN const func = (msg) => msg + correlationIdService_1.correlationIdService.getId(); // WHEN let boundFunc; correlationIdService_1.correlationIdService.withId(() => { boundFunc = correlationIdService_1.correlationIdService.bind(func); }, 'foo'); // THEN const result = boundFunc('Bar-'); chai_1.assert.equal(result, 'Bar-foo'); }); it('with bound method', () => { // GIVEN const instance = { title: 'Hello-', say(msg) { return this.title + msg + correlationIdService_1.correlationIdService.getId(); }, }; // WHEN correlationIdService_1.correlationIdService.withId(() => { instance.say = correlationIdService_1.correlationIdService.bind(instance.say); }, 'foo'); // THEN const result = instance.say('Bar-'); chai_1.assert.equal(result, 'Hello-Bar-foo'); }); it('with resolved promise', async () => { let done = false; const promise = correlationIdService_1.correlationIdService.withId(() => Promise.resolve(correlationIdService_1.correlationIdService.getId()).then((id) => { chai_1.assert.match(id, uuidMatcher, 'Promise should resolve correlation id'); done = true; })); // "withId" doesn't care about a promise to be floating or not chai_1.assert.isFalse(done); await promise; }); it('with nested functions', () => { correlationIdService_1.correlationIdService.withId(() => { const cid1 = correlationIdService_1.correlationIdService.getId(); chai_1.assert.match(cid1, uuidMatcher, 'correlationIdService.getId() should return a UUID'); correlationIdService_1.correlationIdService.withId(() => { const cid2 = correlationIdService_1.correlationIdService.getId(); chai_1.assert.notEqual(cid2, cid1, 'correlationIdService.getId() should return a different id for every scope'); chai_1.assert.match(cid2, uuidMatcher, 'correlationIdService.getId() should return a UUID'); }); const cid3 = correlationIdService_1.correlationIdService.getId(); chai_1.assert.strictEqual(cid3, cid1, 'correlationIdService.getId() should return the same id for the same scope'); chai_1.assert.match(cid3, uuidMatcher, 'correlationIdService.getId() should return a UUID'); }); }); it('with async function', async function () { const duration = 25; setSlowThreshold(this, duration); // GIVEN const expectedResult = '⭐'; // WHEN const result = await correlationIdService_1.correlationIdService.withId(async () => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); await timeout(() => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); }, duration); chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); return expectedResult; }, 'foo'); // THEN chai_1.assert.strictEqual(result, expectedResult); }); }); describe('withIdAsync correlator', () => { it('with async function', async function () { const duration = 25; setSlowThreshold(this, duration); // GIVEN const expectedResult = '⭐'; // WHEN const result = await correlationIdService_1.correlationIdService.withIdAsync(async () => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); await timeout(() => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); }, duration); chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); return expectedResult; }, 'foo'); // THEN chai_1.assert.strictEqual(result, expectedResult); }); it('with error in callback', async () => { try { await correlationIdService_1.correlationIdService.withIdAsync(async () => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); throw new Error('some error...'); }, 'foo'); chai_1.assert.fail('expected error'); } catch (err) { chai_1.assert.equal(err.message, 'some error...'); } }); it('with error after await', async function () { const duration = 25; setSlowThreshold(this, duration); try { await correlationIdService_1.correlationIdService.withIdAsync(async () => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); await timeout(() => { }, duration); throw new Error('some error...'); }, 'foo'); chai_1.assert.fail('expected error'); } catch (err) { chai_1.assert.equal(err.message, 'some error...'); } }); it('with nested async functions', async function () { const duration = 25; setSlowThreshold(this, 2 * duration); await correlationIdService_1.correlationIdService.withIdAsync(async () => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); await timeout(async () => { await correlationIdService_1.correlationIdService.withIdAsync(async () => { await timeout(() => { chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'bar'); }, duration); }, 'bar'); }, duration); chai_1.assert.equal(correlationIdService_1.correlationIdService.getId(), 'foo'); }, 'foo'); }); }); function setSlowThreshold(context, expectedTestDuration) { // Cf. https://mochajs.org/#test-duration // 10: budgeted test case own processing time // ×2: for the estimation to sit around "slow/2" in Mocha scale (and no warning shows up) context.slow((expectedTestDuration + 10) * 2); } }); //# sourceMappingURL=correlationIdService.test.js.map