prebid.js 7.40.0 → 7.41.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 (167) 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/adrelevantisBidAdapter.js +1 -1
  7. package/dist/adtrgtmeBidAdapter.js +1 -1
  8. package/dist/aduptechBidAdapter.js +1 -1
  9. package/dist/adxcgBidAdapter.js +1 -1
  10. package/dist/adyoulikeBidAdapter.js +1 -1
  11. package/dist/ajaBidAdapter.js +1 -1
  12. package/dist/amxBidAdapter.js +1 -1
  13. package/dist/amxIdSystem.js +1 -1
  14. package/dist/appierAnalyticsAdapter.js +1 -1
  15. package/dist/appnexusBidAdapter.js +1 -1
  16. package/dist/asoBidAdapter.js +1 -1
  17. package/dist/axonixBidAdapter.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/browsiBidAdapter.js +1 -0
  23. package/dist/carodaBidAdapter.js +1 -1
  24. package/dist/chtnwBidAdapter.js +1 -1
  25. package/dist/cleanmedianetBidAdapter.js +1 -1
  26. package/dist/concertBidAdapter.js +1 -1
  27. package/dist/connectadBidAdapter.js +1 -1
  28. package/dist/consumableBidAdapter.js +1 -1
  29. package/dist/conversantAnalyticsAdapter.js +1 -1
  30. package/dist/conversantBidAdapter.js +1 -1
  31. package/dist/craftBidAdapter.js +1 -1
  32. package/dist/criteoBidAdapter.js +1 -1
  33. package/dist/cwireBidAdapter.js +1 -1
  34. package/dist/dfpAdServerVideo.js +1 -1
  35. package/dist/dspxBidAdapter.js +1 -1
  36. package/dist/eplanningBidAdapter.js +1 -1
  37. package/dist/feedadBidAdapter.js +1 -1
  38. package/dist/finativeBidAdapter.js +1 -1
  39. package/dist/freewheel-sspBidAdapter.js +1 -1
  40. package/dist/glimpseBidAdapter.js +1 -1
  41. package/dist/gmosspBidAdapter.js +1 -1
  42. package/dist/goldbachBidAdapter.js +1 -1
  43. package/dist/gridBidAdapter.js +1 -1
  44. package/dist/gridNMBidAdapter.js +1 -1
  45. package/dist/gumgumBidAdapter.js +1 -1
  46. package/dist/h12mediaBidAdapter.js +1 -1
  47. package/dist/id5IdSystem.js +1 -1
  48. package/dist/improvedigitalBidAdapter.js +1 -1
  49. package/dist/inmarBidAdapter.js +1 -1
  50. package/dist/insticatorBidAdapter.js +1 -1
  51. package/dist/ixBidAdapter.js +1 -1
  52. package/dist/justpremiumBidAdapter.js +1 -1
  53. package/dist/kargoBidAdapter.js +1 -1
  54. package/dist/konduitAnalyticsAdapter.js +1 -1
  55. package/dist/kueezBidAdapter.js +1 -1
  56. package/dist/kueezRtbBidAdapter.js +1 -1
  57. package/dist/lassoBidAdapter.js +1 -1
  58. package/dist/lifestreetBidAdapter.js +1 -1
  59. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  60. package/dist/logicadBidAdapter.js +1 -1
  61. package/dist/loglyliftBidAdapter.js +1 -1
  62. package/dist/magniteAnalyticsAdapter.js +1 -1
  63. package/dist/malltvAnalyticsAdapter.js +1 -1
  64. package/dist/marsmediaBidAdapter.js +1 -1
  65. package/dist/mediafuseBidAdapter.js +1 -1
  66. package/dist/mediasquareBidAdapter.js +1 -1
  67. package/dist/mgidBidAdapter.js +1 -1
  68. package/dist/minutemediaBidAdapter.js +1 -1
  69. package/dist/minutemediaplusBidAdapter.js +1 -1
  70. package/dist/missenaBidAdapter.js +1 -1
  71. package/dist/nexx360BidAdapter.js +1 -1
  72. package/dist/nobidBidAdapter.js +1 -1
  73. package/dist/not-for-prod/prebid.js +130 -129
  74. package/dist/oguryBidAdapter.js +1 -1
  75. package/dist/onetagBidAdapter.js +1 -1
  76. package/dist/ooloAnalyticsAdapter.js +1 -1
  77. package/dist/optidigitalBidAdapter.js +1 -1
  78. package/dist/outbrainBidAdapter.js +1 -1
  79. package/dist/parrableIdSystem.js +1 -1
  80. package/dist/permutiveRtdProvider.js +1 -1
  81. package/dist/pixfutureBidAdapter.js +1 -1
  82. package/dist/prebid-core.js +1 -1
  83. package/dist/publinkIdSystem.js +1 -1
  84. package/dist/pubmaticBidAdapter.js +1 -1
  85. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  86. package/dist/pubwiseBidAdapter.js +1 -1
  87. package/dist/pxyzBidAdapter.js +1 -1
  88. package/dist/quantcastBidAdapter.js +1 -1
  89. package/dist/readpeakBidAdapter.js +1 -1
  90. package/dist/relaidoBidAdapter.js +1 -1
  91. package/dist/rhythmoneBidAdapter.js +1 -1
  92. package/dist/riseBidAdapter.js +1 -1
  93. package/dist/rubiconAnalyticsAdapter.js +1 -1
  94. package/dist/rubiconBidAdapter.js +1 -1
  95. package/dist/seedingAllianceBidAdapter.js +1 -1
  96. package/dist/seedtagBidAdapter.js +1 -1
  97. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  98. package/dist/sharethroughBidAdapter.js +1 -1
  99. package/dist/shinezBidAdapter.js +1 -1
  100. package/dist/smaatoBidAdapter.js +1 -1
  101. package/dist/smartadserverBidAdapter.js +1 -1
  102. package/dist/smartxBidAdapter.js +1 -1
  103. package/dist/smilewantedBidAdapter.js +1 -1
  104. package/dist/sonobiBidAdapter.js +1 -1
  105. package/dist/sovrnAnalyticsAdapter.js +1 -1
  106. package/dist/sovrnBidAdapter.js +1 -1
  107. package/dist/sspBCBidAdapter.js +1 -1
  108. package/dist/stvBidAdapter.js +1 -0
  109. package/dist/sublimeBidAdapter.js +1 -1
  110. package/dist/synacormediaBidAdapter.js +1 -1
  111. package/dist/targetVideoBidAdapter.js +1 -1
  112. package/dist/teadsBidAdapter.js +1 -1
  113. package/dist/trionBidAdapter.js +1 -1
  114. package/dist/tripleliftBidAdapter.js +1 -1
  115. package/dist/ttdBidAdapter.js +1 -1
  116. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  117. package/dist/uid2IdSystem.js +1 -1
  118. package/dist/underdogmediaBidAdapter.js +1 -1
  119. package/dist/undertoneBidAdapter.js +1 -1
  120. package/dist/vidazooBidAdapter.js +1 -1
  121. package/dist/videobyteBidAdapter.js +1 -1
  122. package/dist/visxBidAdapter.js +1 -1
  123. package/dist/vuukleBidAdapter.js +1 -1
  124. package/dist/widespaceBidAdapter.js +1 -1
  125. package/dist/winrBidAdapter.js +1 -1
  126. package/dist/yahoosspBidAdapter.js +1 -1
  127. package/dist/yandexBidAdapter.js +1 -1
  128. package/dist/yieldmoBidAdapter.js +1 -1
  129. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  130. package/integrationExamples/gpt/x-domain/creative.html +1 -1
  131. package/modules/aduptechBidAdapter.js +43 -37
  132. package/modules/browsiBidAdapter.js +171 -0
  133. package/modules/browsiBidAdapter.md +38 -0
  134. package/modules/cleanmedianetBidAdapter.js +191 -126
  135. package/modules/cleanmedianetBidAdapter.md +64 -18
  136. package/modules/conversantBidAdapter.js +4 -0
  137. package/modules/dfpAdServerVideo.js +8 -8
  138. package/modules/freewheel-sspBidAdapter.js +9 -0
  139. package/modules/gridBidAdapter.js +12 -1
  140. package/modules/ixBidAdapter.js +1 -1
  141. package/modules/missenaBidAdapter.js +2 -1
  142. package/modules/neuwoRtdProvider.js +1 -1
  143. package/modules/nobidBidAdapter.js +13 -2
  144. package/modules/nobidBidAdapter.md +2 -2
  145. package/modules/permutiveRtdProvider.js +8 -2
  146. package/modules/pubwiseBidAdapter.js +265 -33
  147. package/modules/stvBidAdapter.js +330 -0
  148. package/modules/stvBidAdapter.md +62 -0
  149. package/modules/yandexBidAdapter.js +259 -71
  150. package/modules/yandexBidAdapter.md +52 -15
  151. package/package.json +1 -1
  152. package/src/videoCache.js +4 -4
  153. package/test/spec/modules/browsiBidAdapter_spec.js +209 -0
  154. package/test/spec/modules/cleanmedianetBidAdapter_spec.js +462 -407
  155. package/test/spec/modules/conversantBidAdapter_spec.js +8 -0
  156. package/test/spec/modules/dfpAdServerVideo_spec.js +36 -4
  157. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +19 -0
  158. package/test/spec/modules/gridBidAdapter_spec.js +24 -0
  159. package/test/spec/modules/ixBidAdapter_spec.js +4 -4
  160. package/test/spec/modules/nobidBidAdapter_spec.js +32 -0
  161. package/test/spec/modules/permutiveRtdProvider_spec.js +61 -4
  162. package/test/spec/modules/pubwiseBidAdapter_spec.js +313 -3
  163. package/test/spec/modules/stvBidAdapter_spec.js +402 -0
  164. package/test/spec/modules/yandexBidAdapter_spec.js +315 -45
  165. package/test/spec/videoCache_spec.js +23 -0
  166. package/dist/flocIdSystem.js +0 -1
  167. package/modules/flocIdSystem.js +0 -0
