prebid.js 6.7.0 → 6.11.0

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 (160) hide show
  1. package/.eslintrc.js +8 -1
  2. package/integrationExamples/gpt/{haloRtdProvider_example.html → hadronRtdProvider_example.html} +9 -9
  3. package/integrationExamples/gpt/idImportLibrary_example.html +2 -2
  4. package/integrationExamples/gpt/userId_example.html +2 -2
  5. package/integrationExamples/gpt/weboramaRtdProvider_example.html +154 -115
  6. package/integrationExamples/gpt/x-domain/creative.html +63 -29
  7. package/modules/.submodules.json +3 -0
  8. package/modules/adagioBidAdapter.js +0 -8
  9. package/modules/adagioBidAdapter.md +1 -1
  10. package/modules/adkernelBidAdapter.js +2 -1
  11. package/modules/adnuntiusRtdProvider.js +96 -0
  12. package/modules/adnuntiusRtdProvider.md +41 -0
  13. package/modules/adotBidAdapter.js +516 -567
  14. package/modules/adotBidAdapter.md +6 -44
  15. package/modules/adpod.js +12 -14
  16. package/modules/adyoulikeBidAdapter.js +2 -0
  17. package/modules/appnexusBidAdapter.js +14 -2
  18. package/modules/asealBidAdapter.js +58 -0
  19. package/modules/asealBidAdapter.md +52 -0
  20. package/modules/brandmetricsRtdProvider.js +168 -0
  21. package/modules/brandmetricsRtdProvider.md +40 -0
  22. package/modules/conversantBidAdapter.js +7 -0
  23. package/modules/criteoBidAdapter.js +9 -0
  24. package/modules/currency.js +27 -5
  25. package/modules/displayioBidAdapter.js +157 -0
  26. package/modules/displayioBidAdapter.md +148 -0
  27. package/modules/dspxBidAdapter.js +69 -29
  28. package/modules/dspxBidAdapter.md +2 -1
  29. package/modules/e_volutionBidAdapter.js +158 -0
  30. package/modules/gridBidAdapter.js +15 -1
  31. package/modules/gumgumBidAdapter.js +52 -38
  32. package/modules/hadronIdSystem.js +96 -0
  33. package/modules/hadronIdSystem.md +35 -0
  34. package/modules/hadronRtdProvider.js +254 -0
  35. package/modules/hadronRtdProvider.md +126 -0
  36. package/modules/haloIdSystem.md +4 -35
  37. package/modules/haloRtdProvider.md +3 -126
  38. package/modules/imRtdProvider.js +10 -0
  39. package/modules/improvedigitalBidAdapter.js +5 -0
  40. package/modules/interactiveOffersBidAdapter.js +9 -6
  41. package/modules/iqzoneBidAdapter.js +10 -3
  42. package/modules/iqzoneBidAdapter.md +16 -0
  43. package/modules/ixBidAdapter.js +2 -6
  44. package/modules/kubientBidAdapter.js +50 -19
  45. package/modules/lunamediahbBidAdapter.js +32 -4
  46. package/modules/malltvBidAdapter.js +7 -3
  47. package/modules/malltvBidAdapter.md +64 -51
  48. package/modules/mass.js +3 -5
  49. package/modules/mediakeysBidAdapter.js +0 -5
  50. package/modules/medianetAnalyticsAdapter.js +1 -1
  51. package/modules/mediasquareBidAdapter.js +9 -1
  52. package/modules/nextMillenniumBidAdapter.js +1 -0
  53. package/modules/oguryBidAdapter.js +7 -14
  54. package/modules/prebidServerBidAdapter/index.js +61 -39
  55. package/modules/priceFloors.js +20 -12
  56. package/modules/pubmaticBidAdapter.js +1 -1
  57. package/modules/richaudienceBidAdapter.js +8 -3
  58. package/modules/riseBidAdapter.js +17 -6
  59. package/modules/rtbhouseBidAdapter.js +2 -0
  60. package/modules/rubiconAnalyticsAdapter.js +5 -0
  61. package/modules/rubiconBidAdapter.js +2 -2
  62. package/modules/sizeMappingV2.js +1 -8
  63. package/modules/sortableAnalyticsAdapter.js +5 -4
  64. package/modules/sovrnBidAdapter.js +93 -18
  65. package/modules/sovrnBidAdapter.md +80 -2
  66. package/modules/sspBCBidAdapter.js +53 -20
  67. package/modules/telariaBidAdapter.js +22 -29
  68. package/modules/trustpidSystem.js +197 -0
  69. package/modules/trustpidSystem.md +45 -0
  70. package/modules/undertoneBidAdapter.js +17 -1
  71. package/modules/userId/eids.js +16 -1
  72. package/modules/userId/eids.md +10 -2
  73. package/modules/userId/userId.md +17 -2
  74. package/modules/vibrantmediaBidAdapter.js +220 -0
  75. package/modules/vibrantmediaBidAdapter.md +92 -0
  76. package/modules/vidoomyBidAdapter.js +8 -0
  77. package/modules/vidoomyBidAdapter.md +4 -2
  78. package/modules/weboramaRtdProvider.js +264 -34
  79. package/modules/weboramaRtdProvider.md +110 -40
  80. package/modules/yahoosspBidAdapter.js +3 -1
  81. package/modules/yieldoneBidAdapter.js +6 -0
  82. package/package.json +2 -1
  83. package/src/adRendering.js +38 -0
  84. package/src/adapterManager.js +24 -19
  85. package/src/adapters/bidderFactory.js +14 -11
  86. package/src/adloader.js +2 -1
  87. package/src/auction.js +138 -115
  88. package/src/auctionIndex.js +85 -0
  89. package/src/auctionManager.js +3 -0
  90. package/src/bidderSettings.js +69 -0
  91. package/src/bidfactory.js +18 -6
  92. package/src/native.js +29 -21
  93. package/src/prebid.js +3 -19
  94. package/src/secureCreatives.js +128 -45
  95. package/src/targeting.js +11 -2
  96. package/src/utils.js +14 -17
  97. package/src/video.js +10 -11
  98. package/src/videoCache.js +10 -9
  99. package/test/fixtures/fixtures.js +2 -1
  100. package/test/helpers/indexStub.js +28 -0
  101. package/test/helpers/syncPromise.js +71 -0
  102. package/test/spec/auctionmanager_spec.js +268 -89
  103. package/test/spec/config_spec.js +24 -1
  104. package/test/spec/modules/adagioBidAdapter_spec.js +0 -10
  105. package/test/spec/modules/adnuntiusRtdProvider_spec.js +145 -0
  106. package/test/spec/modules/adotBidAdapter_spec.js +294 -3124
  107. package/test/spec/modules/adpod_spec.js +91 -156
  108. package/test/spec/modules/adyoulikeBidAdapter_spec.js +4 -0
  109. package/test/spec/modules/appnexusBidAdapter_spec.js +27 -0
  110. package/test/spec/modules/asealBidAdapter_spec.js +144 -0
  111. package/test/spec/modules/brandmetricsRtdProvider_spec.js +191 -0
  112. package/test/spec/modules/conversantBidAdapter_spec.js +54 -2
  113. package/test/spec/modules/criteoBidAdapter_spec.js +21 -0
  114. package/test/spec/modules/currency_spec.js +36 -15
  115. package/test/spec/modules/displayioBidAdapter_spec.js +239 -0
  116. package/test/spec/modules/dspxBidAdapter_spec.js +20 -15
  117. package/test/spec/modules/e_volutionBidAdapter_spec.js +242 -0
  118. package/test/spec/modules/eids_spec.js +2 -2
  119. package/test/spec/modules/gridBidAdapter_spec.js +18 -0
  120. package/test/spec/modules/gumgumBidAdapter_spec.js +49 -3
  121. package/test/spec/modules/hadronIdSystem_spec.js +57 -0
  122. package/test/spec/modules/hadronRtdProvider_spec.js +762 -0
  123. package/test/spec/modules/imRtdProvider_spec.js +30 -1
  124. package/test/spec/modules/improvedigitalBidAdapter_spec.js +19 -0
  125. package/test/spec/modules/iqzoneBidAdapter_spec.js +1 -0
  126. package/test/spec/modules/ixBidAdapter_spec.js +1 -1
  127. package/test/spec/modules/kubientBidAdapter_spec.js +182 -84
  128. package/test/spec/modules/lunamediahbBidAdapter_spec.js +27 -1
  129. package/test/spec/modules/mass_spec.js +2 -14
  130. package/test/spec/modules/mediakeysBidAdapter_spec.js +9 -5
  131. package/test/spec/modules/mediasquareBidAdapter_spec.js +25 -1
  132. package/test/spec/modules/oguryBidAdapter_spec.js +63 -5
  133. package/test/spec/modules/prebidServerBidAdapter_spec.js +43 -6
  134. package/test/spec/modules/priceFloors_spec.js +83 -24
  135. package/test/spec/modules/pubmaticBidAdapter_spec.js +40 -0
  136. package/test/spec/modules/riseBidAdapter_spec.js +30 -4
  137. package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +31 -1
  138. package/test/spec/modules/rubiconBidAdapter_spec.js +1 -1
  139. package/test/spec/modules/sortableAnalyticsAdapter_spec.js +2 -3
  140. package/test/spec/modules/sovrnBidAdapter_spec.js +413 -333
  141. package/test/spec/modules/sspBCBidAdapter_spec.js +7 -7
  142. package/test/spec/modules/telariaBidAdapter_spec.js +1 -3
  143. package/test/spec/modules/trustpidSystem_spec.js +232 -0
  144. package/test/spec/modules/undertoneBidAdapter_spec.js +55 -2
  145. package/test/spec/modules/userId_spec.js +39 -39
  146. package/test/spec/modules/vibrantmediaBidAdapter_spec.js +1237 -0
  147. package/test/spec/modules/vidoomyBidAdapter_spec.js +7 -1
  148. package/test/spec/modules/weboramaRtdProvider_spec.js +536 -20
  149. package/test/spec/modules/yahoosspBidAdapter_spec.js +10 -0
  150. package/test/spec/modules/yieldoneBidAdapter_spec.js +33 -0
  151. package/test/spec/native_spec.js +62 -40
  152. package/test/spec/unit/core/adapterManager_spec.js +22 -0
  153. package/test/spec/unit/core/auctionIndex_spec.js +129 -0
  154. package/test/spec/unit/core/bidderFactory_spec.js +65 -12
  155. package/test/spec/unit/core/bidderSettings_spec.js +123 -0
  156. package/test/spec/unit/core/targeting_spec.js +93 -0
  157. package/test/spec/unit/pbjs_api_spec.js +80 -42
  158. package/test/spec/unit/secureCreatives_spec.js +143 -24
  159. package/test/spec/videoCache_spec.js +18 -19
  160. package/test/spec/video_spec.js +51 -61
