prebid.js 6.0.0 → 6.4.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 (201) hide show
  1. package/.babelrc.js +1 -7
  2. package/.circleci/config.yml +1 -1
  3. package/README.md +1 -1
  4. package/browsers.json +13 -29
  5. package/gulpfile.js +88 -82
  6. package/integrationExamples/gpt/weboramaRtdProvider_example.html +23 -14
  7. package/karma.conf.maker.js +2 -2
  8. package/modules/33acrossBidAdapter.js +189 -102
  9. package/modules/adagioBidAdapter.js +1 -1
  10. package/modules/addefendBidAdapter.js +1 -0
  11. package/modules/adheseBidAdapter.js +7 -2
  12. package/modules/adkernelBidAdapter.js +147 -61
  13. package/modules/adlivetechBidAdapter.md +61 -0
  14. package/modules/adlooxAdServerVideo.js +2 -2
  15. package/modules/adlooxAnalyticsAdapter.js +4 -4
  16. package/modules/admanBidAdapter.js +1 -0
  17. package/modules/admixerBidAdapter.js +3 -2
  18. package/modules/adnuntiusBidAdapter.js +5 -2
  19. package/modules/adomikAnalyticsAdapter.js +16 -4
  20. package/modules/adplusBidAdapter.js +203 -0
  21. package/modules/adplusBidAdapter.md +39 -0
  22. package/modules/adxcgBidAdapter.js +311 -359
  23. package/modules/adxcgBidAdapter.md +22 -21
  24. package/modules/adyoulikeBidAdapter.js +7 -2
  25. package/modules/aniviewBidAdapter.js +1 -1
  26. package/modules/appnexusBidAdapter.js +23 -3
  27. package/modules/beachfrontBidAdapter.js +14 -17
  28. package/modules/beopBidAdapter.js +6 -4
  29. package/modules/bidViewability.js +3 -3
  30. package/modules/bidViewabilityIO.js +3 -3
  31. package/modules/codefuelBidAdapter.js +1 -3
  32. package/modules/codefuelBidAdapter.md +3 -3
  33. package/modules/colossussspBidAdapter.js +7 -0
  34. package/modules/compassBidAdapter.js +201 -0
  35. package/modules/compassBidAdapter.md +79 -0
  36. package/modules/craftBidAdapter.js +5 -3
  37. package/modules/criteoBidAdapter.js +1 -1
  38. package/modules/currency.js +2 -2
  39. package/modules/cwireBidAdapter.js +3 -0
  40. package/modules/dailyhuntBidAdapter.js +435 -0
  41. package/modules/dailyhuntBidAdapter.md +4 -0
  42. package/modules/datablocksBidAdapter.js +3 -3
  43. package/modules/dchain.js +149 -0
  44. package/modules/dchain.md +45 -0
  45. package/modules/deepintentBidAdapter.js +1 -1
  46. package/modules/dspxBidAdapter.js +1 -1
  47. package/modules/emx_digitalBidAdapter.js +9 -1
  48. package/modules/engageyaBidAdapter.js +68 -54
  49. package/modules/feedadBidAdapter.js +2 -2
  50. package/modules/feedadBidAdapter.md +4 -2
  51. package/modules/freewheel-sspBidAdapter.js +6 -0
  52. package/modules/futureads.md +48 -0
  53. package/modules/glimpseBidAdapter.js +44 -16
  54. package/modules/goldbachBidAdapter.js +1176 -0
  55. package/modules/goldbachBidAdapter.md +151 -0
  56. package/modules/gptPreAuction.js +11 -5
  57. package/modules/gridBidAdapter.js +5 -4
  58. package/modules/gumgumBidAdapter.js +7 -3
  59. package/modules/id5IdSystem.md +6 -6
  60. package/modules/imRtdProvider.js +31 -0
  61. package/modules/improvedigitalBidAdapter.js +19 -3
  62. package/modules/instreamTracking.js +4 -4
  63. package/modules/intersectionRtdProvider.js +114 -0
  64. package/modules/invibesBidAdapter.js +64 -14
  65. package/modules/invibesBidAdapter.md +2 -1
  66. package/modules/ipromBidAdapter.js +79 -0
  67. package/modules/ixBidAdapter.js +185 -22
  68. package/modules/kinessoIdSystem.js +1 -1
  69. package/modules/limelightDigitalBidAdapter.js +2 -1
  70. package/modules/livewrappedBidAdapter.js +8 -2
  71. package/modules/lotamePanoramaIdSystem.js +80 -8
  72. package/modules/luponmediaBidAdapter.js +570 -0
  73. package/modules/mediasquareBidAdapter.js +1 -9
  74. package/modules/merkleIdSystem.js +5 -0
  75. package/modules/missenaBidAdapter.js +89 -0
  76. package/modules/nativoBidAdapter.js +27 -1
  77. package/modules/nextMillenniumBidAdapter.js +37 -7
  78. package/modules/oguryBidAdapter.js +2 -1
  79. package/modules/openxBidAdapter.js +6 -1
  80. package/modules/prebidServerBidAdapter/index.js +19 -15
  81. package/modules/pubgeniusBidAdapter.js +1 -1
  82. package/modules/pubmaticBidAdapter.js +5 -3
  83. package/modules/pubxaiAnalyticsAdapter.js +17 -0
  84. package/modules/relaidoBidAdapter.js +86 -65
  85. package/modules/richaudienceBidAdapter.js +2 -3
  86. package/modules/rtdModule/index.js +48 -18
  87. package/modules/rubiconBidAdapter.js +31 -19
  88. package/modules/saambaaBidAdapter.js +420 -0
  89. package/modules/saambaaBidAdapter.md +65 -68
  90. package/modules/seedtagBidAdapter.js +6 -0
  91. package/modules/sharedIdSystem.js +27 -1
  92. package/modules/smaatoBidAdapter.js +9 -1
  93. package/modules/smartxBidAdapter.js +17 -1
  94. package/modules/sspBCBidAdapter.js +34 -3
  95. package/modules/tappxBidAdapter.js +3 -1
  96. package/modules/targetVideoBidAdapter.js +187 -0
  97. package/modules/targetVideoBidAdapter.md +34 -0
  98. package/modules/telariaBidAdapter.js +2 -2
  99. package/modules/trustxBidAdapter.js +18 -17
  100. package/modules/undertoneBidAdapter.js +8 -1
  101. package/modules/userId/index.js +27 -2
  102. package/modules/ventes.md +71 -0
  103. package/modules/ventesBidAdapter.js +104 -64
  104. package/modules/ventesBidAdapter.md +0 -1
  105. package/modules/vidoomyBidAdapter.js +65 -108
  106. package/modules/visxBidAdapter.js +20 -3
  107. package/modules/visxBidAdapter.md +4 -6
  108. package/modules/weboramaRtdProvider.js +288 -73
  109. package/modules/weboramaRtdProvider.md +27 -10
  110. package/modules/yahoosspBidAdapter.js +5 -1
  111. package/modules/yahoosspBidAdapter.md +1 -1
  112. package/modules/yieldlabBidAdapter.js +41 -10
  113. package/modules/yieldlabBidAdapter.md +91 -48
  114. package/modules/yieldoneBidAdapter.js +115 -11
  115. package/modules/zetaSspBidAdapter.md +33 -1
  116. package/modules/zeta_global_sspBidAdapter.js +22 -1
  117. package/package.json +6 -1
  118. package/plugins/pbjsGlobals.js +28 -1
  119. package/src/adapterManager.js +14 -8
  120. package/src/auction.js +5 -4
  121. package/src/prebid.js +1 -2
  122. package/src/targeting.js +24 -3
  123. package/src/utils.js +41 -7
  124. package/test/helpers/prebidGlobal.js +1 -0
  125. package/test/spec/integration/faker/googletag.js +6 -0
  126. package/test/spec/modules/33acrossBidAdapter_spec.js +300 -78
  127. package/test/spec/modules/adheseBidAdapter_spec.js +27 -1
  128. package/test/spec/modules/adlooxAnalyticsAdapter_spec.js +6 -6
  129. package/test/spec/modules/adnuntiusBidAdapter_spec.js +35 -0
  130. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +9 -1
  131. package/test/spec/modules/adplusBidAdapter_spec.js +213 -0
  132. package/test/spec/modules/adxcgBidAdapter_spec.js +820 -571
  133. package/test/spec/modules/adyoulikeBidAdapter_spec.js +26 -0
  134. package/test/spec/modules/appnexusBidAdapter_spec.js +63 -1
  135. package/test/spec/modules/beachfrontBidAdapter_spec.js +65 -1
  136. package/test/spec/modules/beopBidAdapter_spec.js +1 -1
  137. package/test/spec/modules/bidViewabilityIO_spec.js +2 -2
  138. package/test/spec/modules/bidViewability_spec.js +4 -4
  139. package/test/spec/modules/codefuelBidAdapter_spec.js +1 -1
  140. package/test/spec/modules/colossussspBidAdapter_spec.js +9 -0
  141. package/test/spec/modules/compassBidAdapter_spec.js +397 -0
  142. package/test/spec/modules/cwireBidAdapter_spec.js +10 -8
  143. package/test/spec/modules/dailyhuntBidAdapter_spec.js +404 -0
  144. package/test/spec/modules/datablocksBidAdapter_spec.js +3 -3
  145. package/test/spec/modules/dchain_spec.js +329 -0
  146. package/test/spec/modules/emx_digitalBidAdapter_spec.js +10 -0
  147. package/test/spec/modules/engageyaBidAdapter_spec.js +231 -95
  148. package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
  149. package/test/spec/modules/feedadBidAdapter_spec.js +15 -0
  150. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +19 -0
  151. package/test/spec/modules/glimpseBidAdapter_spec.js +33 -0
  152. package/test/spec/modules/goldbachBidAdapter_spec.js +1359 -0
  153. package/test/spec/modules/gptPreAuction_spec.js +58 -4
  154. package/test/spec/modules/gumgumBidAdapter_spec.js +6 -0
  155. package/test/spec/modules/imRtdProvider_spec.js +25 -0
  156. package/test/spec/modules/improvedigitalBidAdapter_spec.js +3 -1
  157. package/test/spec/modules/intersectionRtdProvider_spec.js +141 -0
  158. package/test/spec/modules/invibesBidAdapter_spec.js +148 -4
  159. package/test/spec/modules/ipromBidAdapter_spec.js +195 -0
  160. package/test/spec/modules/ixBidAdapter_spec.js +293 -2
  161. package/test/spec/modules/konduitWrapper_spec.js +0 -1
  162. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +10 -7
  163. package/test/spec/modules/livewrappedBidAdapter_spec.js +31 -0
  164. package/test/spec/modules/lotamePanoramaIdSystem_spec.js +227 -0
  165. package/test/spec/modules/luponmediaBidAdapter_spec.js +412 -0
  166. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -4
  167. package/test/spec/modules/merkleIdSystem_spec.js +18 -0
  168. package/test/spec/modules/missenaBidAdapter_spec.js +134 -0
  169. package/test/spec/modules/nativoBidAdapter_spec.js +35 -18
  170. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +26 -1
  171. package/test/spec/modules/oguryBidAdapter_spec.js +13 -11
  172. package/test/spec/modules/openxBidAdapter_spec.js +5 -0
  173. package/test/spec/modules/prebidServerBidAdapter_spec.js +62 -2
  174. package/test/spec/modules/pubgeniusBidAdapter_spec.js +3 -3
  175. package/test/spec/modules/pubmaticBidAdapter_spec.js +1 -1
  176. package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +11 -0
  177. package/test/spec/modules/realTimeDataModule_spec.js +135 -49
  178. package/test/spec/modules/relaidoBidAdapter_spec.js +71 -63
  179. package/test/spec/modules/richaudienceBidAdapter_spec.js +2 -2
  180. package/test/spec/modules/rubiconBidAdapter_spec.js +65 -9
  181. package/test/spec/modules/seedtagBidAdapter_spec.js +3 -0
  182. package/test/spec/modules/sharedIdSystem_spec.js +52 -6
  183. package/test/spec/modules/smaatoBidAdapter_spec.js +61 -0
  184. package/test/spec/modules/smartxBidAdapter_spec.js +9 -0
  185. package/test/spec/modules/sspBCBidAdapter_spec.js +33 -3
  186. package/test/spec/modules/tappxBidAdapter_spec.js +4 -0
  187. package/test/spec/modules/targetVideoBidAdapter_spec.js +96 -0
  188. package/test/spec/modules/trustxBidAdapter_spec.js +42 -0
  189. package/test/spec/modules/userId_spec.js +51 -0
  190. package/test/spec/modules/vidoomyBidAdapter_spec.js +32 -13
  191. package/test/spec/modules/visxBidAdapter_spec.js +121 -5
  192. package/test/spec/modules/weboramaRtdProvider_spec.js +408 -214
  193. package/test/spec/modules/yahoosspBidAdapter_spec.js +28 -1
  194. package/test/spec/modules/yieldlabBidAdapter_spec.js +81 -0
  195. package/test/spec/modules/yieldoneBidAdapter_spec.js +299 -53
  196. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +33 -1
  197. package/test/spec/unit/core/adapterManager_spec.js +24 -6
  198. package/test/spec/unit/core/targeting_spec.js +116 -0
  199. package/test/spec/utils_spec.js +38 -0
  200. package/test/test_deps.js +3 -0
  201. package/test/test_index.js +1 -3
