prebid.js 7.29.0 → 7.31.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 (173) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adkernelBidAdapter.js +1 -1
  7. package/dist/adrelevantisBidAdapter.js +1 -1
  8. package/dist/adtrgtmeBidAdapter.js +1 -1
  9. package/dist/adxcgBidAdapter.js +1 -1
  10. package/dist/ajaBidAdapter.js +1 -1
  11. package/dist/amxBidAdapter.js +1 -1
  12. package/dist/amxIdSystem.js +1 -1
  13. package/dist/appierAnalyticsAdapter.js +1 -1
  14. package/dist/appnexusBidAdapter.js +1 -1
  15. package/dist/asoBidAdapter.js +1 -1
  16. package/dist/axonixBidAdapter.js +1 -1
  17. package/dist/bidViewability.js +1 -1
  18. package/dist/bidglassBidAdapter.js +1 -1
  19. package/dist/big-richmediaBidAdapter.js +1 -1
  20. package/dist/bridgewellBidAdapter.js +1 -1
  21. package/dist/brightMountainMediaBidAdapter.js +1 -1
  22. package/dist/byDataAnalyticsAdapter.js +1 -1
  23. package/dist/carodaBidAdapter.js +1 -1
  24. package/dist/ccxBidAdapter.js +1 -1
  25. package/dist/chtnwBidAdapter.js +1 -1
  26. package/dist/colossussspBidAdapter.js +1 -1
  27. package/dist/concertBidAdapter.js +1 -1
  28. package/dist/confiantRtdProvider.js +1 -0
  29. package/dist/connectadBidAdapter.js +1 -1
  30. package/dist/consentManagement.js +1 -1
  31. package/dist/consentManagementGpp.js +1 -0
  32. package/dist/consumableBidAdapter.js +1 -1
  33. package/dist/conversantBidAdapter.js +1 -1
  34. package/dist/craftBidAdapter.js +1 -1
  35. package/dist/criteoBidAdapter.js +1 -1
  36. package/dist/datawrkzBidAdapter.js +1 -1
  37. package/dist/dfpAdServerVideo.js +1 -1
  38. package/dist/dspxBidAdapter.js +1 -1
  39. package/dist/eplanningBidAdapter.js +1 -1
  40. package/dist/feedadBidAdapter.js +1 -1
  41. package/dist/finativeBidAdapter.js +1 -1
  42. package/dist/glimpseBidAdapter.js +1 -1
  43. package/dist/gmosspBidAdapter.js +1 -1
  44. package/dist/goldbachBidAdapter.js +1 -1
  45. package/dist/gridBidAdapter.js +1 -1
  46. package/dist/gridNMBidAdapter.js +1 -1
  47. package/dist/gumgumBidAdapter.js +1 -1
  48. package/dist/h12mediaBidAdapter.js +1 -1
  49. package/dist/id5IdSystem.js +1 -1
  50. package/dist/improvedigitalBidAdapter.js +1 -1
  51. package/dist/inmarBidAdapter.js +1 -1
  52. package/dist/insticatorBidAdapter.js +1 -1
  53. package/dist/ixBidAdapter.js +1 -1
  54. package/dist/justpremiumBidAdapter.js +1 -1
  55. package/dist/konduitAnalyticsAdapter.js +1 -1
  56. package/dist/kueezBidAdapter.js +1 -1
  57. package/dist/kueezRtbBidAdapter.js +1 -1
  58. package/dist/lassoBidAdapter.js +1 -1
  59. package/dist/lifestreetBidAdapter.js +1 -1
  60. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  61. package/dist/logicadBidAdapter.js +1 -1
  62. package/dist/loglyliftBidAdapter.js +1 -1
  63. package/dist/magniteAnalyticsAdapter.js +1 -1
  64. package/dist/malltvAnalyticsAdapter.js +1 -1
  65. package/dist/marsmediaBidAdapter.js +1 -1
  66. package/dist/mediafuseBidAdapter.js +1 -1
  67. package/dist/mediasquareBidAdapter.js +1 -1
  68. package/dist/mgidBidAdapter.js +1 -1
  69. package/dist/minutemediaBidAdapter.js +1 -1
  70. package/dist/nexx360BidAdapter.js +1 -1
  71. package/dist/not-for-prod/prebid.js +127 -124
  72. package/dist/oguryBidAdapter.js +1 -1
  73. package/dist/onetagBidAdapter.js +1 -1
  74. package/dist/ooloAnalyticsAdapter.js +1 -1
  75. package/dist/outbrainBidAdapter.js +1 -1
  76. package/dist/parrableIdSystem.js +1 -1
  77. package/dist/pbsExtensions.js +1 -1
  78. package/dist/pixfutureBidAdapter.js +1 -1
  79. package/dist/prebid-core.js +1 -1
  80. package/dist/prebidServerBidAdapter.js +1 -1
  81. package/dist/publinkIdSystem.js +1 -1
  82. package/dist/pubmaticBidAdapter.js +1 -1
  83. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  84. package/dist/pxyzBidAdapter.js +1 -1
  85. package/dist/quantcastBidAdapter.js +1 -1
  86. package/dist/readpeakBidAdapter.js +1 -1
  87. package/dist/relaidoBidAdapter.js +1 -1
  88. package/dist/rhythmoneBidAdapter.js +1 -1
  89. package/dist/riseBidAdapter.js +1 -1
  90. package/dist/rtdModule.js +1 -1
  91. package/dist/rubiconAnalyticsAdapter.js +1 -1
  92. package/dist/rubiconBidAdapter.js +1 -1
  93. package/dist/seedingAllianceBidAdapter.js +1 -1
  94. package/dist/seedtagBidAdapter.js +1 -1
  95. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  96. package/dist/sharethroughBidAdapter.js +1 -1
  97. package/dist/shinezBidAdapter.js +1 -1
  98. package/dist/smaatoBidAdapter.js +1 -1
  99. package/dist/smartadserverBidAdapter.js +1 -1
  100. package/dist/smartxBidAdapter.js +1 -1
  101. package/dist/smilewantedBidAdapter.js +1 -1
  102. package/dist/sonobiBidAdapter.js +1 -1
  103. package/dist/sovrnAnalyticsAdapter.js +1 -1
  104. package/dist/sovrnBidAdapter.js +1 -1
  105. package/dist/sspBCBidAdapter.js +1 -1
  106. package/dist/sublimeBidAdapter.js +1 -1
  107. package/dist/synacormediaBidAdapter.js +1 -1
  108. package/dist/targetVideoBidAdapter.js +1 -1
  109. package/dist/teadsBidAdapter.js +1 -1
  110. package/dist/trionBidAdapter.js +1 -1
  111. package/dist/tripleliftBidAdapter.js +1 -1
  112. package/dist/ttdBidAdapter.js +1 -1
  113. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  114. package/dist/uid2IdSystem.js +1 -1
  115. package/dist/underdogmediaBidAdapter.js +1 -1
  116. package/dist/undertoneBidAdapter.js +1 -1
  117. package/dist/vidazooBidAdapter.js +1 -1
  118. package/dist/videobyteBidAdapter.js +1 -1
  119. package/dist/viouslyBidAdapter.js +1 -0
  120. package/dist/visxBidAdapter.js +1 -1
  121. package/dist/vuukleBidAdapter.js +1 -1
  122. package/dist/widespaceBidAdapter.js +1 -1
  123. package/dist/winrBidAdapter.js +1 -1
  124. package/dist/yahoosspBidAdapter.js +1 -1
  125. package/dist/yieldmoBidAdapter.js +1 -1
  126. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  127. package/integrationExamples/gpt/gpp_us_hello_world.html +124 -0
  128. package/integrationExamples/gpt/gpp_us_hello_world_iframe.html +12 -0
  129. package/integrationExamples/gpt/gpp_us_hello_world_iframe_subpage.html +140 -0
  130. package/karma.conf.maker.js +1 -1
  131. package/libraries/pbsExtensions/processors/adUnitCode.js +13 -0
  132. package/libraries/pbsExtensions/processors/pbs.js +5 -0
  133. package/modules/.submodules.json +1 -0
  134. package/modules/adkernelBidAdapter.js +2 -1
  135. package/modules/appnexusBidAdapter.js +23 -2
  136. package/modules/bidViewability.js +6 -1
  137. package/modules/ccxBidAdapter.js +3 -2
  138. package/modules/colossussspBidAdapter.js +8 -0
  139. package/modules/confiantRtdProvider.js +128 -0
  140. package/modules/confiantRtdProvider.md +45 -0
  141. package/modules/consentManagement.js +4 -4
  142. package/modules/consentManagementGpp.js +386 -0
  143. package/modules/datawrkzBidAdapter.js +24 -4
  144. package/modules/dfpAdServerVideo.js +6 -1
  145. package/modules/feedadBidAdapter.js +11 -3
  146. package/modules/gridBidAdapter.js +1 -2
  147. package/modules/lassoBidAdapter.js +2 -2
  148. package/modules/magniteAnalyticsAdapter.js +9 -1
  149. package/modules/onetagBidAdapter.js +20 -29
  150. package/modules/prebidServerBidAdapter/index.js +19 -8
  151. package/modules/prebidServerBidAdapter/ortbConverter.js +1 -0
  152. package/modules/rtdModule/index.js +2 -1
  153. package/modules/viouslyBidAdapter.js +209 -0
  154. package/modules/viouslyBidAdapter.md +35 -0
  155. package/package.json +1 -1
  156. package/src/adapterManager.js +11 -10
  157. package/src/adapters/bidderFactory.js +5 -5
  158. package/src/adloader.js +2 -1
  159. package/src/consentHandler.js +11 -0
  160. package/src/prebid.js +9 -9
  161. package/test/helpers/hookSetup.js +5 -0
  162. package/test/spec/modules/ViouslyBidAdapter_spec.js +378 -0
  163. package/test/spec/modules/appnexusBidAdapter_spec.js +46 -0
  164. package/test/spec/modules/colossussspBidAdapter_spec.js +89 -2
  165. package/test/spec/modules/confiantRtdProvider_spec.js +107 -0
  166. package/test/spec/modules/consentManagementGpp_spec.js +577 -0
  167. package/test/spec/modules/feedadBidAdapter_spec.js +38 -13
  168. package/test/spec/modules/gridBidAdapter_spec.js +0 -18
  169. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +36 -14
  170. package/test/spec/modules/onetagBidAdapter_spec.js +29 -23
  171. package/test/spec/modules/topicsFpdModule_spec.js +41 -22
  172. package/test/spec/ortbConverter/pbsExtensions/adUnitCode_spec.js +23 -0
  173. package/test/spec/unit/pbjs_api_spec.js +11 -0
