From a13a04a7e9702e56f29dfba8926a30c925190f8a Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Tue, 11 Jan 2022 12:58:41 -0800 Subject: [PATCH] RTD module: allow submodules to setBidRequestData without `waitForIt` (#7862) This change allows all RTD submodules at least one shot to see the `setBidRequestData` hook even if they are not flagged `waitForIt` (previously they would not be run at all in some cases). Addresses https://github.com/prebid/Prebid.js/issues/7117 --- modules/rtdModule/index.js | 15 +++--- test/spec/modules/realTimeDataModule_spec.js | 53 +++++++++++++++++++- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/modules/rtdModule/index.js b/modules/rtdModule/index.js index 67326e7d887..6c88d66999a 100644 --- a/modules/rtdModule/index.js +++ b/modules/rtdModule/index.js @@ -291,18 +291,12 @@ export function setBidRequestsData(fn, reqBidsConfigObj) { return exitHook(); } - if (shouldDelayAuction) { - waitTimeout = setTimeout(exitHook, _moduleConfig.auctionDelay); - } + waitTimeout = setTimeout(exitHook, shouldDelayAuction ? _moduleConfig.auctionDelay : 0); relevantSubModules.forEach(sm => { sm.getBidRequestData(reqBidsConfigObj, onGetBidRequestDataCallback.bind(sm), sm.config, _userConsent) }); - if (!shouldDelayAuction) { - return exitHook(); - } - function onGetBidRequestDataCallback() { if (isDone) { return; @@ -310,12 +304,15 @@ export function setBidRequestsData(fn, reqBidsConfigObj) { if (this.config && this.config.waitForIt) { callbacksExpected--; } - if (callbacksExpected <= 0) { - return exitHook(); + if (callbacksExpected === 0) { + setTimeout(exitHook, 0); } } function exitHook() { + if (isDone) { + return; + } isDone = true; clearTimeout(waitTimeout); fn.call(this, reqBidsConfigObj); diff --git a/test/spec/modules/realTimeDataModule_spec.js b/test/spec/modules/realTimeDataModule_spec.js index 6538dec37c4..11639733661 100644 --- a/test/spec/modules/realTimeDataModule_spec.js +++ b/test/spec/modules/realTimeDataModule_spec.js @@ -141,7 +141,56 @@ describe('Real time module', function () { const adUnits = rtdModule.getAdUnitTargeting(auction); assert.deepEqual(expectedAdUnits, adUnits) done(); - }) + }); + + describe('setBidRequestData', () => { + let withWait, withoutWait; + + function runSetBidRequestData() { + return new Promise((resolve) => { + rtdModule.setBidRequestsData(resolve, {bidRequest: {}}); + }); + } + + beforeEach(() => { + withWait = { + submod: validSMWait, + cbTime: 0, + cbRan: false + }; + withoutWait = { + submod: validSM, + cbTime: 0, + cbRan: false + }; + + [withWait, withoutWait].forEach((c) => { + c.submod.getBidRequestData = sinon.stub().callsFake((_, cb) => { + setTimeout(() => { + c.cbRan = true; + cb(); + }, c.cbTime); + }); + }); + }); + + it('should allow non-priority submodules to run synchronously', () => { + withWait.cbTime = withoutWait.cbTime = 0; + return runSetBidRequestData().then(() => { + expect(withWait.cbRan).to.be.true; + expect(withoutWait.cbRan).to.be.true; + }) + }); + + it('should not wait for non-priority submodules if priority ones complete first', () => { + withWait.cbTime = 10; + withoutWait.cbTime = 100; + return runSetBidRequestData().then(() => { + expect(withWait.cbRan).to.be.true; + expect(withoutWait.cbRan).to.be.false; + }); + }); + }); }); it('deep merge object', function () { @@ -255,5 +304,5 @@ describe('Real time module', function () { expect(providers[1][hook].called).to.be.true; }); }); - }) + }); });