@@ -4,6 +4,8 @@ import {
4
4
  AUCTION_COMPLETED,
5
5
  adjustBids,
6
6
  getMediaTypeGranularity,
7
+ getPriceByGranularity,
8
+ addBidResponse
7
9
  } from 'src/auction.js';
8
10
  import CONSTANTS from 'src/constants.json';
9
11
  import * as auctionModule from 'src/auction.js';
@@ -14,6 +16,12 @@ import * as store from 'src/videoCache.js';
14
16
  import * as ajaxLib from 'src/ajax.js';
15
17
  import find from 'core-js-pure/features/array/find.js';
16
18
  import { server } from 'test/mocks/xhr.js';
19
+ import {hook} from '../../src/hook.js';
20
+ import {auctionManager} from '../../src/auctionManager.js';
21
+ import 'src/debugging.js' // some tests look for debugging side effects
22
+ import {AuctionIndex} from '../../src/auctionIndex.js';
23
+ import {expect} from 'chai';
24
+ import {synchronizePromise} from '../helpers/syncPromise.js';
17
25
 
18
26
  var assert = require('assert');
19
27
 
@@ -45,6 +53,7 @@ function mockBid(opts) {
45
53
  'height': 250,
46
54
  'bidderCode': bidderCode || BIDDER_CODE,
47
55
  'requestId': utils.getUniqueIdentifierStr(),
56
+ 'transactionId': (opts && opts.transactionId) || ADUNIT_CODE,
48
57
  'creativeId': 'id',
49
58
  'currency': 'USD',
50
59
  'netRevenue': true,
@@ -75,7 +84,7 @@ function mockBidRequest(bid, opts) {
75
84
 
76
85
  return {
77
86
  'bidderCode': bidderCode || bid.bidderCode,
78
- 'auctionId': '20882439e3238c',
87
+ 'auctionId': opts && opts.auctionId,
79
88
  'bidderRequestId': requestId,
80
89
  'bids': [
81
90
  {
@@ -84,10 +93,11 @@ function mockBidRequest(bid, opts) {
84
93
  'placementId': 'id'
85
94
  },
86
95
  'adUnitCode': adUnitCode || ADUNIT_CODE,
96
+ 'transactionId': bid.transactionId,
87
97
  'sizes': [[300, 250], [300, 600]],
88
98
  'bidId': bid.requestId,
89
99
  'bidderRequestId': requestId,
90
- 'auctionId': '20882439e3238c',
100
+ 'auctionId': opts && opts.auctionId,
91
101
  'mediaTypes': mediaType
92
102
  }
93
103
  ],
@@ -124,6 +134,31 @@ function mockAjaxBuilder() {
124
134
  }
125
135
 
126
136
  describe('auctionmanager.js', function () {
137
+ let indexAuctions, indexStub, promiseSandbox;
138
+
139
+ before(() => {
140
+ // hooks are global and their side effects depend on what has been loaded
141
+ [
142
+ auctionModule.addBidResponse,
143
+ auctionModule.addBidderRequests,
144
+ auctionModule.bidsBackCallback
145
+ ].forEach((h) => h.getHooks().remove())
146
+ hook.ready();
147
+ });
148
+
149
+ beforeEach(() => {
150
+ indexAuctions = [];
151
+ indexStub = sinon.stub(auctionManager, 'index');
152
+ indexStub.get(() => new AuctionIndex(() => indexAuctions));
153
+ promiseSandbox = sinon.createSandbox();
154
+ synchronizePromise(promiseSandbox);
155
+ });
156
+
157
+ afterEach(() => {
158
+ indexStub.restore();
159
+ promiseSandbox.restore();
160
+ });
161
+
127
162
  describe('getKeyValueTargetingPairs', function () {
128
163
  const DEFAULT_BID = {
129
164
  cpm: 5.578,
@@ -647,14 +682,14 @@ describe('auctionmanager.js', function () {
647
682
  });
648
683
  });
649
684
 
650
- describe('addBidResponse', function () {
685
+ describe('addBidResponse #1', function () {
651
686
  let createAuctionStub;
652
687
  let adUnits;
653
688
  let adUnitCodes;
654
689
  let spec;
655
690
  let auction;
656
691
  let ajaxStub;
657
- let bids = TEST_BIDS;
692
+ let bids;
658
693
  let makeRequestsStub;
659
694
 
660
695
  before(function () {
@@ -666,19 +701,20 @@ describe('auctionmanager.js', function () {
666
701
  });
667
702
 
668
703
  describe('when auction timeout is 3000', function () {
669
- before(function () {
670
- ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder);
671
- makeRequestsStub.returns(TEST_BID_REQS);
672
- });
673
704
  beforeEach(function () {
705
+ ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder);
674
706
  adUnits = [{
675
707
  code: ADUNIT_CODE,
708
+ transactionId: ADUNIT_CODE,
676
709
  bids: [
677
710
  {bidder: BIDDER_CODE, params: {placementId: 'id'}},
678
711
  ]
679
712
  }];
680
713
  adUnitCodes = [ADUNIT_CODE];
681
714
  auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000});
715
+ bids = TEST_BIDS.slice();
716
+ makeRequestsStub.returns(bids.map(b => mockBidRequest(b, {auctionId: auction.getAuctionId()})));
717
+ indexAuctions = [auction];
682
718
  createAuctionStub = sinon.stub(auctionModule, 'newAuction');
683
719
  createAuctionStub.returns(auction);
684
720
 
@@ -687,11 +723,8 @@ describe('auctionmanager.js', function () {
687
723
  });
688
724
 
689
725
  afterEach(function () {
690
- auctionModule.newAuction.restore();
691
- });
692
-
693
- after(function () {
694
726
  ajaxStub.restore();
727
+ auctionModule.newAuction.restore();
695
728
  });
696
729
 
697
730
  function checkPbDg(cpm, expected, msg) {
@@ -739,9 +772,7 @@ describe('auctionmanager.js', function () {
739
772
  url: 'renderer.js',
740
773
  render: (bid) => bid
741
774
  };
742
- let bidRequests = [Object.assign({}, TEST_BID_REQS[0])];
743
- bidRequests[0].bids[0] = Object.assign({ renderer }, bidRequests[0].bids[0]);
744
- makeRequestsStub.returns(bidRequests);
775
+ Object.assign(adUnits[0], {renderer});
745
776
 
746
777
  let bids1 = Object.assign({},
747
778
  bids[0],
@@ -762,9 +793,7 @@ describe('auctionmanager.js', function () {
762
793
  backupOnly: true,
763
794
  render: (bid) => bid
764
795
  };
765
- let bidRequests = [Object.assign({}, TEST_BID_REQS[0])];
766
- bidRequests[0].bids[0] = Object.assign({ renderer }, bidRequests[0].bids[0]);
767
- makeRequestsStub.returns(bidRequests);
796
+ Object.assign(adUnits[0], {renderer});
768
797
 
769
798
  let bids1 = Object.assign({},
770
799
  bids[0],
@@ -846,17 +875,19 @@ describe('auctionmanager.js', function () {
846
875
  url: 'renderer.js',
847
876
  render: (bid) => bid
848
877
  };
849
-
878
+ Object.assign(adUnits[0], {renderer});
850
879
  // make sure that if the renderer is only on the second ad unit, prebid
851
880
  // still correctly uses it
852
881
  let bid = mockBid();
853
- let bidRequests = [mockBidRequest(bid)];
882
+ let bidRequests = [mockBidRequest(bid, {auctionId: auction.getAuctionId()})];
854
883
 
855
884
  bidRequests[0].bids[1] = Object.assign({
856
- renderer,
857
885
  bidId: utils.getUniqueIdentifierStr()
858
886
  }, bidRequests[0].bids[0]);
859
- bidRequests[0].bids[0].adUnitCode = ADUNIT_CODE1;
887
+ Object.assign(bidRequests[0].bids[0], {
888
+ adUnitCode: ADUNIT_CODE1,
889
+ transactionId: ADUNIT_CODE1,
890
+ });
860
891
 
861
892
  makeRequestsStub.returns(bidRequests);
862
893
 
@@ -874,16 +905,16 @@ describe('auctionmanager.js', function () {
874
905
  describe('when auction timeout is 20', function () {
875
906
  let eventsEmitSpy;
876
907
 
877
- before(function () {
908
+ function setupBids(auctionId) {
878
909
  bids = [mockBid(), mockBid({ bidderCode: BIDDER_CODE1 })];
879
- let bidRequests = bids.map(bid => mockBidRequest(bid));
880
-
910
+ let bidRequests = bids.map(bid => mockBidRequest(bid, {auctionId}));
881
911
  makeRequestsStub.returns(bidRequests);
882
- });
912
+ }
883
913
 
884
914
  beforeEach(function () {
885
915
  adUnits = [{
886
916
  code: ADUNIT_CODE,
917
+ transactionId: ADUNIT_CODE,
887
918
  bids: [
888
919
  {bidder: BIDDER_CODE, params: {placementId: 'id'}},
889
920
  ]
@@ -919,6 +950,7 @@ describe('auctionmanager.js', function () {
919
950
  done();
920
951
  }
921
952
  auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20});
953
+ setupBids(auction.getAuctionId());
922
954
 
923
955
  auction.callBids();
924
956
  respondToRequest(0);
@@ -937,7 +969,7 @@ describe('auctionmanager.js', function () {
937
969
  done();
938
970
  }
939
971
  auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20});
940
-
972
+ setupBids(auction.getAuctionId());
941
973
  auction.callBids();
942
974
  respondToRequest(0);
943
975
  respondToRequest(1);
@@ -959,14 +991,14 @@ describe('auctionmanager.js', function () {
959
991
  done();
960
992
  }
961
993
  auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20});
962
-
994
+ setupBids(auction.getAuctionId());
963
995
  auction.callBids();
964
996
  respondToRequest(0);
965
997
  });
966
998
  });
967
999
  });
968
1000
 
969
- describe('addBidResponse', function () {
1001
+ describe('addBidResponse #2', function () {
970
1002
  let createAuctionStub;
971
1003
  let adUnits;
972
1004
  let adUnitCodes;
@@ -978,38 +1010,32 @@ describe('auctionmanager.js', function () {
978
1010
  let bids = TEST_BIDS;
979
1011
  let bids1 = [mockBid({ bidderCode: BIDDER_CODE1 })];
980
1012
 
981
- before(function () {
982
- let bidRequests = [
983
- mockBidRequest(bids[0]),
984
- mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 })
985
- ];
986
- let makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests');
987
- makeRequestsStub.returns(bidRequests);
988
-
989
- ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder);
990
- });
991
-
992
- after(function () {
993
- ajaxStub.restore();
994
- adapterManager.makeBidRequests.restore();
995
- });
996
-
997
1013
  beforeEach(function () {
998
1014
  adUnits = [{
999
1015
  code: ADUNIT_CODE,
1016
+ transactionId: ADUNIT_CODE,
1000
1017
  bids: [
1001
1018
  {bidder: BIDDER_CODE, params: {placementId: 'id'}},
1002
1019
  ]
1003
1020
  }, {
1004
1021
  code: ADUNIT_CODE1,
1022
+ transactionId: ADUNIT_CODE1,
1005
1023
  bids: [
1006
1024
  {bidder: BIDDER_CODE1, params: {placementId: 'id'}},
1007
1025
  ]
1008
1026
  }];
1009
1027
  adUnitCodes = adUnits.map(({ code }) => code);
1010
1028
  auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000});
1029
+ let bidRequests = [
1030
+ mockBidRequest(bids[0], { auctionId: auction.getAuctionId() }),
1031
+ mockBidRequest(bids1[0], { auctionId: auction.getAuctionId(), adUnitCode: ADUNIT_CODE1 })
1032
+ ];
1033
+ let makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests');
1034
+ makeRequestsStub.returns(bidRequests);
1035
+ ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder);
1011
1036
  createAuctionStub = sinon.stub(auctionModule, 'newAuction');
1012
1037
  createAuctionStub.returns(auction);
1038
+ indexAuctions = [auction];
1013
1039
 
1014
1040
  spec = mockBidder(BIDDER_CODE, bids);
1015
1041
  spec1 = mockBidder(BIDDER_CODE1, bids1);
@@ -1020,6 +1046,8 @@ describe('auctionmanager.js', function () {
1020
1046
 
1021
1047
  afterEach(function () {
1022
1048
  auctionModule.newAuction.restore();
1049
+ ajaxStub.restore();
1050
+ adapterManager.makeBidRequests.restore();
1023
1051
  });
1024
1052
 
1025
1053
  it('should not alter bid requestID', function () {
@@ -1109,14 +1137,6 @@ describe('auctionmanager.js', function () {
1109
1137
  logInfoStub = sinon.stub(utils, 'logInfo');
1110
1138
  logWarnStub = sinon.stub(utils, 'logWarn');
1111
1139
  logErrorStub = sinon.stub(utils, 'logError');
1112
- let bidRequests = [
1113
- mockBidRequest(bids[0]),
1114
- mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 })
1115
- ];
1116
- let makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests');
1117
- makeRequestsStub.returns(bidRequests);
1118
-
1119
- ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder);
1120
1140
  });
1121
1141
 
1122
1142
  after(function () {
@@ -1124,8 +1144,6 @@ describe('auctionmanager.js', function () {
1124
1144
  logInfoStub.restore();
1125
1145
  logWarnStub.restore();
1126
1146
  logErrorStub.restore();
1127
- ajaxStub.restore();
1128
- adapterManager.makeBidRequests.restore();
1129
1147
  });
1130
1148
 
1131
1149
  beforeEach(function () {
@@ -1142,11 +1160,13 @@ describe('auctionmanager.js', function () {
1142
1160
 
1143
1161
  adUnits = [{
1144
1162
  code: ADUNIT_CODE,
1163
+ transactionId: ADUNIT_CODE,
1145
1164
  bids: [
1146
1165
  {bidder: BIDDER_CODE, params: {placementId: 'id'}},
1147
1166
  ]
1148
1167
  }, {
1149
1168
  code: ADUNIT_CODE1,
1169
+ transactionId: ADUNIT_CODE1,
1150
1170
  bids: [
1151
1171
  {bidder: BIDDER_CODE1, params: {placementId: 'id'}},
1152
1172
  ]
@@ -1155,6 +1175,15 @@ describe('auctionmanager.js', function () {
1155
1175
  auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000});
1156
1176
  createAuctionStub = sinon.stub(auctionModule, 'newAuction');
1157
1177
  createAuctionStub.returns(auction);
1178
+ indexAuctions = [auction];
1179
+ let bidRequests = [
1180
+ mockBidRequest(bids[0], { auctionId: auction.getAuctionId() }),
1181
+ mockBidRequest(bids1[0], { auctionId: auction.getAuctionId(), adUnitCode: ADUNIT_CODE1 })
1182
+ ];
1183
+ let makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests');
1184
+ makeRequestsStub.returns(bidRequests);
1185
+
1186
+ ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder);
1158
1187
 
1159
1188
  spec = mockBidder(BIDDER_CODE, bids);
1160
1189
  spec1 = mockBidder(BIDDER_CODE1, bids1);
@@ -1169,6 +1198,8 @@ describe('auctionmanager.js', function () {
1169
1198
  logWarnStub.resetHistory();
1170
1199
  logErrorStub.resetHistory();
1171
1200
  auctionModule.newAuction.restore();
1201
+ ajaxStub.restore();
1202
+ adapterManager.makeBidRequests.restore();
1172
1203
  config.resetConfig();
1173
1204
  });
1174
1205
 
@@ -1187,12 +1218,10 @@ describe('auctionmanager.js', function () {
1187
1218
 
1188
1219
  describe('getMediaTypeGranularity', function () {
1189
1220
  it('video', function () {
1190
- let bidReq = {
1191
- 'mediaTypes': { video: {id: '1'} }
1192
- };
1221
+ let mediaTypes = { video: {id: '1'} };
1193
1222
 
1194
1223
  // mediaType is video and video.context is undefined
1195
- expect(getMediaTypeGranularity('video', bidReq, {
1224
+ expect(getMediaTypeGranularity('video', mediaTypes, {
1196
1225
  banner: 'low',
1197
1226
  video: 'medium'
1198
1227
  })).to.equal('medium');
@@ -1208,10 +1237,8 @@ describe('auctionmanager.js', function () {
1208
1237
  })).to.equal('medium');
1209
1238
 
1210
1239
  // also when mediaTypes.video is undefined
1211
- bidReq = {
1212
- 'mediaTypes': { banner: {} }
1213
- };
1214
- expect(getMediaTypeGranularity('video', bidReq, {
1240
+ mediaTypes = { banner: {} };
1241
+ expect(getMediaTypeGranularity('video', mediaTypes, {
1215
1242
  banner: 'low',
1216
1243
  video: 'medium'
1217
1244
  })).to.equal('medium');
@@ -1224,22 +1251,22 @@ describe('auctionmanager.js', function () {
1224
1251
  });
1225
1252
 
1226
1253
  it('video-outstream', function () {
1227
- let bidReq = { 'mediaTypes': { video: { context: 'outstream' } } };
1254
+ let mediaTypes = { video: { context: 'outstream' } };
1228
1255
 
1229
- expect(getMediaTypeGranularity('video', bidReq, {
1256
+ expect(getMediaTypeGranularity('video', mediaTypes, {
1230
1257
  'banner': 'low', 'video': 'medium', 'video-outstream': 'high'
1231
1258
  })).to.equal('high');
1232
1259
  });
1233
1260
 
1234
1261
  it('video-instream', function () {
1235
- let bidReq = { 'mediaTypes': { video: { context: 'instream' } } };
1262
+ let mediaTypes = { video: { context: 'instream' } };
1236
1263
 
1237
- expect(getMediaTypeGranularity('video', bidReq, {
1264
+ expect(getMediaTypeGranularity('video', mediaTypes, {
1238
1265
  banner: 'low', video: 'medium', 'video-instream': 'high'
1239
1266
  })).to.equal('high');
1240
1267
 
1241
1268
  // fall back to video if video-instream not found
1242
- expect(getMediaTypeGranularity('video', bidReq, {
1269
+ expect(getMediaTypeGranularity('video', mediaTypes, {
1243
1270
  banner: 'low', video: 'medium'
1244
1271
  })).to.equal('medium');
1245
1272
 
@@ -1249,43 +1276,83 @@ describe('auctionmanager.js', function () {
1249
1276
  });
1250
1277
 
1251
1278
  it('native', function () {
1252
- expect(getMediaTypeGranularity('native', {mediaTypes: {native: {}}}, {
1279
+ expect(getMediaTypeGranularity('native', {native: {}}, {
1253
1280
  banner: 'low', video: 'medium', native: 'high'
1254
1281
  })).to.equal('high');
1255
1282
  });
1256
1283
  });
1257
1284
 
1285
+ function mockAuction(getBidRequests, start = 1) {
1286
+ return {
1287
+ getBidRequests: getBidRequests,
1288
+ getAdUnits: () => getBidRequests().flatMap(br => br.bids).map(br => ({ code: br.adUnitCode, transactionId: br.transactionId, mediaTypes: br.mediaTypes })),
1289
+ getAuctionId: () => '1',
1290
+ addBidReceived: () => true,
1291
+ getTimeout: () => 1000,
1292
+ getAuctionStart: () => start,
1293
+ }
1294
+ }
1295
+
1296
+ describe('getPriceByGranularity', () => {
1297
+ beforeEach(() => {
1298
+ config.setConfig({
1299
+ mediaTypePriceGranularity: {
1300
+ video: 'medium',
1301
+ banner: 'low'
1302
+ }
1303
+ });
1304
+ })
1305
+
1306
+ afterEach(() => {
1307
+ config.resetConfig();
1308
+ })
1309
+
1310
+ it('evaluates undef granularity on each call', () => {
1311
+ const gpbg = getPriceByGranularity();
1312
+ expect(gpbg({
1313
+ mediaType: 'video', pbMg: 'medium'
1314
+ }, {
1315
+ 'mediaTypes': {video: {id: '1'}}
1316
+ })).to.equal('medium');
1317
+ expect(gpbg({
1318
+ mediaType: 'banner',
1319
+ pbLg: 'low'
1320
+ }, {
1321
+ 'mediaTypes': {banner: {}}
1322
+ })).to.equal('low');
1323
+ });
1324
+ })
1325
+
1258
1326
  describe('auctionCallbacks', function() {
1259
1327
  let bids = TEST_BIDS;
1260
1328
  let bidRequests;
1261
1329
  let doneSpy;
1262
- let auction = {
1263
- getBidRequests: () => bidRequests,
1264
- getAuctionId: () => '1',
1265
- addBidReceived: () => true,
1266
- getTimeout: () => 1000
1267
- }
1330
+ let auction;
1268
1331
 
1269
1332
  beforeEach(() => {
1333
+ const start = Date.now();
1334
+ auction = mockAuction(() => bidRequests, start);
1335
+ indexAuctions = [auction];
1270
1336
  doneSpy = sinon.spy();
1271
1337
  config.setConfig({
1272
1338
  cache: {
1273
1339
  url: 'https://prebid.adnxs.com/pbc/v1/cache'
1274
1340
  }
1275
- })
1341
+ });
1276
1342
  });
1277
1343
 
1278
1344
  afterEach(() => {
1279
1345
  doneSpy.resetHistory();
1280
1346
  config.resetConfig();
1347
+ bidRequests = null;
1281
1348
  });
1282
1349
 
1283
1350
  it('should call auction done after bid is added to auction for mediaType banner', function () {
1284
1351
  let ADUNIT_CODE2 = 'adUnitCode2';
1285
1352
  let BIDDER_CODE2 = 'sampleBidder2';
1286
1353
 
1287
- let bids1 = [mockBid({ bidderCode: BIDDER_CODE1 })];
1288
- let bids2 = [mockBid({ bidderCode: BIDDER_CODE2 })];
1354
+ let bids1 = [mockBid({ bidderCode: BIDDER_CODE1, transactionId: ADUNIT_CODE1 })];
1355
+ let bids2 = [mockBid({ bidderCode: BIDDER_CODE2, transactionId: ADUNIT_CODE2 })];
1289
1356
  bidRequests = [
1290
1357
  mockBidRequest(bids[0]),
1291
1358
  mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }),
@@ -1328,22 +1395,130 @@ describe('auctionmanager.js', function () {
1328
1395
  const responseBody = `{"responses":[{"uuid":"${uuid}"}]}`;
1329
1396
  server.requests[0].respond(200, { 'Content-Type': 'application/json' }, responseBody);
1330
1397
  assert.equal(doneSpy.callCount, 1);
1331
- })
1398
+ });
1399
+
1400
+ describe('when addBidResponse hook returns promises', () => {
1401
+ let resolvers, callbacks, bids;
1402
+
1403
+ function hook(next, ...args) {
1404
+ next.bail(new Promise((resolve, reject) => {
1405
+ resolvers.resolve.push(resolve);
1406
+ resolvers.reject.push(reject);
1407
+ }).finally(() => next(...args)));
1408
+ }
1409
+
1410
+ function invokeCallbacks() {
1411
+ bids.forEach((bid) => callbacks.addBidResponse(ADUNIT_CODE, bid));
1412
+ bidRequests.forEach(bidRequest => callbacks.adapterDone.call(bidRequest));
1413
+ }
1414
+
1415
+ function delay(ms = 0) {
1416
+ return new Promise((resolve) => {
1417
+ setTimeout(resolve, ms)
1418
+ });
1419
+ }
1420
+
1421
+ beforeEach(() => {
1422
+ promiseSandbox.restore();
1423
+ bids = [
1424
+ mockBid({bidderCode: BIDDER_CODE1}),
1425
+ mockBid({bidderCode: BIDDER_CODE})
1426
+ ]
1427
+ bidRequests = bids.map((b) => mockBidRequest(b));
1428
+ resolvers = {resolve: [], reject: []};
1429
+ addBidResponse.before(hook);
1430
+ callbacks = auctionCallbacks(doneSpy, auction);
1431
+ Object.assign(auction, {
1432
+ addNoBid: sinon.spy()
1433
+ });
1434
+ });
1435
+
1436
+ afterEach(() => {
1437
+ addBidResponse.getHooks({hook: hook}).remove();
1438
+ });
1439
+
1440
+ it('should wait for bids without a request bids before calling auctionDone', () => {
1441
+ callbacks.addBidResponse(ADUNIT_CODE, Object.assign(mockBid(), {requestId: null}));
1442
+ invokeCallbacks();
1443
+ resolvers.resolve.slice(1, 3).forEach((fn) => fn());
1444
+ return delay().then(() => {
1445
+ expect(doneSpy.called).to.be.false;
1446
+ resolvers.resolve[0]();
1447
+ return delay();
1448
+ }).then(() => {
1449
+ expect(doneSpy.called).to.be.true;
1450
+ });
1451
+ });
1452
+
1453
+ Object.entries({
1454
+ 'all succeed': ['resolve', 'resolve'],
1455
+ 'some fail': ['resolve', 'reject'],
1456
+ 'all fail': ['reject', 'reject']
1457
+ }).forEach(([test, results]) => {
1458
+ describe(`(and ${test})`, () => {
1459
+ it('should wait for them to complete before calling auctionDone', () => {
1460
+ invokeCallbacks();
1461
+ return delay().then(() => {
1462
+ expect(doneSpy.called).to.be.false;
1463
+ expect(auction.addNoBid.called).to.be.false;
1464
+ resolvers[results[0]][0]();
1465
+ return delay();
1466
+ }).then(() => {
1467
+ expect(doneSpy.called).to.be.false;
1468
+ expect(auction.addNoBid.called).to.be.false;
1469
+ resolvers[results[1]][1]();
1470
+ return delay();
1471
+ }).then(() => {
1472
+ expect(doneSpy.called).to.be.true;
1473
+ });
1474
+ });
1475
+ });
1476
+ });
1477
+
1478
+ Object.entries({
1479
+ bidder: (timeout) => {
1480
+ bidRequests.forEach((r) => r.timeout = timeout);
1481
+ auction.getTimeout = () => timeout + 10000
1482
+ },
1483
+ auction: (timeout) => {
1484
+ auction.getTimeout = () => timeout;
1485
+ bidRequests.forEach((r) => r.timeout = timeout + 10000)
1486
+ }
1487
+ }).forEach(([test, setTimeout]) => {
1488
+ it(`should respect ${test} timeout if they never complete`, () => {
1489
+ const start = Date.now() - 2900;
1490
+ auction.getAuctionStart = () => start;
1491
+ setTimeout(3000);
1492
+ invokeCallbacks();
1493
+ return delay().then(() => {
1494
+ expect(doneSpy.called).to.be.false;
1495
+ return delay(100);
1496
+ }).then(() => {
1497
+ expect(doneSpy.called).to.be.true;
1498
+ });
1499
+ });
1500
+
1501
+ it(`should not wait if ${test} has already timed out`, () => {
1502
+ const start = Date.now() - 2000;
1503
+ auction.getAuctionStart = () => start;
1504
+ setTimeout(1000);
1505
+ invokeCallbacks();
1506
+ return delay().then(() => {
1507
+ expect(doneSpy.called).to.be.true;
1508
+ });
1509
+ });
1510
+ })
1511
+ });
1332
1512
  });
1333
1513
 
1334
1514
  describe('auctionOptions', function() {
1335
1515
  let bidRequests;
1336
1516
  let doneSpy;
1337
1517
  let clock;
1338
- let auction = {
1339
- getBidRequests: () => bidRequests,
1340
- getAuctionId: () => '1',
1341
- addBidReceived: () => true,
1342
- getTimeout: () => 1000
1343
- }
1344
1518
  let requiredBidder = BIDDER_CODE;
1345
1519
  let requiredBidder1 = BIDDER_CODE1;
1346
1520
  let secondaryBidder = 'doNotWaitForMe';
1521
+ let auction;
1347
1522
 
1348
1523
  beforeEach(() => {
1349
1524
  clock = sinon.useFakeTimers();
@@ -1352,7 +1527,11 @@ describe('auctionmanager.js', function () {
1352
1527
  'auctionOptions': {
1353
1528
  secondaryBidders: [ secondaryBidder ]
1354
1529
  }
1355
- })
1530
+ });
1531
+
1532
+ const start = Date.now();
1533
+ auction = mockAuction(() => bidRequests);
1534
+ indexAuctions = [auction];
1356
1535
  });
1357
1536
 
1358
1537
  afterEach(() => {
@@ -1362,9 +1541,9 @@ describe('auctionmanager.js', function () {
1362
1541
  });
1363
1542
 
1364
1543
  it('should not wait to call auction done for secondary bidders', function () {
1365
- let bids1 = [mockBid({ bidderCode: requiredBidder })];
1366
- let bids2 = [mockBid({ bidderCode: requiredBidder1 })];
1367
- let bids3 = [mockBid({ bidderCode: secondaryBidder })];
1544
+ let bids1 = [mockBid({ bidderCode: requiredBidder, transactionId: ADUNIT_CODE1 })];
1545
+ let bids2 = [mockBid({ bidderCode: requiredBidder1, transactionId: ADUNIT_CODE1 })];
1546
+ let bids3 = [mockBid({ bidderCode: secondaryBidder, transactionId: ADUNIT_CODE1 })];
1368
1547
  bidRequests = [
1369
1548
  mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }),
1370
1549
  mockBidRequest(bids2[0], { adUnitCode: ADUNIT_CODE1 }),
@@ -16,8 +16,10 @@ let setDefaults;
16
16
  describe('config API', function () {
17
17
  let logErrorSpy;
18
18
  let logWarnSpy;
19
+ let config;
20
+
19
21
  beforeEach(function () {
20
- const config = newConfig();
22
+ config = newConfig();
21
23
  getConfig = config.getConfig;
22
24
  setConfig = config.setConfig;
23
25
  readConfig = config.readConfig;
@@ -624,4 +626,25 @@ describe('config API', function () {
624
626
  expect(ortb2Config.user.data).to.have.lengthOf(2);
625
627
  expect(ortb2Config.site.content.data).to.have.lengthOf(1);
626
628
  });
629
+
630
+ it('should not corrupt global configuration with bidder configuration', () => {
631
+ // https://github.com/prebid/Prebid.js/issues/7956
632
+ config.setConfig({
633
+ outer: {
634
+ inner: ['global']
635
+ }
636
+ });
637
+ config.setBidderConfig({
638
+ bidders: ['bidder'],
639
+ config: {
640
+ outer: {
641
+ inner: ['bidder']
642
+ }
643
+ }
644
+ });
645
+ config.runWithBidder('bidder', () => config.getConfig())
646
+ expect(config.getConfig('outer')).to.eql({
647
+ inner: ['global']
648
+ });
649
+ });
627
650
  });