@@ -2,7 +2,7 @@ import * as utils from 'src/utils.js';
2
2
  import { config } from 'src/config.js';
3
3
  import { expect } from 'chai';
4
4
  import { newBidder } from 'src/adapters/bidderFactory.js';
5
- import { spec } from 'modules/ixBidAdapter.js';
5
+ import { spec, storage, ERROR_CODES } from '../../../modules/ixBidAdapter.js';
6
6
  import { createEidsArray } from 'modules/userId/eids.js';
7
7
 
8
8
  describe('IndexexchangeAdapter', function () {
@@ -353,6 +353,37 @@ describe('IndexexchangeAdapter', function () {
353
353
  ]
354
354
  };
355
355
 
356
+ const DEFAULT_VIDEO_BID_RESPONSE_WITH_MTYPE_SET = {
357
+ cur: 'USD',
358
+ id: '1aa2bb3cc4de',
359
+ seatbid: [
360
+ {
361
+ bid: [
362
+ {
363
+ crid: '12346',
364
+ adomain: ['www.abcd.com'],
365
+ adid: '14851456',
366
+ impid: '1a2b3c4e',
367
+ cid: '3051267',
368
+ price: 110,
369
+ id: '2',
370
+ mtype: 2,
371
+ adm: '<?xml version=\"1.0\" encoding=\"UTF-8\"?><VAST xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"vast.xsd\" version=\"3.0\"> <Ad id=\"488427365\"> <InLine> <AdSystem>Test</AdSystem> <AdTitle>In-Stream Video</AdTitle> </InLine> </Ad></VAST',
372
+ ext: {
373
+ vasturl: 'www.abcd.com/vast',
374
+ errorurl: 'www.abcd.com/error',
375
+ dspid: 51,
376
+ pricelevel: '_110',
377
+ advbrandid: 303326,
378
+ advbrand: 'OECTB'
379
+ }
380
+ }
381
+ ],
382
+ seat: '3971'
383
+ }
384
+ ]
385
+ };
386
+
356
387
  const DEFAULT_OPTION = {
357
388
  gdprConsent: {
358
389
  gdprApplies: true,
@@ -1236,7 +1267,7 @@ describe('IndexexchangeAdapter', function () {
1236
1267
  afterEach(function () {
1237
1268
  config.setConfig({
1238
1269
  ortb2: {}
1239
- })
1270
+ });
1240
1271
  });
1241
1272
 
1242
1273
  it('should not set ixdiag.fpd value if not defined', function () {
@@ -2343,6 +2374,45 @@ describe('IndexexchangeAdapter', function () {
2343
2374
  expect(result[0]).to.deep.equal(expectedParse[0]);
2344
2375
  });
2345
2376
 
2377
+ it('should get correct bid response for video ad and set bid.vastXml when mtype is 2 (video)', function () {
2378
+ const expectedParse = [
2379
+ {
2380
+ requestId: '1a2b3c4e',
2381
+ cpm: 1.1,
2382
+ creativeId: '12346',
2383
+ mediaType: 'video',
2384
+ mediaTypes: {
2385
+ video: {
2386
+ context: 'instream',
2387
+ playerSize: [
2388
+ [
2389
+ 400,
2390
+ 100
2391
+ ]
2392
+ ]
2393
+ }
2394
+ },
2395
+ width: 640,
2396
+ height: 480,
2397
+ currency: 'USD',
2398
+ ttl: 3600,
2399
+ netRevenue: true,
2400
+ vastXml: '<?xml version=\"1.0\" encoding=\"UTF-8\"?><VAST xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"vast.xsd\" version=\"3.0\"> <Ad id=\"488427365\"> <InLine> <AdSystem>Test</AdSystem> <AdTitle>In-Stream Video</AdTitle> </InLine> </Ad></VAST',
2401
+ meta: {
2402
+ networkId: 51,
2403
+ brandId: 303326,
2404
+ brandName: 'OECTB',
2405
+ advertiserDomains: ['www.abcd.com']
2406
+ }
2407
+ }
2408
+ ];
2409
+ const result = spec.interpretResponse({ body: DEFAULT_VIDEO_BID_RESPONSE_WITH_MTYPE_SET }, {
2410
+ data: DEFAULT_BIDDER_REQUEST_DATA, validBidRequests: ONE_VIDEO
2411
+ });
2412
+
2413
+ expect(result[0]).to.deep.equal(expectedParse[0]);
2414
+ });
2415
+
2346
2416
  it('bidrequest should not have page if options is undefined', function () {
2347
2417
  const options = {};
2348
2418
  const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options);
@@ -2524,4 +2594,225 @@ describe('IndexexchangeAdapter', function () {
2524
2594
  expect(r.regs.coppa).to.be.undefined;
2525
2595
  });
2526
2596
  });
2597
+
2598
+ describe('LocalStorage ixdiag', () => {
2599
+ let TODAY = new Date().toISOString().slice(0, 10);
2600
+ const key = 'ixdiag';
2601
+
2602
+ let sandbox;
2603
+ let setDataInLocalStorageStub;
2604
+ let getDataFromLocalStorageStub;
2605
+ let removeDataFromLocalStorageStub;
2606
+ let localStorageValues = {};
2607
+
2608
+ beforeEach(() => {
2609
+ sandbox = sinon.sandbox.create();
2610
+ setDataInLocalStorageStub = sandbox.stub(storage, 'setDataInLocalStorage').callsFake((key, value) => localStorageValues[key] = value)
2611
+ getDataFromLocalStorageStub = sandbox.stub(storage, 'getDataFromLocalStorage').callsFake((key) => localStorageValues[key])
2612
+ removeDataFromLocalStorageStub = sandbox.stub(storage, 'removeDataFromLocalStorage').callsFake((key) => delete localStorageValues[key])
2613
+ sandbox.stub(storage, 'localStorageIsEnabled').returns(true);
2614
+ });
2615
+
2616
+ afterEach(() => {
2617
+ setDataInLocalStorageStub.restore();
2618
+ getDataFromLocalStorageStub.restore();
2619
+ removeDataFromLocalStorageStub.restore();
2620
+ localStorageValues = {};
2621
+ sandbox.restore();
2622
+
2623
+ config.setConfig({
2624
+ fpd: {},
2625
+ ix: {},
2626
+ })
2627
+ });
2628
+
2629
+ it('should not log error in LocalStorage when there is no logError called.', () => {
2630
+ const bid = DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0];
2631
+ expect(spec.isBidRequestValid(bid)).to.be.true;
2632
+ expect(localStorageValues[key]).to.be.undefined;
2633
+ });
2634
+
2635
+ it('should log ERROR_CODES.BID_SIZE_INVALID_FORMAT in LocalStorage when there is logError called.', () => {
2636
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2637
+ bid.params.size = ['400', 100];
2638
+
2639
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2640
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_SIZE_INVALID_FORMAT]: 1 } });
2641
+ });
2642
+
2643
+ it('should log ERROR_CODES.BID_SIZE_NOT_INCLUDED in LocalStorage when there is logError called.', () => {
2644
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2645
+ bid.params.size = [407, 100];
2646
+
2647
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2648
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_SIZE_NOT_INCLUDED]: 1 } });
2649
+ });
2650
+
2651
+ it('should log ERROR_CODES.PROPERTY_NOT_INCLUDED in LocalStorage when there is logError called.', () => {
2652
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2653
+ bid.params.video = {};
2654
+
2655
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2656
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PROPERTY_NOT_INCLUDED]: 4 } });
2657
+ });
2658
+
2659
+ it('should log ERROR_CODES.SITE_ID_INVALID_VALUE in LocalStorage when there is logError called.', () => {
2660
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2661
+ bid.params.siteId = false;
2662
+
2663
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2664
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.SITE_ID_INVALID_VALUE]: 1 } });
2665
+ });
2666
+
2667
+ it('should log ERROR_CODES.BID_FLOOR_INVALID_FORMAT in LocalStorage when there is logError called.', () => {
2668
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2669
+ bid.params.bidFloor = true;
2670
+
2671
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2672
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_FLOOR_INVALID_FORMAT]: 1 } });
2673
+ });
2674
+
2675
+ it('should log ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE in LocalStorage when there is logError called.', () => {
2676
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2677
+
2678
+ config.setConfig({
2679
+ ix: {
2680
+ firstPartyData: {
2681
+ cd: Array(1700).join('#')
2682
+ }
2683
+ }
2684
+ });
2685
+
2686
+ expect(spec.isBidRequestValid(bid)).to.be.true;
2687
+ spec.buildRequests([bid]);
2688
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE]: 2 } });
2689
+ });
2690
+
2691
+ it('should log ERROR_CODES.EXCEEDS_MAX_SIZE in LocalStorage when there is logError called.', () => {
2692
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2693
+ bid.bidderRequestId = Array(8000).join('#');
2694
+
2695
+ expect(spec.isBidRequestValid(bid)).to.be.true;
2696
+ spec.buildRequests([bid]);
2697
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.EXCEEDS_MAX_SIZE]: 2 } });
2698
+ });
2699
+
2700
+ it('should log ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE in LocalStorage when there is logError called.', () => {
2701
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2702
+
2703
+ config.setConfig({
2704
+ fpd: {
2705
+ site: {
2706
+ data: {
2707
+ pageType: Array(5700).join('#')
2708
+ }
2709
+ }
2710
+ }
2711
+ });
2712
+
2713
+ expect(spec.isBidRequestValid(bid)).to.be.true;
2714
+ spec.buildRequests([bid]);
2715
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE]: 2 } });
2716
+ });
2717
+
2718
+ it('should log ERROR_CODES.VIDEO_DURATION_INVALID in LocalStorage when there is logError called.', () => {
2719
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2720
+ bid.params.video.minduration = 1;
2721
+ bid.params.video.maxduration = 0;
2722
+
2723
+ expect(spec.isBidRequestValid(bid)).to.be.true;
2724
+ spec.buildRequests([bid]);
2725
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.VIDEO_DURATION_INVALID]: 2 } });
2726
+ });
2727
+
2728
+ it('should increment errors for errorCode', () => {
2729
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2730
+ bid.params.video = {};
2731
+
2732
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2733
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PROPERTY_NOT_INCLUDED]: 4 } });
2734
+
2735
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2736
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PROPERTY_NOT_INCLUDED]: 8 } });
2737
+ });
2738
+
2739
+ it('should add new errorCode to ixdiag.', () => {
2740
+ let bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2741
+ bid.params.size = ['400', 100];
2742
+
2743
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2744
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_SIZE_INVALID_FORMAT]: 1 } });
2745
+
2746
+ bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2747
+ bid.params.siteId = false;
2748
+
2749
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2750
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({
2751
+ [TODAY]: {
2752
+ [ERROR_CODES.BID_SIZE_INVALID_FORMAT]: 1,
2753
+ [ERROR_CODES.SITE_ID_INVALID_VALUE]: 1
2754
+ }
2755
+ });
2756
+ });
2757
+
2758
+ it('should clear errors with successful response', () => {
2759
+ const ixdiag = { [TODAY]: { '1': 1, '3': 8, '4': 1 } };
2760
+ setDataInLocalStorageStub(key, JSON.stringify(ixdiag));
2761
+
2762
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal(ixdiag);
2763
+
2764
+ const request = DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0];
2765
+ expect(spec.isBidRequestValid(request)).to.be.true;
2766
+
2767
+ const data = {
2768
+ ...utils.deepClone(DEFAULT_BIDDER_REQUEST_DATA[0]),
2769
+ r: JSON.stringify({
2770
+ id: '345',
2771
+ imp: [
2772
+ {
2773
+ id: '1a2b3c4e',
2774
+ }
2775
+ ],
2776
+ ext: {
2777
+ ixdiag: {
2778
+ err: {
2779
+ '4': 8
2780
+ }
2781
+ }
2782
+ }
2783
+ }),
2784
+ };
2785
+
2786
+ const validBidRequests = [
2787
+ DEFAULT_MULTIFORMAT_BANNER_VALID_BID[0],
2788
+ DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]
2789
+ ];
2790
+
2791
+ spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }, { data, validBidRequests });
2792
+
2793
+ expect(localStorageValues[key]).to.be.undefined;
2794
+ });
2795
+
2796
+ it('should clear errors after 7 day expiry errorCode', () => {
2797
+ const EXPIRED_DATE = '2019-12-12';
2798
+
2799
+ const ixdiag = { [EXPIRED_DATE]: { '1': 1, '3': 8, '4': 1 }, [TODAY]: { '3': 8, '4': 1 } };
2800
+ setDataInLocalStorageStub(key, JSON.stringify(ixdiag));
2801
+
2802
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2803
+ bid.params.size = ['400', 100];
2804
+
2805
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2806
+ expect(JSON.parse(localStorageValues[key])[EXPIRED_DATE]).to.be.undefined;
2807
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { '1': 1, '3': 8, '4': 1 } })
2808
+ });
2809
+
2810
+ it('should not save error data into localstorage if consent is not given', () => {
2811
+ config.setConfig({ deviceAccess: false });
2812
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
2813
+ bid.params.size = ['400', 100];
2814
+ expect(spec.isBidRequestValid(bid)).to.be.false;
2815
+ expect(localStorageValues[key]).to.be.undefined;
2816
+ });
2817
+ });
2527
2818
  });