@@ -389,6 +389,14 @@ describe('Conversant adapter tests', function() {
389
389
  expect(payload.device).to.have.property('ua', navigator.userAgent);
390
390
 
391
391
  expect(payload).to.not.have.property('user'); // there should be no user by default
392
+ expect(payload).to.not.have.property('tmax'); // there should be no user by default
393
+ });
394
+
395
+ it('Verify timeout', () => {
396
+ const bidderRequest = { timeout: 9999 };
397
+ const request = spec.buildRequests(bidRequests, bidderRequest);
398
+ const payload = request.data;
399
+ expect(payload.tmax).equals(bidderRequest.timeout);
392
400
  });
393
401
 
394
402
  it('Verify first party data', () => {
@@ -1,7 +1,7 @@
1
1
  import { expect } from 'chai';
2
2
 
3
3
  import parse from 'url-parse';
4
- import { buildDfpVideoUrl, buildAdpodVideoUrl } from 'modules/dfpAdServerVideo.js';
4
+ import {buildDfpVideoUrl, buildAdpodVideoUrl, dep} from 'modules/dfpAdServerVideo.js';
5
5
  import adUnit from 'test/fixtures/video/adUnit.json';
6
6
  import * as utils from 'src/utils.js';
7
7
  import { config } from 'src/config.js';
@@ -13,6 +13,7 @@ import { server } from 'test/mocks/xhr.js';
13
13
  import * as adServer from 'src/adserver.js';
14
14
  import {deepClone} from 'src/utils.js';
15
15
  import {hook} from '../../../src/hook.js';
16
+ import {getRefererInfo} from '../../../src/refererDetection.js';
16
17
 
17
18
  const bid = {
18
19
  videoCacheKey: 'abc',
@@ -27,6 +28,40 @@ describe('The DFP video support module', function () {
27
28
  hook.ready();
28
29
  });
29
30
 
31
+ let sandbox;
32
+
33
+ beforeEach(() => {
34
+ sandbox = sinon.sandbox.create();
35
+ });
36
+
37
+ afterEach(() => {
38
+ sandbox.restore();
39
+ });
40
+
41
+ Object.entries({
42
+ params: {
43
+ params: {
44
+ 'iu': 'my/adUnit'
45
+ }
46
+ },
47
+ url: {
48
+ url: 'https://some-example-url.com'
49
+ }
50
+ }).forEach(([t, options]) => {
51
+ describe(`when using ${t}`, () => {
52
+ it('should use page location as default for description_url', () => {
53
+ sandbox.stub(dep, 'ri').callsFake(() => ({page: 'example.com'}));
54
+
55
+ const url = parse(buildDfpVideoUrl(Object.assign({
56
+ adUnit: adUnit,
57
+ bid: bid,
58
+ }, options)));
59
+ const prm = utils.parseQS(url.query);
60
+ expect(prm.description_url).to.eql('example.com');
61
+ })
62
+ })
63
+ })
64
+
30
65
  it('should make a legal request URL when given the required params', function () {
31
66
  const url = parse(buildDfpVideoUrl({
32
67
  adUnit: adUnit,
@@ -63,9 +98,6 @@ describe('The DFP video support module', function () {
63
98
  }));
64
99
 
65
100
  expect(url.host).to.equal('video.adserver.example');
66
-
67
- const queryObject = utils.parseQS(url.query);
68
- expect(queryObject.description_url).to.equal('vastUrl.example');
69
101
  });
70
102
 
71
103
  it('requires a params object or url', function () {
@@ -1,8 +1,10 @@
1
1
  import { expect } from 'chai';
2
2
  import { spec } from 'modules/freewheel-sspBidAdapter.js';
3
3
  import { newBidder } from 'src/adapters/bidderFactory.js';
4
+ import { createEidsArray } from 'modules/userId/eids.js';
4
5
 
5
6
  const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php';
7
+ const PREBID_VERSION = '$prebid.version$';
6
8
 
7
9
  describe('freewheelSSP BidAdapter Test', () => {
8
10
  const adapter = newBidder(spec);
@@ -131,6 +133,22 @@ describe('freewheelSSP BidAdapter Test', () => {
131
133
  expect(payload._fw_bidfloorcur).to.deep.equal('USD');
132
134
  });
133
135
 
136
+ it('should pass 3rd party IDs with the request when present', function () {
137
+ const bidRequest = bidRequests[0];
138
+ bidRequest.userIdAsEids = createEidsArray({
139
+ tdid: 'TTD_ID_FROM_USER_ID_MODULE',
140
+ admixerId: 'admixerId_FROM_USER_ID_MODULE',
141
+ adtelligentId: 'adtelligentId_FROM_USER_ID_MODULE'
142
+ });
143
+ const request = spec.buildRequests(bidRequests);
144
+ const payload = request[0].data;
145
+ expect(payload._fw_prebid_3p_UID).to.deep.equal(JSON.stringify([
146
+ {source: 'adserver.org', uids: [{id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: {rtiPartner: 'TDID'}}]},
147
+ {source: 'admixer.net', uids: [{id: 'admixerId_FROM_USER_ID_MODULE', atype: 3}]},
148
+ {source: 'adtelligent.com', uids: [{id: 'adtelligentId_FROM_USER_ID_MODULE', atype: 3}]},
149
+ ]));
150
+ });
151
+
134
152
  it('should return empty bidFloorCurrency when bidfloor <= 0', () => {
135
153
  const bidRequest = bidRequests[0];
136
154
  bidRequest.getFloor = () => ({ currency: 'USD', floor: -1 });
@@ -149,6 +167,7 @@ describe('freewheelSSP BidAdapter Test', () => {
149
167
  expect(payload.componentId).to.equal('prebid');
150
168
  expect(payload.componentSubId).to.equal('mustang');
151
169
  expect(payload.playerSize).to.equal('300x600');
170
+ expect(payload.pbjs_version).to.equal(PREBID_VERSION);
152
171
  });
153
172
 
154
173
  it('should return a properly formatted request with schain defined', function () {
@@ -575,6 +575,30 @@ describe('TheMediaGrid Adapter', function () {
575
575
  expect(payload.regs.ext).to.have.property('us_privacy', '1YNN');
576
576
  });
577
577
 
578
+ it('should add gpp information to the request via bidderRequest.gppConsent', function () {
579
+ let consentString = 'abc1234';
580
+ const gppBidderRequest = Object.assign({gppConsent: {gppString: consentString, applicableSections: [8]}}, bidderRequest);
581
+
582
+ const [request] = spec.buildRequests(bidRequests, gppBidderRequest);
583
+ const payload = JSON.parse(request.data);
584
+
585
+ expect(payload.regs).to.exist;
586
+ expect(payload.regs.gpp).to.equal(consentString);
587
+ expect(payload.regs.gpp_sid).to.deep.equal([8]);
588
+ });
589
+
590
+ it('should add gpp information to the request via bidderRequest.ortb2.regs.gpp', function () {
591
+ let consentString = 'abc1234';
592
+ const gppBidderRequest = Object.assign({ortb2: {regs: {gpp: consentString, gpp_sid: [8]}}}, bidderRequest);
593
+
594
+ const [request] = spec.buildRequests(bidRequests, gppBidderRequest);
595
+ const payload = JSON.parse(request.data);
596
+
597
+ expect(payload.regs).to.exist;
598
+ expect(payload.regs.gpp).to.equal(consentString);
599
+ expect(payload.regs.gpp_sid).to.deep.equal([8]);
600
+ });
601
+
578
602
  it('if userId is present payload must have user.ext param with right keys', function () {
579
603
  const eids = [
580
604
  {
@@ -3469,7 +3469,7 @@ describe('IndexexchangeAdapter', function () {
3469
3469
  expect(requestWithConsent.regs.ext.us_privacy).to.equal('1YYN');
3470
3470
  });
3471
3471
 
3472
- it('should contain `consented_providers_settings.consented_providers` & consent on user.ext when both are provided', function () {
3472
+ it('should contain `consented_providers_settings.addtl_consent` & consent on user.ext when both are provided', function () {
3473
3473
  const options = {
3474
3474
  gdprConsent: {
3475
3475
  consentString: '3huaa11=qu3198ae',
@@ -3479,11 +3479,11 @@ describe('IndexexchangeAdapter', function () {
3479
3479
 
3480
3480
  const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options);
3481
3481
  const requestWithConsent = extractPayload(validBidWithConsent[0]);
3482
- expect(requestWithConsent.user.ext.consented_providers_settings.consented_providers).to.equal('1~1.35.41.101');
3482
+ expect(requestWithConsent.user.ext.consented_providers_settings.addtl_consent).to.equal('1~1.35.41.101');
3483
3483
  expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae');
3484
3484
  });
3485
3485
 
3486
- it('should not contain `consented_providers_settings.consented_providers` on user.ext when consent is not provided', function () {
3486
+ it('should not contain `consented_providers_settings.addtl_consent` on user.ext when consent is not provided', function () {
3487
3487
  const options = {
3488
3488
  gdprConsent: {
3489
3489
  addtlConsent: '1~1.35.41.101',
@@ -3492,7 +3492,7 @@ describe('IndexexchangeAdapter', function () {
3492
3492
 
3493
3493
  const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options);
3494
3494
  const requestWithConsent = extractPayload(validBidWithConsent[0]);
3495
- expect(utils.deepAccess(requestWithConsent, 'user.ext.consented_providers_settings')).to.not.exist;
3495
+ expect(utils.deepAccess(requestWithConsent, 'user.ext.consented_providers_settings.addtl_consent')).to.not.exist;
3496
3496
  expect(utils.deepAccess(requestWithConsent, 'user.ext.consent')).to.not.exist;
3497
3497
  });
3498
3498
 
@@ -14,6 +14,38 @@ describe('Nobid Adapter', function () {
14
14
  });
15
15
  });
16
16
 
17
+ describe('buildRequestsWithFloor', function () {
18
+ const SITE_ID = 2;
19
+ const REFERER = 'https://www.examplereferer.com';
20
+ let bidRequests = [
21
+ {
22
+ 'bidder': 'nobid',
23
+ 'params': {
24
+ 'siteId': SITE_ID
25
+ },
26
+ 'getFloor': () => { return { currency: 'USD', floor: 1.00 } },
27
+ 'adUnitCode': 'adunit-code',
28
+ 'sizes': [[300, 250]],
29
+ 'bidId': '30b31c1838de1e',
30
+ 'bidderRequestId': '22edbae2733bf6',
31
+ 'auctionId': '1d1a030790a475'
32
+ }
33
+ ];
34
+
35
+ let bidderRequest = {
36
+ refererInfo: {page: REFERER}
37
+ }
38
+
39
+ it('should FLoor = 1', function () {
40
+ spec.buildRequests(bidRequests, bidderRequest);
41
+ const request = spec.buildRequests(bidRequests, bidderRequest);
42
+ /* eslint-disable no-console */
43
+ console.log('request.data:', request.data);
44
+ const payload = JSON.parse(request.data);
45
+ expect(payload.a[0].floor).to.equal(1);
46
+ });
47
+ });
48
+
17
49
  describe('isBidRequestValid', function () {
18
50
  let bid = {
19
51
  'bidder': 'nobid',
@@ -196,12 +196,67 @@ describe('permutiveRtdProvider', function () {
196
196
  setBidderRtb(bidderConfig, moduleConfig, segmentsData)
197
197
 
198
198
  acBidders.forEach(bidder => {
199
- expect(bidderConfig[bidder].user.data).to.deep.include.members([{
200
- name: 'permutive.com',
201
- segment: expectedTargetingData
202
- }])
199
+ const customCohorts = segmentsData[bidder] || []
200
+ expect(bidderConfig[bidder].user.data).to.deep.include.members([
201
+ {
202
+ name: 'permutive.com',
203
+ segment: expectedTargetingData,
204
+ },
205
+ // Should have custom cohorts specific for that bidder
206
+ {
207
+ name: 'permutive',
208
+ segment: customCohorts.map(seg => {
209
+ return { id: seg }
210
+ }),
211
+ },
212
+ ])
203
213
  })
204
214
  })
215
+
216
+ it('should override existing ortb2.user.data reserved by permutive RTD', function () {
217
+ const reservedPermutiveStandardName = 'permutive.com'
218
+ const reservedPermutiveCustomCohortName = 'permutive'
219
+
220
+ const moduleConfig = getConfig()
221
+ const acBidders = moduleConfig.params.acBidders
222
+ const segmentsData = transformedTargeting()
223
+
224
+ const sampleOrtbConfig = {
225
+ user: {
226
+ data: [
227
+ {
228
+ name: reservedPermutiveCustomCohortName,
229
+ segment: [{ id: 'remove-me' }, { id: 'remove-me-also' }]
230
+ },
231
+ {
232
+ name: reservedPermutiveStandardName,
233
+ segment: [{ id: 'remove-me-also-also' }, { id: 'remove-me-also-also-also' }]
234
+ }
235
+ ]
236
+ }
237
+ }
238
+
239
+ const bidderConfig = Object.fromEntries(acBidders.map(bidder => [bidder, sampleOrtbConfig]))
240
+
241
+ setBidderRtb(bidderConfig, moduleConfig, segmentsData)
242
+
243
+ acBidders.forEach(bidder => {
244
+ const customCohorts = segmentsData[bidder] || []
245
+
246
+ expect(bidderConfig[bidder].user.data).to.not.deep.include.members([...sampleOrtbConfig.user.data])
247
+ expect(bidderConfig[bidder].user.data).to.deep.include.members([
248
+ {
249
+ name: reservedPermutiveCustomCohortName,
250
+ segment: customCohorts.map(id => ({ id })),
251
+ },
252
+ {
253
+ name: reservedPermutiveStandardName,
254
+ segment: segmentsData.ac.map(id => ({ id })),
255
+ },
256
+ ])
257
+ })
258
+ })
259
+
205
260
  it('should include ortb2 user data transformation for IAB audience taxonomy', function() {
206
261
  const moduleConfig = getConfig()
207
262
  const bidderConfig = {}
@@ -647,6 +702,7 @@ function transformedTargeting (data = getTargetingData()) {
647
702
  return {
648
703
  ac: [...data._pcrprs, ...data._ppam, ...data._psegs.filter(seg => seg >= 1000000)],
649
704
  appnexus: data._papns,
705
+ ix: data._pindexs,
650
706
  rubicon: data._prubicons,
651
707
  gam: data._pdfps,
652
708
  ssp: data._pssps,
@@ -660,6 +716,7 @@ function getTargetingData () {
660
716
  _papns: ['appnexus1', 'appnexus2'],
661
717
  _psegs: ['1234', '1000001', '1000002'],
662
718
  _ppam: ['ppam1', 'ppam2'],
719
+ _pindexs: ['pindex1', 'pindex2'],
663
720
  _pcrprs: ['pcrprs1', 'pcrprs2', 'dup'],
664
721
  _pssps: { ssps: ['xyz', 'abc', 'dup'], cohorts: ['123', 'abc'] }
665
722
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {expect} from 'chai';
4
4
  import {spec} from 'modules/pubwiseBidAdapter.js';
5
- import {_checkMediaType} from 'modules/pubwiseBidAdapter.js'; // this is exported only for testing so maintaining the JS convention of _ to indicate the intent
5
+ import {_checkVideoPlacement, _checkMediaType} from 'modules/pubwiseBidAdapter.js'; // this is exported only for testing so maintaining the JS convention of _ to indicate the intent
6
6
  import {_parseAdSlot} from 'modules/pubwiseBidAdapter.js'; // this is exported only for testing so maintaining the JS convention of _ to indicate the intent
7
7
  import * as utils from 'src/utils.js';
8
8
 
@@ -486,6 +486,28 @@ const samplePBBidObjects = [
486
486
  ];
487
487
 
488
488
  describe('PubWiseAdapter', function () {
489
+ describe('Handles Params Properly', function () {
490
+ it('properly sets the default endpoint', function () {
491
+ const referenceEndpoint = 'https://bid.pubwise.io/prebid';
492
+ let endpointBidRequest = utils.deepClone(sampleValidBidRequests);
493
+ // endpointBidRequest.forEach((bidRequest) => {
494
+ // bidRequest.params.endpoint_url = newEndpoint;
495
+ // });
496
+ let result = spec.buildRequests(endpointBidRequest, {auctionId: 'placeholder'});
497
+ expect(result.url).to.equal(referenceEndpoint);
498
+ });
499
+
500
+ it('allows endpoint to be reset', function () {
501
+ const newEndpoint = 'http://www.pubwise.io/endpointtest';
502
+ let endpointBidRequest = utils.deepClone(sampleValidBidRequests);
503
+ endpointBidRequest.forEach((bidRequest) => {
504
+ bidRequest.params.endpoint_url = newEndpoint;
505
+ });
506
+ let result = spec.buildRequests(endpointBidRequest, {auctionId: 'placeholder'});
507
+ expect(result.url).to.equal(newEndpoint);
508
+ });
509
+ });
510
+
489
511
  describe('Properly Validates Bids', function () {
490
512
  it('valid bid', function () {
491
513
  let validBid = {
@@ -555,14 +577,14 @@ describe('PubWiseAdapter', function () {
555
577
  it('identifies native adm type', function() {
556
578
  let adm = '{"ver":"1.2","assets":[{"title":{"text":"PubWise Test"}},{"img":{"type":3,"url":"http://www.pubwise.io"}},{"img":{"type":1,"url":"http://www.pubwise.io"}},{"data":{"type":2,"value":"PubWise Test Desc"}},{"data":{"type":1,"value":"PubWise.io"}}],"link":{"url":""}}';
557
579
  let newBid = {mediaType: 'unknown'};
558
- _checkMediaType(adm, newBid);
580
+ _checkMediaType({adm}, newBid);
559
581
  expect(newBid.mediaType).to.equal('native', adm + ' Is a Native adm');
560
582
  });
561
583
 
562
584
  it('identifies banner adm type', function() {
563
585
  let adm = '<div style="box-sizing: border-box;width:298px;height:248px;border: 1px solid rgba(0,0,0,.25);border-radius:10px;">↵ <h3 style="margin-top:80px;text-align: center;">PubWise Test Bid</h3>↵</div>';
564
586
  let newBid = {mediaType: 'unknown'};
565
- _checkMediaType(adm, newBid);
587
+ _checkMediaType({adm}, newBid);
566
588
  expect(newBid.mediaType).to.equal('banner', adm + ' Is a Banner adm');
567
589
  });
568
590
  });
@@ -582,4 +604,292 @@ describe('PubWiseAdapter', function () {
582
604
  expect(pbResponse).to.deep.equal(samplePBBidObjects);
583
605
  });
584
606
  });
607
+
608
+ describe('Video Testing', function () {
609
+ /**
610
+ * Video Testing
611
+ */
612
+
613
+ const videoBidRequests =
614
+ [
615
+ {
616
+ code: 'video1',
617
+ mediaTypes: {
618
+ video: {
619
+ playerSize: [640, 480],
620
+ context: 'instream'
621
+ }
622
+ },
623
+ bidder: 'pwbid',
624
+ bidId: '22bddb28db77d',
625
+ adUnitCode: 'Div1',
626
+ params: {
627
+ siteId: 'xxxxxx',
628
+ video: {
629
+ mimes: ['video/mp4', 'video/x-flv'],
630
+ skippable: true,
631
+ minduration: 5,
632
+ maxduration: 30,
633
+ startdelay: 5,
634
+ playbackmethod: [1, 3],
635
+ api: [1, 2],
636
+ protocols: [2, 3],
637
+ battr: [13, 14],
638
+ linearity: 1,
639
+ placement: 2,
640
+ minbitrate: 10,
641
+ maxbitrate: 10
642
+ }
643
+ }
644
+ }
645
+ ];
646
+
647
+ let newvideoRequests = [{
648
+ 'bidder': 'pwbid',
649
+ 'params': {
650
+ 'siteId': 'xxxxx',
651
+ 'video': {
652
+ 'mimes': ['video/mp4'],
653
+ 'skippable': true,
654
+ 'protocols': [1, 2, 5],
655
+ 'linearity': 1
656
+ }
657
+ },
658
+ 'mediaTypes': {
659
+ 'video': {
660
+ 'playerSize': [
661
+ [640, 480]
662
+ ],
663
+ 'protocols': [1, 2, 5],
664
+ 'context': 'instream',
665
+ 'mimes': ['video/flv'],
666
+ 'skippable': false,
667
+ 'skip': 1,
668
+ 'linearity': 2
669
+ }
670
+ },
671
+ 'adUnitCode': 'video1',
672
+ 'transactionId': '803e3750-0bbe-4ffe-a548-b6eca15087bf',
673
+ 'sizes': [
674
+ [640, 480]
675
+ ],
676
+ 'bidId': '2c95df014cfe97',
677
+ 'bidderRequestId': '1fe59391566442',
678
+ 'auctionId': '3a4118ef-fb96-4416-b0b0-3cfc1cebc142',
679
+ 'src': 'client',
680
+ 'bidRequestsCount': 1,
681
+ 'bidderRequestsCount': 1,
682
+ 'bidderWinsCount': 0
683
+ }];
684
+
685
+ let newvideoBidResponses = {
686
+ 'body': {
687
+ 'id': '1621441141473',
688
+ 'cur': 'USD',
689
+ 'customdata': 'openrtb1',
690
+ 'ext': {
691
+ 'buyid': 'myBuyId'
692
+ },
693
+ 'seatbid': [{
694
+ 'bid': [{
695
+ 'id': '2c95df014cfe97',
696
+ 'impid': '2c95df014cfe97',
697
+ 'price': 4.2,
698
+ 'cid': 'test1',
699
+ 'crid': 'test2',
700
+ 'adm': "<VAST version='3.0'><Ad id='601364'><InLine><AdSystem>Acudeo Compatible</AdSystem><AdTitle>VAST 2.0 Instream Test 1</AdTitle><Description>VAST 2.0 Instream Test 1</Description><Creatives><Creative AdID='601364'><Linear skipoffset='20%'><TrackingEvents><Tracking event='close'><![CDATA[https://pwtracking.com/linear/close]]></Tracking><Tracking event='skip'><![CDATA[https://pwtracking.com/linear/skip]]></Tracking><MediaFiles><MediaFile delivery='progressive' type='video/mp4' bitrate='500' width='400' height='300' scalable='true' maintainAspectRatio='true'><![CDATA[https://localhost/pubwise.mp4]]></MediaFile></MediaFiles></Linear></Creative></Creatives></InLine></Ad></VAST>",
701
+ 'w': 0,
702
+ 'h': 0
703
+ }],
704
+ 'ext': {
705
+ 'buyid': 'myBuyId'
706
+ }
707
+ }]
708
+ },
709
+ 'headers': {}
710
+ };
711
+
712
+ let videoBidResponse = {
713
+ 'body': {
714
+ 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865',
715
+ 'seatbid': [{
716
+ 'bid': [{
717
+ 'id': '74858439-49D7-4169-BA5D-44A046315B2F',
718
+ 'impid': '22bddb28db77d',
719
+ 'price': 1.3,
720
+ 'adm': '<VAST version="3.0"><Ad id="601364"><!--not real sample--></Ad></VAST>',
721
+ 'h': 250,
722
+ 'w': 300,
723
+ 'ext': {
724
+ 'deal_channel': 6
725
+ }
726
+ }]
727
+ }]
728
+ }
729
+ };
730
+
731
+ it('Request params check for video ad', function () {
732
+ let request = spec.buildRequests(videoBidRequests, {
733
+ auctionId: 'new-auction-id'
734
+ });
735
+ let data = request.data;
736
+ expect(data.imp[0].video).to.exist;
737
+ expect(data.imp[0].tagid).to.equal('Div1');
738
+ expect(data.imp[0]['video']['mimes']).to.exist.and.to.be.an('array');
739
+ expect(data.imp[0]['video']['mimes'][0]).to.equal(videoBidRequests[0].params.video['mimes'][0]);
740
+ expect(data.imp[0]['video']['mimes'][1]).to.equal(videoBidRequests[0].params.video['mimes'][1]);
741
+ expect(data.imp[0]['video']['minduration']).to.equal(videoBidRequests[0].params.video['minduration']);
742
+ expect(data.imp[0]['video']['maxduration']).to.equal(videoBidRequests[0].params.video['maxduration']);
743
+ expect(data.imp[0]['video']['startdelay']).to.equal(videoBidRequests[0].params.video['startdelay']);
744
+
745
+ expect(data.imp[0]['video']['playbackmethod']).to.exist.and.to.be.an('array');
746
+ expect(data.imp[0]['video']['playbackmethod'][0]).to.equal(videoBidRequests[0].params.video['playbackmethod'][0]);
747
+ expect(data.imp[0]['video']['playbackmethod'][1]).to.equal(videoBidRequests[0].params.video['playbackmethod'][1]);
748
+
749
+ expect(data.imp[0]['video']['api']).to.exist.and.to.be.an('array');
750
+ expect(data.imp[0]['video']['api'][0]).to.equal(videoBidRequests[0].params.video['api'][0]);
751
+ expect(data.imp[0]['video']['api'][1]).to.equal(videoBidRequests[0].params.video['api'][1]);
752
+
753
+ expect(data.imp[0]['video']['protocols']).to.exist.and.to.be.an('array');
754
+ expect(data.imp[0]['video']['protocols'][0]).to.equal(videoBidRequests[0].params.video['protocols'][0]);
755
+ expect(data.imp[0]['video']['protocols'][1]).to.equal(videoBidRequests[0].params.video['protocols'][1]);
756
+
757
+ expect(data.imp[0]['video']['battr']).to.exist.and.to.be.an('array');
758
+ expect(data.imp[0]['video']['battr'][0]).to.equal(videoBidRequests[0].params.video['battr'][0]);
759
+ expect(data.imp[0]['video']['battr'][1]).to.equal(videoBidRequests[0].params.video['battr'][1]);
760
+
761
+ expect(data.imp[0]['video']['linearity']).to.equal(videoBidRequests[0].params.video['linearity']);
762
+ expect(data.imp[0]['video']['placement']).to.equal(videoBidRequests[0].params.video['placement']);
763
+ expect(data.imp[0]['video']['minbitrate']).to.equal(videoBidRequests[0].params.video['minbitrate']);
764
+ expect(data.imp[0]['video']['maxbitrate']).to.equal(videoBidRequests[0].params.video['maxbitrate']);
765
+
766
+ expect(data.imp[0]['video']['w']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[0]);
767
+ expect(data.imp[0]['video']['h']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[1]);
768
+ });
769
+
770
+ it('should assign mediaType even if bid.ext.mediaType does not exists', function() {
771
+ let newrequest = spec.buildRequests(newvideoRequests, {
772
+ auctionId: 'new-auction-id'
773
+ });
774
+ let newresponse = spec.interpretResponse(newvideoBidResponses, newrequest);
775
+ expect(newresponse[0].mediaType).to.equal('video');
776
+ });
777
+
778
+ it('should not assign renderer if bid is video and request is for instream', function() {
779
+ let request = spec.buildRequests(videoBidRequests, {
780
+ auctionId: 'new-auction-id'
781
+ });
782
+ let response = spec.interpretResponse(videoBidResponse, request);
783
+ expect(response[0].renderer).to.not.exist;
784
+ });
785
+
786
+ it('should process instream and outstream', function() {
787
+ let validOutstreamRequest =
788
+ {
789
+ code: 'video1',
790
+ mediaTypes: {
791
+ video: {
792
+ playerSize: [640, 480],
793
+ context: 'outstream'
794
+ }
795
+ },
796
+ bidder: 'pwbid',
797
+ bidId: '47acc48ad47af5',
798
+ requestId: '0fb4905b-1234-4152-86be-c6f6d259ba99',
799
+ bidderRequestId: '1c56ad30b9b8ca8',
800
+ transactionId: '92489f71-1bf2-49a0-adf9-000cea934729',
801
+ params: {
802
+ siteId: 'xxxxx',
803
+ adSlot: 'Div1', // ad_id or tagid
804
+ video: {
805
+ mimes: ['video/mp4', 'video/x-flv'],
806
+ skippable: true,
807
+ minduration: 5,
808
+ maxduration: 30
809
+ }
810
+ }
811
+ };
812
+
813
+ let outstreamBidRequest =
814
+ [
815
+ validOutstreamRequest
816
+ ];
817
+
818
+ let validInstreamRequest = {
819
+ code: 'video1',
820
+ mediaTypes: {
821
+ video: {
822
+ playerSize: [640, 480],
823
+ context: 'instream'
824
+ }
825
+ },
826
+ bidder: 'pwbid',
827
+ bidId: '47acc48ad47af5',
828
+ requestId: '0fb4905b-1234-4152-86be-c6f6d259ba99',
829
+ bidderRequestId: '1c56ad30b9b8ca8',
830
+ transactionId: '92489f71-1bf2-49a0-adf9-000cea934729',
831
+ params: {
832
+ siteId: 'xxxxx',
833
+ adSlot: 'Div1', // ad_id or tagid
834
+ video: {
835
+ mimes: ['video/mp4', 'video/x-flv'],
836
+ skippable: true,
837
+ minduration: 5,
838
+ maxduration: 30
839
+ }
840
+ }
841
+ };
842
+
843
+ let instreamBidRequest =
844
+ [
845
+ validInstreamRequest
846
+ ];
847
+
848
+ let outstreamRequest = spec.isBidRequestValid(validOutstreamRequest);
849
+ expect(outstreamRequest).to.equal(false);
850
+
851
+ let instreamRequest = spec.isBidRequestValid(validInstreamRequest);
852
+ expect(instreamRequest).to.equal(true);
853
+ });
854
+
855
+ describe('Checking for Video.Placement property', function() {
856
+ let sandbox, utilsMock;
857
+ const adUnit = 'DivCheckPlacement';
858
+ const msg_placement_missing = 'PubWise: Video.Placement param missing for DivCheckPlacement';
859
+ let videoData = {
860
+ battr: [6, 7],
861
+ skipafter: 15,
862
+ maxduration: 50,
863
+ context: 'instream',
864
+ playerSize: [640, 480],
865
+ skip: 0,
866
+ connectiontype: [1, 2, 6],
867
+ skipmin: 10,
868
+ minduration: 10,
869
+ mimes: ['video/mp4', 'video/x-flv'],
870
+ }
871
+ beforeEach(() => {
872
+ utilsMock = sinon.mock(utils);
873
+ sandbox = sinon.sandbox.create();
874
+ sandbox.spy(utils, 'logWarn');
875
+ });
876
+
877
+ afterEach(() => {
878
+ utilsMock.restore();
879
+ sandbox.restore();
880
+ })
881
+
882
+ it('should log Video.Placement param missing', function() {
883
+ _checkVideoPlacement(videoData, adUnit);
884
+ // when failing this gives an odd message about "AssertError: expected logWarn to be called with arguments" it means the specific message expected
885
+ sinon.assert.calledWith(utils.logWarn, msg_placement_missing);
886
+ })
887
+ it('shoud not log Video.Placement param missing', function() {
888
+ videoData['placement'] = 1;
889
+ _checkVideoPlacement(videoData, adUnit);
890
+ sinon.assert.neverCalledWith(utils.logWarn, msg_placement_missing);
891
+ })
892
+ });
893
+ // end video testing
894
+ });
585
895
  });