@@ -358,14 +358,20 @@ describe('FeedAdAdapter', function () {
358
358
  const pixelSync2 = {type: 'image', url: 'the pixel url 2'};
359
359
  const iFrameSync1 = {type: 'iframe', url: 'the iFrame url 1'};
360
360
  const iFrameSync2 = {type: 'iframe', url: 'the iFrame url 2'};
361
+ const mockServerResponse = (content) => {
362
+ if (!(content instanceof Array)) {
363
+ content = [content];
364
+ }
365
+ return content.map(it => ({body: it}));
366
+ };
361
367
 
362
368
  it('should pass through the syncs out of the extension fields of the server response', function () {
363
- const serverResponse = [{
369
+ const serverResponse = mockServerResponse([{
364
370
  ext: {
365
371
  pixels: [pixelSync1, pixelSync2],
366
372
  iframes: [iFrameSync1, iFrameSync2],
367
373
  }
368
- }];
374
+ }]);
369
375
  const result = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, serverResponse)
370
376
  expect(result).to.deep.equal([
371
377
  pixelSync1,
@@ -376,7 +382,7 @@ describe('FeedAdAdapter', function () {
376
382
  });
377
383
 
378
384
  it('should concat the syncs of all responses', function () {
379
- const serverResponse = [{
385
+ const serverResponse = mockServerResponse([{
380
386
  ext: {
381
387
  pixels: [pixelSync1],
382
388
  iframes: [iFrameSync2],
@@ -391,7 +397,7 @@ describe('FeedAdAdapter', function () {
391
397
  ext: {
392
398
  pixels: [pixelSync2],
393
399
  }
394
- }];
400
+ }]);
395
401
  const result = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, serverResponse);
396
402
  expect(result).to.deep.equal([
397
403
  pixelSync1,
@@ -402,7 +408,7 @@ describe('FeedAdAdapter', function () {
402
408
  });
403
409
 
404
410
  it('should filter out duplicates', function () {
405
- const serverResponse = [{
411
+ const serverResponse = mockServerResponse([{
406
412
  ext: {
407
413
  pixels: [pixelSync1, pixelSync1],
408
414
  iframes: [iFrameSync2, iFrameSync2],
@@ -411,7 +417,7 @@ describe('FeedAdAdapter', function () {
411
417
  ext: {
412
418
  iframes: [iFrameSync2, iFrameSync2],
413
419
  }
414
- }];
420
+ }]);
415
421
  const result = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, serverResponse);
416
422
  expect(result).to.deep.equal([
417
423
  pixelSync1,
@@ -420,12 +426,12 @@ describe('FeedAdAdapter', function () {
420
426
  });
421
427
 
422
428
  it('should not include iFrame syncs if the option is disabled', function () {
423
- const serverResponse = [{
429
+ const serverResponse = mockServerResponse([{
424
430
  ext: {
425
431
  pixels: [pixelSync1, pixelSync2],
426
432
  iframes: [iFrameSync1, iFrameSync2],
427
433
  }
428
- }];
434
+ }]);
429
435
  const result = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, serverResponse);
430
436
  expect(result).to.deep.equal([
431
437
  pixelSync1,
@@ -434,12 +440,12 @@ describe('FeedAdAdapter', function () {
434
440
  });
435
441
 
436
442
  it('should not include pixel syncs if the option is disabled', function () {
437
- const serverResponse = [{
443
+ const serverResponse = mockServerResponse([{
438
444
  ext: {
439
445
  pixels: [pixelSync1, pixelSync2],
440
446
  iframes: [iFrameSync1, iFrameSync2],
441
447
  }
442
- }];
448
+ }]);
443
449
  const result = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, serverResponse);
444
450
  expect(result).to.deep.equal([
445
451
  iFrameSync1,
@@ -448,15 +454,34 @@ describe('FeedAdAdapter', function () {
448
454
  });
449
455
 
450
456
  it('should not include any syncs if the sync options are disabled or missing', function () {
451
- const serverResponse = [{
457
+ const serverResponse = mockServerResponse([{
452
458
  ext: {
453
459
  pixels: [pixelSync1, pixelSync2],
454
460
  iframes: [iFrameSync1, iFrameSync2],
455
461
  }
456
- }];
462
+ }]);
457
463
  const result = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false}, serverResponse);
458
464
  expect(result).to.deep.equal([]);
459
465
  });
466
+
467
+ it('should handle empty responses', function () {
468
+ const serverResponse = mockServerResponse([]);
469
+ const result = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, serverResponse)
470
+ expect(result).to.deep.equal([]);
471
+ });
472
+
473
+ it('should not throw if the server response is weird', function () {
474
+ const responses = [
475
+ mockServerResponse(null),
476
+ mockServerResponse('null'),
477
+ mockServerResponse(1234),
478
+ mockServerResponse({}),
479
+ mockServerResponse([{}, 123]),
480
+ ];
481
+ responses.forEach(it => {
482
+ expect(() => spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, it)).not.to.throw;
483
+ });
484
+ });
460
485
  });
461
486
 
462
487
  describe('event tracking calls', function () {
@@ -592,7 +617,7 @@ describe('FeedAdAdapter', function () {
592
617
  prebid_bid_id: bidId,
593
618
  prebid_transaction_id: transactionId,
594
619
  referer,
595
- sdk_version: '1.0.3'
620
+ sdk_version: '1.0.4'
596
621
  };
597
622
  subject(data);
598
623
  expect(server.requests.length).to.equal(1);
@@ -840,24 +840,6 @@ describe('TheMediaGrid Adapter', function () {
840
840
  expect(payload.site.content.id).to.equal(contentId);
841
841
  });
842
842
 
843
- it('should be right tmax when timeout in config is less then timeout in bidderRequest', function() {
844
- const getConfigStub = sinon.stub(config, 'getConfig').callsFake(
845
- arg => arg === 'bidderTimeout' ? 2000 : null);
846
- const [request] = spec.buildRequests([bidRequests[0]], bidderRequest);
847
- expect(request.data).to.be.an('string');
848
- const payload = parseRequest(request.data);
849
- expect(payload.tmax).to.equal(2000);
850
- getConfigStub.restore();
851
- });
852
- it('should be right tmax when timeout in bidderRequest is less then timeout in config', function() {
853
- const getConfigStub = sinon.stub(config, 'getConfig').callsFake(
854
- arg => arg === 'bidderTimeout' ? 5000 : null);
855
- const [request] = spec.buildRequests([bidRequests[0]], bidderRequest);
856
- expect(request.data).to.be.an('string');
857
- const payload = parseRequest(request.data);
858
- expect(payload.tmax).to.equal(3000);
859
- getConfigStub.restore();
860
- });
861
843
  it('should contain regs.coppa if coppa is true in config', function () {
862
844
  const getConfigStub = sinon.stub(config, 'getConfig').callsFake(
863
845
  arg => arg === 'coppa' ? true : null);
@@ -306,7 +306,7 @@ const ANALYTICS_MESSAGE = {
306
306
  describe('magnite analytics adapter', function () {
307
307
  let sandbox;
308
308
  let clock;
309
- let getDataFromLocalStorageStub, setDataInLocalStorageStub, localStorageIsEnabledStub;
309
+ let getDataFromLocalStorageStub, setDataInLocalStorageStub, localStorageIsEnabledStub, removeDataFromLocalStorageStub;
310
310
  let gptSlot0;
311
311
  let gptSlotRenderEnded0;
312
312
  beforeEach(function () {
@@ -325,6 +325,7 @@ describe('magnite analytics adapter', function () {
325
325
  getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage');
326
326
  setDataInLocalStorageStub = sinon.stub(storage, 'setDataInLocalStorage');
327
327
  localStorageIsEnabledStub = sinon.stub(storage, 'localStorageIsEnabled');
328
+ removeDataFromLocalStorageStub = sinon.stub(storage, 'removeDataFromLocalStorage')
328
329
  sandbox = sinon.sandbox.create();
329
330
 
330
331
  localStorageIsEnabledStub.returns(true);
@@ -355,6 +356,7 @@ describe('magnite analytics adapter', function () {
355
356
  getDataFromLocalStorageStub.restore();
356
357
  setDataInLocalStorageStub.restore();
357
358
  localStorageIsEnabledStub.restore();
359
+ removeDataFromLocalStorageStub.restore();
358
360
  magniteAdapter.disableAnalytics();
359
361
  });
360
362
 
@@ -1932,19 +1934,21 @@ describe('magnite analytics adapter', function () {
1932
1934
  });
1933
1935
  });
1934
1936
 
1935
- it('getHostNameFromReferer correctly grabs hostname from an input URL', function () {
1936
- let inputUrl = 'https://www.prebid.org/some/path?pbjs_debug=true';
1937
- expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.org');
1938
- inputUrl = 'https://www.prebid.com/some/path?pbjs_debug=true';
1939
- expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.com');
1940
- inputUrl = 'https://prebid.org/some/path?pbjs_debug=true';
1941
- expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org');
1942
- inputUrl = 'http://xn--p8j9a0d9c9a.xn--q9jyb4c/';
1943
- expect(typeof getHostNameFromReferer(inputUrl)).to.equal('string');
1944
-
1945
- // not non-UTF char's in query / path which break if noDecodeWholeURL not set
1946
- inputUrl = 'https://prebid.org/search_results/%95x%8Em%92%CA/?category=000';
1947
- expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org');
1937
+ describe('getHostNameFromReferer', () => {
1938
+ it('correctly grabs hostname from an input URL', function () {
1939
+ let inputUrl = 'https://www.prebid.org/some/path?pbjs_debug=true';
1940
+ expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.org');
1941
+ inputUrl = 'https://www.prebid.com/some/path?pbjs_debug=true';
1942
+ expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.com');
1943
+ inputUrl = 'https://prebid.org/some/path?pbjs_debug=true';
1944
+ expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org');
1945
+ inputUrl = 'http://xn--p8j9a0d9c9a.xn--q9jyb4c/';
1946
+ expect(typeof getHostNameFromReferer(inputUrl)).to.equal('string');
1947
+
1948
+ // not non-UTF char's in query / path which break if noDecodeWholeURL not set
1949
+ inputUrl = 'https://prebid.org/search_results/%95x%8Em%92%CA/?category=000';
1950
+ expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org');
1951
+ });
1948
1952
  });
1949
1953
 
1950
1954
  describe(`handle currency conversions`, () => {
@@ -1985,4 +1989,22 @@ describe('magnite analytics adapter', function () {
1985
1989
  expect(bidResponseObj.bidPriceUSD).to.equal(0);
1986
1990
  });
1987
1991
  });
1992
+
1993
+ describe('onDataDeletionRequest', () => {
1994
+ it('attempts to delete the magnite cookie when local storage is enabled', () => {
1995
+ magniteAdapter.onDataDeletionRequest();
1996
+
1997
+ expect(removeDataFromLocalStorageStub.getCall(0).args[0]).to.equal('mgniSession');
1998
+ });
1999
+
2000
+ it('throws an error if it cannot access the cookie', (done) => {
2001
+ localStorageIsEnabledStub.returns(false);
2002
+ try {
2003
+ magniteAdapter.onDataDeletionRequest();
2004
+ } catch (error) {
2005
+ expect(error.message).to.equal('Unable to access local storage, no data deleted');
2006
+ done();
2007
+ }
2008
+ })
2009
+ });
1988
2010
  });
@@ -1,8 +1,8 @@
1
1
  import { spec, isValid, hasTypeVideo, isSchainValid } from 'modules/onetagBidAdapter.js';
2
2
  import { expect } from 'chai';
3
- import {find} from 'src/polyfill.js';
3
+ import { find } from 'src/polyfill.js';
4
4
  import { BANNER, VIDEO } from 'src/mediaTypes.js';
5
- import {INSTREAM, OUTSTREAM} from 'src/video.js';
5
+ import { INSTREAM, OUTSTREAM } from 'src/video.js';
6
6
 
7
7
  describe('onetag', function () {
8
8
  function createBid() {
@@ -122,14 +122,14 @@ describe('onetag', function () {
122
122
  it('Should return true when correct multi format bid is passed', function () {
123
123
  expect(spec.isBidRequestValid(createMultiFormatBid())).to.be.true;
124
124
  });
125
- it('Should split multi format bid into two single format bid with same bidId', function() {
126
- const bids = JSON.parse(spec.buildRequests([ createMultiFormatBid() ]).data).bids;
125
+ it('Should split multi format bid into two single format bid with same bidId', function () {
126
+ const bids = JSON.parse(spec.buildRequests([createMultiFormatBid()]).data).bids;
127
127
  expect(bids.length).to.equal(2);
128
128
  expect(bids[0].bidId).to.equal(bids[1].bidId);
129
129
  });
130
- it('Should retrieve correct request bid when extracting video request data', function() {
130
+ it('Should retrieve correct request bid when extracting video request data', function () {
131
131
  const requestBid = createMultiFormatBid();
132
- const multiFormatRequest = spec.buildRequests([ requestBid ]);
132
+ const multiFormatRequest = spec.buildRequests([requestBid]);
133
133
  const serverResponse = {
134
134
  body: {
135
135
  bids: [
@@ -173,24 +173,30 @@ describe('onetag', function () {
173
173
  const data = JSON.parse(d);
174
174
  it('Should contain all keys', function () {
175
175
  expect(data).to.be.an('object');
176
- expect(data).to.include.all.keys('location', 'referrer', 'masked', 'sHeight', 'sWidth', 'docHeight', 'wHeight', 'wWidth', 'oHeight', 'oWidth', 'aWidth', 'aHeight', 'sLeft', 'sTop', 'hLength', 'bids', 'docHidden', 'xOffset', 'yOffset', 'timing', 'version');
177
- expect(data.location).to.be.a('string');
178
- expect(data.masked).to.be.oneOf([0, 1, 2]);
176
+ expect(data).to.include.all.keys('location', 'referrer', 'stack', 'numIframes', 'sHeight', 'sWidth', 'docHeight', 'wHeight', 'wWidth', 'oHeight', 'oWidth', 'aWidth', 'aHeight', 'sLeft', 'sTop', 'hLength', 'bids', 'docHidden', 'xOffset', 'yOffset', 'networkConnectionType', 'networkEffectiveConnectionType', 'timing', 'version');
177
+ expect(data.location).to.satisfy(function (value) {
178
+ return value === null || typeof value === 'string';
179
+ });
179
180
  expect(data.referrer).to.satisfy(referrer => referrer === null || typeof referrer === 'string');
181
+ expect(data.stack).to.be.an('array');
182
+ expect(data.numIframes).to.be.a('number');
180
183
  expect(data.sHeight).to.be.a('number');
181
184
  expect(data.sWidth).to.be.a('number');
182
185
  expect(data.wWidth).to.be.a('number');
183
186
  expect(data.wHeight).to.be.a('number');
184
187
  expect(data.oHeight).to.be.a('number');
185
188
  expect(data.oWidth).to.be.a('number');
186
- expect(data.ancestorOrigin).to.satisfy(function (value) {
187
- return value === null || typeof value === 'string';
188
- });
189
189
  expect(data.aWidth).to.be.a('number');
190
190
  expect(data.aHeight).to.be.a('number');
191
191
  expect(data.sLeft).to.be.a('number');
192
192
  expect(data.sTop).to.be.a('number');
193
193
  expect(data.hLength).to.be.a('number');
194
+ expect(data.networkConnectionType).to.satisfy(function (value) {
195
+ return value === null || typeof value === 'string'
196
+ });
197
+ expect(data.networkEffectiveConnectionType).to.satisfy(function (value) {
198
+ return value === null || typeof value === 'string'
199
+ });
194
200
  expect(data.bids).to.be.an('array');
195
201
  expect(data.version).to.have.all.keys('prebid', 'adapter');
196
202
  const bids = data['bids'];
@@ -231,14 +237,14 @@ describe('onetag', function () {
231
237
  expect(bid.pubId).to.be.a('string');
232
238
  }
233
239
  });
234
- } catch (e) {}
240
+ } catch (e) { }
235
241
  it('Returns empty data if no valid requests are passed', function () {
236
242
  serverRequest = spec.buildRequests([]);
237
243
  let dataString = serverRequest.data;
238
244
  try {
239
245
  let dataObj = JSON.parse(dataString);
240
246
  expect(dataObj.bids).to.be.an('array').that.is.empty;
241
- } catch (e) {}
247
+ } catch (e) { }
242
248
  });
243
249
  it('should send GDPR consent data', function () {
244
250
  let consentString = 'consentString';
@@ -287,7 +293,7 @@ describe('onetag', function () {
287
293
  let dataItem = interpretedResponse[i];
288
294
  expect(dataItem).to.include.all.keys('requestId', 'cpm', 'width', 'height', 'ttl', 'creativeId', 'netRevenue', 'currency', 'meta', 'dealId');
289
295
  if (dataItem.meta.mediaType === VIDEO) {
290
- const {context} = find(requestData.bids, (item) => item.bidId === dataItem.requestId);
296
+ const { context } = find(requestData.bids, (item) => item.bidId === dataItem.requestId);
291
297
  if (context === INSTREAM) {
292
298
  expect(dataItem).to.include.all.keys('videoCacheKey', 'vastUrl');
293
299
  expect(dataItem.vastUrl).to.be.a('string');
@@ -321,7 +327,7 @@ describe('onetag', function () {
321
327
  describe('getUserSyncs', function () {
322
328
  const sync_endpoint = 'https://onetag-sys.com/usync/';
323
329
  it('Returns an iframe if iframeEnabled is true', function () {
324
- const syncs = spec.getUserSyncs({iframeEnabled: true});
330
+ const syncs = spec.getUserSyncs({ iframeEnabled: true });
325
331
  expect(syncs).to.be.an('array');
326
332
  expect(syncs.length).to.equal(1);
327
333
  expect(syncs[0].type).to.equal('iframe');
@@ -383,16 +389,16 @@ describe('onetag', function () {
383
389
  expect(isSchainValid(undefined)).to.be.false;
384
390
  });
385
391
  it('Should return false when schain is missing nodes key', function () {
386
- const schain = {'otherKey': 'otherValue'};
392
+ const schain = { 'otherKey': 'otherValue' };
387
393
  expect(isSchainValid(schain)).to.be.false;
388
394
  });
389
395
  it('Should return false when schain is missing one of the required SupplyChainNode attribute', function () {
390
- const missingAsiNode = {'sid': '00001', 'hp': 1};
391
- const missingSidNode = {'asi': 'indirectseller.com', 'hp': 1};
392
- const missingHpNode = {'asi': 'indirectseller.com', 'sid': '00001'};
393
- expect(isSchainValid({'config': {'nodes': [missingAsiNode]}})).to.be.false;
394
- expect(isSchainValid({'config': {'nodes': [missingSidNode]}})).to.be.false;
395
- expect(isSchainValid({'config': {'nodes': [missingHpNode]}})).to.be.false;
396
+ const missingAsiNode = { 'sid': '00001', 'hp': 1 };
397
+ const missingSidNode = { 'asi': 'indirectseller.com', 'hp': 1 };
398
+ const missingHpNode = { 'asi': 'indirectseller.com', 'sid': '00001' };
399
+ expect(isSchainValid({ 'config': { 'nodes': [missingAsiNode] } })).to.be.false;
400
+ expect(isSchainValid({ 'config': { 'nodes': [missingSidNode] } })).to.be.false;
401
+ expect(isSchainValid({ 'config': { 'nodes': [missingHpNode] } })).to.be.false;
396
402
  });
397
403
  it('Should return true when schain contains all required attributes', function () {
398
404
  const validSchain = {
@@ -1,4 +1,12 @@
1
- import {getTopics, getTopicsData, processFpd, hasGDPRConsent, getCachedTopics, receiveMessage, topicStorageName} from '../../../modules/topicsFpdModule.js';
1
+ import {
2
+ getTopics,
3
+ getTopicsData,
4
+ processFpd,
5
+ hasGDPRConsent,
6
+ getCachedTopics,
7
+ receiveMessage,
8
+ topicStorageName
9
+ } from '../../../modules/topicsFpdModule.js';
2
10
  import {deepClone, safeJSONParse} from '../../../src/utils.js';
3
11
  import {gdprDataHandler} from 'src/adapterManager.js';
4
12
  import {getCoreStorageManager} from 'src/storageManager.js';
@@ -9,14 +17,14 @@ describe('getTopicsData', () => {
9
17
  topic,
10
18
  taxonomyVersion: taxv,
11
19
  modelVersion: modelv
12
- }
20
+ };
13
21
  }
14
22
 
15
23
  function byTaxClass(segments) {
16
24
  return segments.reduce((memo, segment) => {
17
25
  memo[`${segment.ext.segtax}:${segment.ext.segclass}`] = segment;
18
26
  return memo;
19
- }, {})
27
+ }, {});
20
28
  }
21
29
 
22
30
  [
@@ -146,16 +154,16 @@ describe('getTopicsData', () => {
146
154
  Object.entries(byTaxClass(actual)).forEach(([key, datum]) => {
147
155
  sinon.assert.match(datum, expected[key]);
148
156
  expect(datum.name).to.equal('mockName');
149
- })
157
+ });
150
158
  });
151
159
 
152
160
  it('should not set name if null', () => {
153
161
  getTopicsData(null, topics).forEach((data) => {
154
162
  expect(data.hasOwnProperty('name')).to.be.false;
155
- })
156
- })
157
- })
158
- })
163
+ });
164
+ });
165
+ });
166
+ });
159
167
  });
160
168
 
161
169
  describe('getTopics', () => {
@@ -169,11 +177,13 @@ describe('getTopics', () => {
169
177
  'document that throws on featurePolicy': {
170
178
  browsingTopics: sinon.stub(),
171
179
  get featurePolicy() {
172
- throw new Error()
180
+ throw new Error();
173
181
  }
174
182
  },
175
183
  'document that throws on browsingTopics': {
176
- browsingTopics: sinon.stub().callsFake(() => { throw new Error(); }),
184
+ browsingTopics: sinon.stub().callsFake(() => {
185
+ throw new Error();
186
+ }),
177
187
  featurePolicy: {
178
188
  allowsFeature: sinon.stub().returns(true)
179
189
  }
@@ -183,11 +193,11 @@ describe('getTopics', () => {
183
193
  return getTopics(doc).then((topics) => {
184
194
  expect(topics).to.eql([]);
185
195
  });
186
- })
196
+ });
187
197
  });
188
198
 
189
199
  it('should call `document.browsingTopics` when allowed', () => {
190
- const topics = ['t1', 't2']
200
+ const topics = ['t1', 't2'];
191
201
  return getTopics({
192
202
  browsingTopics: sinon.stub().returns(Promise.resolve(topics)),
193
203
  featurePolicy: {
@@ -195,9 +205,9 @@ describe('getTopics', () => {
195
205
  }
196
206
  }).then((actual) => {
197
207
  expect(actual).to.eql(topics);
198
- })
199
- })
200
- })
208
+ });
209
+ });
210
+ });
201
211
 
202
212
  describe('processFpd', () => {
203
213
  const mockData = [
@@ -244,7 +254,7 @@ describe('Topics Module GDPR consent check', () => {
244
254
  let gdprDataHdlrStub;
245
255
  beforeEach(() => {
246
256
  gdprDataHdlrStub = sinon.stub(gdprDataHandler, 'getConsentData');
247
- })
257
+ });
248
258
 
249
259
  afterEach(() => {
250
260
  gdprDataHdlrStub.restore();
@@ -261,7 +271,7 @@ describe('Topics Module GDPR consent check', () => {
261
271
  expect(hasGDPRConsent()).to.equal(false);
262
272
  });
263
273
 
264
- it("should return true when GDPR doesn't apply", () => {
274
+ it('should return true when GDPR doesn\'t apply', () => {
265
275
  const consentString = 'CPi8wgAPi8wgAADABBENCrCsAP_AAH_AAAAAISNB7D==';
266
276
  const consentConfig = {
267
277
  consentString: consentString,
@@ -365,7 +375,7 @@ describe('getCachedTopics()', () => {
365
375
  const evt = {
366
376
  data: '{"segment":{"domain":"ads.pubmatic.com","topics":[{"configVersion":"chrome.1","modelVersion":"2206021246","taxonomyVersion":"1","topic":165,"version":"chrome.1:1:2206021246"}],"bidder":"pubmatic"},"date":1669743901858}',
367
377
  origin: 'https://ads.pubmatic.com'
368
- }
378
+ };
369
379
 
370
380
  let gdprDataHdlrStub;
371
381
  beforeEach(() => {
@@ -378,14 +388,23 @@ describe('getCachedTopics()', () => {
378
388
  });
379
389
 
380
390
  it('should return segments for bidder if GDPR consent is true and there is cached segments stored which is not expired', () => {
381
- let storedSegments = '[["pubmatic",{"2206021246":{"ext":{"segtax":600,"segclass":"2206021246"},"segment":[{"id":"243"},{"id":"265"}],"name":"ads.pubmatic.com"},"lastUpdated":1669719242027}]]';
391
+ const storedSegments = JSON.stringify(
392
+ [['pubmatic', {
393
+ '2206021246': {
394
+ 'ext': {'segtax': 600, 'segclass': '2206021246'},
395
+ 'segment': [{'id': '243'}, {'id': '265'}],
396
+ 'name': 'ads.pubmatic.com'
397
+ },
398
+ 'lastUpdated': new Date().getTime()
399
+ }]]
400
+ );
382
401
  storage.setDataInLocalStorage(topicStorageName, storedSegments);
383
402
  gdprDataHdlrStub.returns(consentConfig);
384
403
  assert.deepEqual(getCachedTopics(), expected);
385
404
  });
386
405
 
387
406
  it('should return empty segments for bidder if GDPR consent is true and there is cached segments stored which is expired', () => {
388
- let storedSegments = '[["pubmatic",{"2206021246":{"ext":{"segtax":600,"segclass":"2206021246"},"segment":[{"id":"243"},{"id":"265"}],"name":"ads.pubmatic.com"},"lastUpdated":1659719242027}]]';
407
+ let storedSegments = '[["pubmatic",{"2206021246":{"ext":{"segtax":600,"segclass":"2206021246"},"segment":[{"id":"243"},{"id":"265"}],"name":"ads.pubmatic.com"},"lastUpdated":10}]]';
389
408
  storage.setDataInLocalStorage(topicStorageName, storedSegments);
390
409
  gdprDataHdlrStub.returns(consentConfig);
391
410
  assert.deepEqual(getCachedTopics(), []);
@@ -394,7 +413,7 @@ describe('getCachedTopics()', () => {
394
413
  it('should stored segments if receiveMessage event is triggerred with segment data', () => {
395
414
  return processFpd({}, {global: {}}, {data: Promise.resolve(mockData)})
396
415
  .then(({global}) => {
397
- receiveMessage(evt)
416
+ receiveMessage(evt);
398
417
  let segments = new Map(safeJSONParse(storage.getDataFromLocalStorage(topicStorageName)));
399
418
  expect(segments.has('pubmatic')).to.equal(true);
400
419
  });
@@ -410,4 +429,4 @@ describe('getCachedTopics()', () => {
410
429
  expect(segments.get('pubmatic')[2206021246].segment.length).to.equal(1);
411
430
  });
412
431
  });
413
- })
432
+ });
@@ -0,0 +1,23 @@
1
+ import {setImpAdUnitCode} from '../../../../libraries/pbsExtensions/processors/adUnitCode.js';
2
+
3
+ describe('pbjs -> ortb adunit code to imp[].ext.prebid.adunitcode', () => {
4
+ function setImp(bidRequest) {
5
+ const imp = {};
6
+ setImpAdUnitCode(imp, bidRequest);
7
+ return imp;
8
+ }
9
+
10
+ it('it sets adunitcode in ext.prebid.adunitcode when adUnitCode is present', () => {
11
+ expect(setImp({bidder: 'mockBidder', adUnitCode: 'mockAdUnit'})).to.eql({
12
+ 'ext': {
13
+ 'prebid': {
14
+ 'adunitcode': 'mockAdUnit'
15
+ }
16
+ }
17
+ })
18
+ });
19
+
20
+ it('does not set adunitcode in ext.prebid.adunitcode if adUnit is undefined', () => {
21
+ expect(setImp({bidder: 'mockBidder'})).to.eql({});
22
+ });
23
+ });
@@ -1810,6 +1810,16 @@ describe('Unit: Prebid Module', function () {
1810
1810
  })
1811
1811
  });
1812
1812
 
1813
+ it('filtering adUnits by adUnitCodes', () => {
1814
+ $$PREBID_GLOBAL$$.requestBids({
1815
+ adUnits: [{code: 'one'}, {code: 'two'}],
1816
+ adUnitCodes: 'two'
1817
+ });
1818
+ sinon.assert.calledWith(startAuctionStub, sinon.match({
1819
+ adUnits: [{code: 'two'}]
1820
+ }));
1821
+ });
1822
+
1813
1823
  it('passing bidder-specific FPD as ortb2Fragments.bidder', () => {
1814
1824
  configObj.setBidderConfig({
1815
1825
  bidders: ['bidderA', 'bidderC'],
@@ -1869,6 +1879,7 @@ describe('Unit: Prebid Module', function () {
1869
1879
  mediaTypes: {banner: {sizes: [[300, 250]]}},
1870
1880
  bids: [{bidder: 'bd'}]
1871
1881
  }],
1882
+ adUnitCodes: ['au'],
1872
1883
  ortb2Fragments
1873
1884
  });
1874
1885
  sinon.assert.calledWith(newAuctionStub, sinon.match({