diff --git a/src/auction.js b/src/auction.js index 7c6a752c057..2a4cc128c2a 100644 --- a/src/auction.js +++ b/src/auction.js @@ -147,14 +147,24 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } function done(bidRequestId) { - var innerBidRequestId = bidRequestId; + const innerBidRequestId = bidRequestId; return delayExecution(function() { - let request = find(_bidderRequests, (bidRequest) => { + const request = find(_bidderRequests, (bidRequest) => { return innerBidRequestId === bidRequest.bidderRequestId; }); - request.doneCbCallCount += 1; - // In case of mediaType video and prebidCache enabled, call bidsBackHandler after cache is stored. - if ((request.bids.filter(videoAdUnit).length == 0) || (request.bids.filter(videoAdUnit).length > 0 && !config.getConfig('cache.url'))) { + + const nonVideoBid = request.bids.filter(videoAdUnit).length === 0; + const videoBid = request.bids.filter(videoAdUnit).length > 0; + const videoBidNoCache = videoBid && !config.getConfig('cache.url'); + const videoBidWithCache = videoBid && config.getConfig('cache.url'); + + // video bids with cache enabled need to be cached first before saying they are done + if (!videoBidWithCache) { + request.doneCbCallCount += 1; + } + + // in case of mediaType video and prebidCache enabled, call bidsBackHandler after cache is stored. + if (nonVideoBid || videoBidNoCache) { bidsBackAll() } }, 1); @@ -216,7 +226,9 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid let bidRequests = auctionInstance.getBidRequests(); let auctionId = auctionInstance.getAuctionId(); - let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequests, auctionId}); + let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); + if (bidResponse.mediaType === 'video') { tryAddVideoBid(bidResponse); } else { @@ -247,6 +259,8 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid if (!bid.vastUrl) { bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } + // only set this prop after the bid has been cached to avoid early ending auction early in bidsBackAll + bidRequest.doneCbCallCount += 1; addBidToAuction(bidResponse); auctionInstance.bidsBackAll(); } @@ -261,9 +275,7 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid // Postprocess the bids so that all the universal properties exist, no matter which bidder they came from. // This should be called before addBidToAuction(). -function getPreparedBidForAuction({adUnitCode, bid, bidRequests, auctionId}) { - let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); - +function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { const start = bidRequest.start; let bidObject = Object.assign({}, bid, { diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 688afc35d9d..3429087a24f 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -4,6 +4,8 @@ import CONSTANTS from 'src/constants.json'; import { adjustBids } from 'src/auction'; import * as auctionModule from 'src/auction'; import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +import * as store from 'src/videoCache'; import * as ajaxLib from 'src/ajax'; var assert = require('assert'); @@ -870,5 +872,32 @@ describe('auctionmanager.js', function () { assert.notEqual(addedBid2.adId, bids1[0].requestId); assert.equal(length, 1); }); + + it('should run auction after video bids have been cached', () => { + sinon.stub(store, 'store').callsArgWith(1, null, [{ uuid: 123}]); + sinon.stub(config, 'getConfig').withArgs('cache.url').returns('cache-url'); + + const bidsCopy = [Object.assign({}, bids[0], { mediaType: 'video'})]; + const bids1Copy = [Object.assign({}, bids1[0], { mediaType: 'video'})]; + + registerBidder(spec); + registerBidder(spec1); + + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bidsCopy); + + spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec1.isBidRequestValid.returns(true); + spec1.interpretResponse.returns(bids1Copy); + + auction.callBids(); + + assert.equal(auction.getBidsReceived().length, 2); + assert.equal(auction.getAuctionStatus(), 'completed'); + + config.getConfig.restore(); + store.store.restore(); + }); }); });