@@ -53,7 +53,6 @@ describe('The Konduit vast wrapper module', function () {
53
53
  const callback = sinon.spy();
54
54
  processBids({ bid, callback });
55
55
  server.respond();
56
-
57
56
  expect(server.requests.length).to.equal(1);
58
57
 
59
58
  const requestBody = JSON.parse(server.requests[0].requestBody);
@@ -9,7 +9,8 @@ describe('limelightDigitalAdapter', function () {
9
9
  params: {
10
10
  host: 'exchange.ortb.net',
11
11
  adUnitId: 123,
12
- adUnitType: 'banner'
12
+ adUnitType: 'banner',
13
+ publisherId: 'perfectPublisher'
13
14
  },
14
15
  placementCode: 'placement_0',
15
16
  auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2',
@@ -41,7 +42,8 @@ describe('limelightDigitalAdapter', function () {
41
42
  params: {
42
43
  host: 'exchange.ortb.net',
43
44
  adUnitId: 789,
44
- adUnitType: 'video'
45
+ adUnitType: 'video',
46
+ publisherId: 'secondPerfectPublisher'
45
47
  },
46
48
  placementCode: 'placement_2',
47
49
  auctionId: 'e4771143-6aa7-41ec-8824-ced4342c96c8',
@@ -89,7 +91,7 @@ describe('limelightDigitalAdapter', function () {
89
91
  expect(data.deviceHeight).to.be.a('number')
90
92
  expect(data.secure).to.be.a('boolean')
91
93
  data.adUnits.forEach(adUnit => {
92
- expect(adUnit).to.have.all.keys('id', 'bidId', 'type', 'sizes', 'transactionId')
94
+ expect(adUnit).to.have.all.keys('id', 'bidId', 'type', 'sizes', 'transactionId', 'publisherId')
93
95
  expect(adUnit.id).to.be.a('number')
94
96
  expect(adUnit.bidId).to.be.a('string')
95
97
  expect(adUnit.type).to.be.a('string')
@@ -456,10 +458,10 @@ describe('limelightDigitalAdapter', function () {
456
458
  });
457
459
 
458
460
  function validateAdUnit(adUnit, bid) {
459
- expect(adUnit.id).to.equal(bid.params.adUnitId)
460
- expect(adUnit.bidId).to.equal(bid.bidId)
461
- expect(adUnit.type).to.equal(bid.params.adUnitType.toUpperCase())
462
- expect(adUnit.transactionId).to.equal(bid.transactionId)
461
+ expect(adUnit.id).to.equal(bid.params.adUnitId);
462
+ expect(adUnit.bidId).to.equal(bid.bidId);
463
+ expect(adUnit.type).to.equal(bid.params.adUnitType.toUpperCase());
464
+ expect(adUnit.transactionId).to.equal(bid.transactionId);
463
465
  let bidSizes = [];
464
466
  if (bid.mediaTypes) {
465
467
  if (bid.mediaTypes.video && bid.mediaTypes.video.playerSize) {
@@ -478,4 +480,5 @@ function validateAdUnit(adUnit, bid) {
478
480
  height: size[1]
479
481
  }
480
482
  }));
483
+ expect(adUnit.publisherId).to.equal(bid.params.publisherId);
481
484
  }
@@ -885,6 +885,37 @@ describe('Livewrapped adapter tests', function () {
885
885
  expect(data.rtbData.user.ext.eids).to.deep.equal(testbidRequest.bids[0].userIdAsEids);
886
886
  });
887
887
 
888
+ it('should merge user ids with existing ortb2', function() {
889
+ sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
890
+ sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);
891
+
892
+ let origGetConfig = config.getConfig;
893
+ sandbox.stub(config, 'getConfig').callsFake(function (key) {
894
+ if (key === 'ortb2') {
895
+ return {user: {ext: {prop: 'value'}}};
896
+ }
897
+ return origGetConfig.apply(config, arguments);
898
+ });
899
+
900
+ let testbidRequest = clone(bidderRequest);
901
+ delete testbidRequest.bids[0].params.userId;
902
+ testbidRequest.bids[0].userIdAsEids = [
903
+ {
904
+ 'source': 'pubcid.org',
905
+ 'uids': [{
906
+ 'id': 'publisher-common-id',
907
+ 'atype': 1
908
+ }]
909
+ }
910
+ ];
911
+
912
+ let result = spec.buildRequests(testbidRequest.bids, testbidRequest);
913
+ let data = JSON.parse(result.data);
914
+ var expected = {user: {ext: {prop: 'value', eids: testbidRequest.bids[0].userIdAsEids}}}
915
+
916
+ expect(data.rtbData).to.deep.equal(expected);
917
+ });
918
+
888
919
  it('should send schain object if available', function() {
889
920
  sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
890
921
  sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);
@@ -2,6 +2,7 @@ import {
2
2
  lotamePanoramaIdSubmodule,
3
3
  storage,
4
4
  } from 'modules/lotamePanoramaIdSystem.js';
5
+ import { uspDataHandler } from 'src/adapterManager.js';
5
6
  import * as utils from 'src/utils.js';
6
7
  import { server } from 'test/mocks/xhr.js';
7
8
  import sinon from 'sinon';
@@ -16,6 +17,7 @@ describe('LotameId', function() {
16
17
  let setLocalStorageStub;
17
18
  let removeFromLocalStorageStub;
18
19
  let timeStampStub;
20
+ let uspConsentDataStub;
19
21
 
20
22
  const nowTimestamp = new Date().getTime();
21
23
 
@@ -30,6 +32,7 @@ describe('LotameId', function() {
30
32
  'removeDataFromLocalStorage'
31
33
  );
32
34
  timeStampStub = sinon.stub(utils, 'timestamp').returns(nowTimestamp);
35
+ uspConsentDataStub = sinon.stub(uspDataHandler, 'getConsentData');
33
36
  });
34
37
 
35
38
  afterEach(function () {
@@ -40,6 +43,7 @@ describe('LotameId', function() {
40
43
  setLocalStorageStub.restore();
41
44
  removeFromLocalStorageStub.restore();
42
45
  timeStampStub.restore();
46
+ uspConsentDataStub.restore();
43
47
  });
44
48
 
45
49
  describe('caching initial data received from the remote server', function () {
@@ -726,4 +730,227 @@ describe('LotameId', function() {
726
730
  );
727
731
  });
728
732
  });
733
+
734
+ describe('with a custom client id', function () {
735
+ describe('with a client expiry set', function () {
736
+ beforeEach(function () {
737
+ getCookieStub
738
+ .withArgs('panoramaId_expiry_1234')
739
+ .returns(String(Date.now() + 500 * 1000));
740
+ });
741
+
742
+ describe('and an existing pano id', function() {
743
+ let submoduleCallback;
744
+ beforeEach(function () {
745
+ getCookieStub
746
+ .withArgs('panoramaId_expiry')
747
+ .returns(String(Date.now() + 100000));
748
+ getCookieStub
749
+ .withArgs('panoramaId')
750
+ .returns(
751
+ 'ca22992567e3cd4d116a5899b88a55d0d857a23610db939ae6ac13ba2335d87c'
752
+ );
753
+ submoduleCallback = lotamePanoramaIdSubmodule.getId(
754
+ {
755
+ params: {
756
+ clientId: '1234',
757
+ },
758
+ },
759
+ {
760
+ gdprApplies: false,
761
+ }
762
+ );
763
+ });
764
+
765
+ it('should not call the remote server when getId is called nor get an id', function () {
766
+ expect(submoduleCallback).to.be.eql({
767
+ id: undefined,
768
+ reason: 'NO_CLIENT_CONSENT',
769
+ });
770
+ });
771
+ });
772
+
773
+ describe('and no existing pano id', function () {
774
+ let submoduleCallback;
775
+
776
+ beforeEach(function () {
777
+ // Let the panoramaId_expiry be empty
778
+
779
+ submoduleCallback = lotamePanoramaIdSubmodule.getId(
780
+ {
781
+ params: {
782
+ clientId: '1234',
783
+ },
784
+ },
785
+ {
786
+ gdprApplies: false,
787
+ }
788
+ );
789
+ });
790
+
791
+ it('should not call the remote server nor return an id', function () {
792
+ expect(submoduleCallback).to.be.eql({
793
+ id: undefined,
794
+ reason: 'NO_CLIENT_CONSENT',
795
+ });
796
+ });
797
+ });
798
+ });
799
+
800
+ describe('with no client expiry set', function () {
801
+ describe('and no existing pano id', function () {
802
+ let request;
803
+ let callBackSpy = sinon.spy();
804
+
805
+ beforeEach(function () {
806
+ uspConsentDataStub.returns('1NNN');
807
+ let submoduleCallback = lotamePanoramaIdSubmodule.getId(
808
+ {
809
+ params: {
810
+ clientId: '1234',
811
+ },
812
+ },
813
+ {
814
+ gdprApplies: false,
815
+ }
816
+ ).callback;
817
+ submoduleCallback(callBackSpy);
818
+
819
+ request = server.requests[0];
820
+
821
+ request.respond(
822
+ 200,
823
+ responseHeader,
824
+ JSON.stringify({
825
+ profile_id: '4ec137245858469eb94a4e248f238694',
826
+ core_id:
827
+ 'ca22992567e3cd4d116a5899b88a55d0d857a23610db939ae6ac13ba2335d87f',
828
+ expiry_ts: 3600000,
829
+ })
830
+ );
831
+ });
832
+
833
+ it('should call the remote server when getId is called', function () {
834
+ expect(callBackSpy.calledOnce).to.be.true;
835
+ });
836
+
837
+ it('should pass the usp consent string and client id back', function () {
838
+ expect(request.url).to.be.eq(
839
+ 'https://id.crwdcntrl.net/id?gdpr_applies=false&us_privacy=1NNN&c=1234'
840
+ );
841
+ });
842
+
843
+ it('should NOT set an expiry for the client', function () {
844
+ sinon.assert.neverCalledWith(
845
+ setCookieStub,
846
+ 'panoramaId_expiry_1234',
847
+ sinon.match.number
848
+ );
849
+ });
850
+ });
851
+
852
+ describe('and an existing pano id', function () {
853
+ let submoduleCallback;
854
+
855
+ beforeEach(function () {
856
+ getCookieStub
857
+ .withArgs('panoramaId_expiry')
858
+ .returns(String(Date.now() + 100000));
859
+ getCookieStub
860
+ .withArgs('panoramaId')
861
+ .returns(
862
+ 'ca22992567e3cd4d116a5899b88a55d0d857a23610db939ae6ac13ba2335d87c'
863
+ );
864
+ submoduleCallback = lotamePanoramaIdSubmodule.getId(
865
+ {
866
+ params: {
867
+ clientId: '1234',
868
+ },
869
+ },
870
+ {
871
+ gdprApplies: false,
872
+ }
873
+ );
874
+ });
875
+
876
+ it('should not call the remote server but use the cached value', function () {
877
+ expect(submoduleCallback).to.be.eql({
878
+ id: 'ca22992567e3cd4d116a5899b88a55d0d857a23610db939ae6ac13ba2335d87c',
879
+ });
880
+ });
881
+
882
+ it('should NOT set an expiry for the client', function () {
883
+ sinon.assert.neverCalledWith(
884
+ setCookieStub,
885
+ 'panoramaId_expiry_1234',
886
+ sinon.match.number
887
+ );
888
+ });
889
+ });
890
+ });
891
+ describe('when client consent has errors', function () {
892
+ let request;
893
+ let callBackSpy = sinon.spy();
894
+
895
+ beforeEach(function () {
896
+ let submoduleCallback = lotamePanoramaIdSubmodule.getId(
897
+ {
898
+ params: {
899
+ clientId: '1234',
900
+ },
901
+ },
902
+ {
903
+ gdprApplies: false,
904
+ }
905
+ ).callback;
906
+ submoduleCallback(callBackSpy);
907
+
908
+ request = server.requests[0];
909
+
910
+ request.respond(
911
+ 200,
912
+ responseHeader,
913
+ JSON.stringify({
914
+ expiry_ts: 3600000,
915
+ errors: [111],
916
+ no_consent: 'CLIENT',
917
+ })
918
+ );
919
+ });
920
+
921
+ it('should call the remote server when getId is called', function () {
922
+ expect(callBackSpy.calledOnce).to.be.true;
923
+ });
924
+
925
+ it('should pass client id back', function () {
926
+ expect(request.url).to.be.eq(
927
+ 'https://id.crwdcntrl.net/id?gdpr_applies=false&c=1234'
928
+ );
929
+ });
930
+
931
+ it('should set the received expiry for the client', function() {
932
+ sinon.assert.calledWith(
933
+ setCookieStub,
934
+ 'panoramaId_expiry_1234',
935
+ 3600000
936
+ );
937
+ });
938
+
939
+ it('should not clear the cache for the panorama id', function() {
940
+ sinon.assert.neverCalledWith(
941
+ setCookieStub,
942
+ 'panoramaId',
943
+ sinon.match.any
944
+ );
945
+ });
946
+
947
+ it('should not clear the cache for the panorama id expiry', function () {
948
+ sinon.assert.neverCalledWith(
949
+ setCookieStub,
950
+ 'panoramaId_expiry',
951
+ sinon.match.any
952
+ );
953
+ });
954
+ });
955
+ });
729
956
  });