Skip to content

Commit

Permalink
Make it idempotent to capturePromise (#400)
Browse files Browse the repository at this point in the history
* Make it idempotent to capturePromise

Add uncapturePromise function in order to cancel patch in tests.

fix #398

* Move Move cleanup after the assertion

To ensure it's executed after the test will execute.

* Change setup process for process_p.test.js

To assure variables reference to original `then` and `catch` function.
  • Loading branch information
fossamagna authored Apr 7, 2021
1 parent 781e1a2 commit 712464f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 21 deletions.
49 changes: 36 additions & 13 deletions packages/core/lib/patchers/promise_p.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,29 @@

const contextUtils = require('../context_utils');

const originalThen = Symbol('original then');
const originalCatch = Symbol('original catch');

function patchPromise(Promise) {
const then = Promise.prototype.then;
Promise.prototype.then = function(onFulfilled, onRejected) {
if (contextUtils.isAutomaticMode()
&& tryGetCurrentSegment()
) {
const ns = contextUtils.getNamespace();

onFulfilled = onFulfilled && ns.bind(onFulfilled);
onRejected = onRejected && ns.bind(onRejected);
}

return then.call(this, onFulfilled, onRejected);
};
if (!then[originalThen]) {
Promise.prototype.then = function(onFulfilled, onRejected) {
if (contextUtils.isAutomaticMode()
&& tryGetCurrentSegment()
) {
const ns = contextUtils.getNamespace();

onFulfilled = onFulfilled && ns.bind(onFulfilled);
onRejected = onRejected && ns.bind(onRejected);
}

return then.call(this, onFulfilled, onRejected);
};
Promise.prototype.then[originalThen] = then;
}

const origCatch = Promise.prototype.catch;
if (origCatch) {
if (origCatch && !origCatch[originalCatch]) {
Promise.prototype.catch = function (onRejected) {
if (contextUtils.isAutomaticMode()
&& tryGetCurrentSegment()
Expand All @@ -37,6 +43,18 @@ function patchPromise(Promise) {

return origCatch.call(this, onRejected);
};
Promise.prototype.catch[originalCatch] = origCatch;
}
}

function unpatchPromise(Promise) {
const then = Promise.prototype.then;
if (then[originalThen]) {
Promise.prototype.then = then[originalThen];
}
const origCatch = Promise.prototype.catch;
if (origCatch && origCatch[originalCatch]) {
Promise.prototype.catch = origCatch[originalCatch];
}
}

Expand All @@ -52,6 +70,11 @@ function capturePromise() {
patchPromise(Promise);
}

function uncapturePromise() {
unpatchPromise(Promise);
}

capturePromise.patchThirdPartyPromise = patchPromise;

module.exports.capturePromise = capturePromise;
module.exports.uncapturePromise = uncapturePromise;
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ var server = http
// setTimeout so the assertion isn't caught by the promise
setTimeout(function() {
assert.equal(segment.id, retrievedSegment.id);
// Cancel the patch because it doesn't affect other tests
require('../../lib/patchers/promise_p').uncapturePromise();
});
});
});
Expand Down
31 changes: 23 additions & 8 deletions packages/core/test/unit/patchers/promise_p.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
const expect = require('chai').expect;
const sinon = require('sinon');

const { capturePromise } = require('../../../lib/patchers/promise_p');
const { capturePromise, uncapturePromise } = require('../../../lib/patchers/promise_p');
const contextUtils = require('../../../lib/context_utils');

const origThen = Promise.prototype.then;
const origCatch = Promise.prototype.catch;

let origThen;
let origCatch;
let getNamespaceStub;
let isAutomaticModeStub;
let getSegmentStub;
Expand All @@ -26,14 +25,16 @@ beforeEach(() => {

beforeEach(() => {
sinon.restore();
Promise.prototype.then = origThen;
Promise.prototype.catch = origCatch;
uncapturePromise();
origThen = Promise.prototype.then;
origCatch = Promise.prototype.catch;
});

after(() => {
sinon.restore();
Promise.prototype.then = origThen;
Promise.prototype.catch = origCatch;
uncapturePromise();
origThen = Promise.prototype.then;
origCatch = Promise.prototype.catch;
});

function verifyBindings (segment, isAutomaticMode, onFulfilled, onRejected) {
Expand Down Expand Up @@ -125,6 +126,20 @@ describe('capturePromise', () => {
});
createTests(true);
});

it('should be idempotent', async () => {
capturePromise();
const thenFirst = Promise.prototype.then;
const catchFirst = Promise.prototype.catch;
capturePromise();
const thenSecond = Promise.prototype.then;
const catchSecond = Promise.prototype.catch;
capturePromise();
expect(Promise.prototype.then).to.equal(thenFirst);
expect(Promise.prototype.catch).to.equal(catchFirst);
expect(Promise.prototype.then).to.equal(thenSecond);
expect(Promise.prototype.catch).to.equal(catchSecond);
});
});

describe('capturePromise.patchThirdPartyPromise', () => {
Expand Down

0 comments on commit 712464f

Please sign in to comment.