prebid.js 6.2.0 → 6.3.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 (60) hide show
  1. package/gulpfile.js +0 -8
  2. package/integrationExamples/gpt/weboramaRtdProvider_example.html +23 -14
  3. package/modules/33acrossBidAdapter.js +189 -102
  4. package/modules/adagioBidAdapter.js +1 -1
  5. package/modules/addefendBidAdapter.js +1 -0
  6. package/modules/admanBidAdapter.js +1 -0
  7. package/modules/admixerBidAdapter.js +1 -1
  8. package/modules/adnuntiusBidAdapter.js +3 -1
  9. package/modules/adxcgBidAdapter.js +311 -359
  10. package/modules/adxcgBidAdapter.md +22 -21
  11. package/modules/appnexusBidAdapter.js +0 -1
  12. package/modules/beopBidAdapter.js +5 -3
  13. package/modules/colossussspBidAdapter.js +7 -0
  14. package/modules/criteoBidAdapter.js +1 -1
  15. package/modules/cwireBidAdapter.js +3 -0
  16. package/modules/dspxBidAdapter.js +1 -1
  17. package/modules/futureads.md +48 -0
  18. package/modules/glimpseBidAdapter.js +16 -3
  19. package/modules/gumgumBidAdapter.js +2 -2
  20. package/modules/kinessoIdSystem.js +1 -1
  21. package/modules/lotamePanoramaIdSystem.js +80 -8
  22. package/modules/mediasquareBidAdapter.js +1 -9
  23. package/modules/nextMillenniumBidAdapter.js +29 -1
  24. package/modules/prebidServerBidAdapter/index.js +16 -12
  25. package/modules/richaudienceBidAdapter.js +1 -2
  26. package/modules/rtdModule/index.js +48 -18
  27. package/modules/rubiconBidAdapter.js +10 -8
  28. package/modules/sharedIdSystem.js +27 -1
  29. package/modules/targetVideoBidAdapter.js +187 -0
  30. package/modules/targetVideoBidAdapter.md +34 -0
  31. package/modules/vidoomyBidAdapter.js +16 -10
  32. package/modules/weboramaRtdProvider.js +288 -73
  33. package/modules/weboramaRtdProvider.md +27 -10
  34. package/modules/yahoosspBidAdapter.js +5 -1
  35. package/modules/zetaSspBidAdapter.md +33 -1
  36. package/modules/zeta_global_sspBidAdapter.js +22 -1
  37. package/package.json +1 -1
  38. package/plugins/pbjsGlobals.js +28 -1
  39. package/src/prebid.js +1 -2
  40. package/src/targeting.js +22 -1
  41. package/src/utils.js +34 -7
  42. package/test/spec/modules/33acrossBidAdapter_spec.js +300 -78
  43. package/test/spec/modules/adnuntiusBidAdapter_spec.js +17 -0
  44. package/test/spec/modules/adxcgBidAdapter_spec.js +820 -571
  45. package/test/spec/modules/colossussspBidAdapter_spec.js +9 -0
  46. package/test/spec/modules/cwireBidAdapter_spec.js +10 -8
  47. package/test/spec/modules/lotamePanoramaIdSystem_spec.js +227 -0
  48. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -4
  49. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +18 -0
  50. package/test/spec/modules/prebidServerBidAdapter_spec.js +43 -0
  51. package/test/spec/modules/realTimeDataModule_spec.js +135 -49
  52. package/test/spec/modules/richaudienceBidAdapter_spec.js +2 -2
  53. package/test/spec/modules/rubiconBidAdapter_spec.js +17 -0
  54. package/test/spec/modules/sharedIdSystem_spec.js +52 -6
  55. package/test/spec/modules/targetVideoBidAdapter_spec.js +96 -0
  56. package/test/spec/modules/weboramaRtdProvider_spec.js +408 -214
  57. package/test/spec/modules/yahoosspBidAdapter_spec.js +28 -1
  58. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +33 -1
  59. package/test/spec/unit/core/targeting_spec.js +72 -0
  60. package/test/spec/utils_spec.js +38 -0
package/src/prebid.js CHANGED
@@ -47,8 +47,7 @@ $$PREBID_GLOBAL$$.libLoaded = true;
47
47
  $$PREBID_GLOBAL$$.version = 'v$prebid.version$';
48
48
  logInfo('Prebid.js v$prebid.version$ loaded');
49
49
 
50
- // modules list generated from build
51
- $$PREBID_GLOBAL$$.installedModules = ['v$prebid.modulesList$'];
50
+ $$PREBID_GLOBAL$$.installedModules = $$PREBID_GLOBAL$$.installedModules || [];
52
51
 
53
52
  // create adUnit array
54
53
  $$PREBID_GLOBAL$$.adUnits = $$PREBID_GLOBAL$$.adUnits || [];
package/src/targeting.js CHANGED
@@ -18,6 +18,10 @@ var pbTargetingKeys = [];
18
18
  const MAX_DFP_KEYLENGTH = 20;
19
19
  const TTL_BUFFER = 1000;
20
20
 
21
+ const CFG_ALLOW_TARGETING_KEYS = `targetingControls.allowTargetingKeys`;
22
+ const CFG_ADD_TARGETING_KEYS = `targetingControls.addTargetingKeys`;
23
+ const TARGETING_KEY_CONFIGURATION_ERROR_MSG = `Only one of "${CFG_ALLOW_TARGETING_KEYS}" or "${CFG_ADD_TARGETING_KEYS}" can be set`;
24
+
21
25
  export const TARGETING_KEYS = Object.keys(CONSTANTS.TARGETING_KEYS).map(
22
26
  key => CONSTANTS.TARGETING_KEYS[key]
23
27
  );
@@ -261,7 +265,17 @@ export function newTargeting(auctionManager) {
261
265
  });
262
266
 
263
267
  const defaultKeys = Object.keys(Object.assign({}, CONSTANTS.DEFAULT_TARGETING_KEYS, CONSTANTS.NATIVE_KEYS));
264
- const allowedKeys = config.getConfig('targetingControls.allowTargetingKeys') || defaultKeys;
268
+ let allowedKeys = config.getConfig(CFG_ALLOW_TARGETING_KEYS);
269
+ const addedKeys = config.getConfig(CFG_ADD_TARGETING_KEYS);
270
+
271
+ if (addedKeys != null && allowedKeys != null) {
272
+ throw new Error(TARGETING_KEY_CONFIGURATION_ERROR_MSG);
273
+ } else if (addedKeys != null) {
274
+ allowedKeys = defaultKeys.concat(addedKeys);
275
+ } else {
276
+ allowedKeys = allowedKeys || defaultKeys;
277
+ }
278
+
265
279
  if (Array.isArray(allowedKeys) && allowedKeys.length > 0) {
266
280
  targeting = getAllowedTargetingKeyValues(targeting, allowedKeys);
267
281
  }
@@ -284,6 +298,13 @@ export function newTargeting(auctionManager) {
284
298
  return targeting;
285
299
  };
286
300
 
301
+ // warn about conflicting configuration
302
+ config.getConfig('targetingControls', function (config) {
303
+ if (deepAccess(config, CFG_ALLOW_TARGETING_KEYS) != null && deepAccess(config, CFG_ADD_TARGETING_KEYS) != null) {
304
+ logError(TARGETING_KEY_CONFIGURATION_ERROR_MSG);
305
+ }
306
+ });
307
+
287
308
  // create an encoded string variant based on the keypairs of the provided object
288
309
  // - note this will encode the characters between the keys (ie = and &)
289
310
  function convertKeysToQueryForm(keyMap) {
package/src/utils.js CHANGED
@@ -482,16 +482,43 @@ export function insertElement(elm, doc, target, asLastChildChild) {
482
482
  } catch (e) {}
483
483
  }
484
484
 
485
+ /**
486
+ * Returns a promise that completes when the given element triggers a 'load' or 'error' DOM event, or when
487
+ * `timeout` milliseconds have elapsed.
488
+ *
489
+ * @param {HTMLElement} element
490
+ * @param {Number} [timeout]
491
+ * @returns {Promise}
492
+ */
493
+ export function waitForElementToLoad(element, timeout) {
494
+ let timer = null;
495
+ return new Promise((resolve) => {
496
+ const onLoad = function() {
497
+ element.removeEventListener('load', onLoad);
498
+ element.removeEventListener('error', onLoad);
499
+ if (timer != null) {
500
+ window.clearTimeout(timer);
501
+ }
502
+ resolve();
503
+ };
504
+ element.addEventListener('load', onLoad);
505
+ element.addEventListener('error', onLoad);
506
+ if (timeout != null) {
507
+ timer = window.setTimeout(onLoad, timeout);
508
+ }
509
+ });
510
+ }
511
+
485
512
  /**
486
513
  * Inserts an image pixel with the specified `url` for cookie sync
487
514
  * @param {string} url URL string of the image pixel to load
488
515
  * @param {function} [done] an optional exit callback, used when this usersync pixel is added during an async process
516
+ * @param {Number} [timeout] an optional timeout in milliseconds for the image to load before calling `done`
489
517
  */
490
- export function triggerPixel(url, done) {
518
+ export function triggerPixel(url, done, timeout) {
491
519
  const img = new Image();
492
520
  if (done && internal.isFn(done)) {
493
- img.addEventListener('load', done);
494
- img.addEventListener('error', done);
521
+ waitForElementToLoad(img, timeout).then(done);
495
522
  }
496
523
  img.src = url;
497
524
  }
@@ -539,18 +566,18 @@ export function insertHtmlIntoIframe(htmlCode) {
539
566
  * @param {string} url URL to be requested
540
567
  * @param {string} encodeUri boolean if URL should be encoded before inserted. Defaults to true
541
568
  * @param {function} [done] an optional exit callback, used when this usersync pixel is added during an async process
569
+ * @param {Number} [timeout] an optional timeout in milliseconds for the iframe to load before calling `done`
542
570
  */
543
- export function insertUserSyncIframe(url, done) {
571
+ export function insertUserSyncIframe(url, done, timeout) {
544
572
  let iframeHtml = internal.createTrackPixelIframeHtml(url, false, 'allow-scripts allow-same-origin');
545
573
  let div = document.createElement('div');
546
574
  div.innerHTML = iframeHtml;
547
575
  let iframe = div.firstChild;
548
576
  if (done && internal.isFn(done)) {
549
- iframe.addEventListener('load', done);
550
- iframe.addEventListener('error', done);
577
+ waitForElementToLoad(iframe, timeout).then(done);
551
578
  }
552
579
  internal.insertElement(iframe, document, 'html', true);
553
- };
580
+ }
554
581
 
555
582
  /**
556
583
  * Creates a snippet of HTML that retrieves the specified `url`
@@ -16,20 +16,21 @@ function validateBuiltServerRequest(builtReq, expectedReq) {
16
16
  describe('33acrossBidAdapter:', function () {
17
17
  const BIDDER_CODE = '33across';
18
18
  const SITE_ID = 'sample33xGUID123456789';
19
- const PRODUCT_ID = 'siab';
20
19
  const END_POINT = 'https://ssc.33across.com/api/v1/hb';
21
20
 
22
21
  let element, win;
23
22
  let bidRequests;
24
23
  let sandbox;
25
24
 
26
- function TtxRequestBuilder() {
25
+ function TtxRequestBuilder(siteId = SITE_ID) {
27
26
  const ttxRequest = {
28
- imp: [{}],
27
+ imp: [{
28
+ id: 'b1'
29
+ }],
29
30
  site: {
30
- id: SITE_ID
31
+ id: siteId
31
32
  },
32
- id: 'b1',
33
+ id: 'r1',
33
34
  regs: {
34
35
  ext: {
35
36
  gdpr: 0
@@ -46,66 +47,83 @@ describe('33acrossBidAdapter:', function () {
46
47
  }
47
48
  };
48
49
 
50
+ this.addImp = (id = 'b2') => {
51
+ ttxRequest.imp.push({ id });
52
+
53
+ return this;
54
+ }
55
+
49
56
  this.withBanner = () => {
50
- Object.assign(ttxRequest.imp[0], {
51
- banner: {
52
- format: [
53
- {
54
- w: 300,
55
- h: 250
56
- },
57
- {
58
- w: 728,
59
- h: 90
60
- }
61
- ],
62
- ext: {
63
- ttx: {
64
- viewability: {
65
- amount: 100
57
+ ttxRequest.imp.forEach((imp) => {
58
+ Object.assign(imp, {
59
+ banner: {
60
+ format: [
61
+ {
62
+ w: 300,
63
+ h: 250
64
+ },
65
+ {
66
+ w: 728,
67
+ h: 90
68
+ }
69
+ ],
70
+ ext: {
71
+ ttx: {
72
+ viewability: {
73
+ amount: 100
74
+ }
66
75
  }
67
76
  }
68
77
  }
69
- }
78
+ });
70
79
  });
71
-
72
80
  return this;
73
81
  };
74
82
 
75
83
  this.withBannerSizes = this.withSizes = sizes => {
76
- Object.assign(ttxRequest.imp[0].banner, { format: sizes });
84
+ ttxRequest.imp.forEach((imp) => {
85
+ Object.assign(imp.banner, { format: sizes });
86
+ });
87
+
77
88
  return this;
78
89
  };
79
90
 
80
91
  this.withVideo = (params = {}) => {
81
- Object.assign(ttxRequest.imp[0], {
82
- video: {
83
- w: 300,
84
- h: 250,
85
- placement: 2,
86
- ...params
87
- }
92
+ ttxRequest.imp.forEach((imp) => {
93
+ Object.assign(imp, {
94
+ video: {
95
+ w: 300,
96
+ h: 250,
97
+ placement: 2,
98
+ ...params
99
+ }
100
+ });
88
101
  });
89
102
 
90
103
  return this;
91
104
  };
92
105
 
93
106
  this.withViewability = (viewability, format = 'banner') => {
94
- Object.assign(ttxRequest.imp[0][format], {
95
- ext: {
96
- ttx: { viewability }
97
- }
107
+ ttxRequest.imp.forEach((imp) => {
108
+ Object.assign(imp[format], {
109
+ ext: {
110
+ ttx: { viewability }
111
+ }
112
+ });
98
113
  });
114
+
99
115
  return this;
100
116
  };
101
117
 
102
- this.withProduct = (prod = PRODUCT_ID) => {
103
- Object.assign(ttxRequest.imp[0], {
104
- ext: {
105
- ttx: {
106
- prod
118
+ this.withProduct = (prod = 'siab') => {
119
+ ttxRequest.imp.forEach((imp) => {
120
+ Object.assign(imp, {
121
+ ext: {
122
+ ttx: {
123
+ prod
124
+ }
107
125
  }
108
- }
126
+ });
109
127
  });
110
128
 
111
129
  return this;
@@ -249,7 +267,7 @@ describe('33acrossBidAdapter:', function () {
249
267
  bidderRequestId: 'b1a',
250
268
  params: {
251
269
  siteId: SITE_ID,
252
- productId: PRODUCT_ID
270
+ productId: 'siab'
253
271
  },
254
272
  adUnitCode: 'div-id',
255
273
  auctionId: 'r1',
@@ -258,35 +276,61 @@ describe('33acrossBidAdapter:', function () {
258
276
  }
259
277
  ];
260
278
 
279
+ this.addBid = (bidParams = {}) => {
280
+ bidRequests.push({
281
+ bidId: 'b2',
282
+ bidder: '33across',
283
+ bidderRequestId: 'b1b',
284
+ params: {
285
+ siteId: SITE_ID,
286
+ productId: 'siab'
287
+ },
288
+ adUnitCode: 'div-id',
289
+ auctionId: 'r1',
290
+ mediaTypes: {},
291
+ transactionId: 't2',
292
+ ...bidParams
293
+ });
294
+
295
+ return this;
296
+ };
297
+
261
298
  this.withBanner = () => {
262
- bidRequests[0].mediaTypes.banner = {
263
- sizes: [
264
- [300, 250],
265
- [728, 90]
266
- ]
267
- };
299
+ bidRequests.forEach((bid) => {
300
+ bid.mediaTypes.banner = {
301
+ sizes: [
302
+ [300, 250],
303
+ [728, 90]
304
+ ]
305
+ };
306
+ });
268
307
 
269
308
  return this;
270
309
  };
271
310
 
272
311
  this.withProduct = (prod) => {
273
- bidRequests[0].params.productId = prod;
274
-
312
+ bidRequests.forEach((bid) => {
313
+ bid.params.productId = prod;
314
+ });
275
315
  return this;
276
316
  };
277
317
 
278
318
  this.withVideo = (params) => {
279
- bidRequests[0].mediaTypes.video = {
280
- playerSize: [[300, 250]],
281
- context: 'outstream',
282
- ...params
283
- };
319
+ bidRequests.forEach((bid) => {
320
+ bid.mediaTypes.video = {
321
+ playerSize: [[300, 250]],
322
+ context: 'outstream',
323
+ ...params
324
+ };
325
+ });
284
326
 
285
327
  return this;
286
328
  }
287
329
 
288
330
  this.withUserIds = (eids) => {
289
- bidRequests[0].userIdAsEids = eids;
331
+ bidRequests.forEach((bid) => {
332
+ bid.userIdAsEids = eids;
333
+ });
290
334
 
291
335
  return this;
292
336
  };
@@ -315,6 +359,7 @@ describe('33acrossBidAdapter:', function () {
315
359
  }
316
360
  };
317
361
  win = {
362
+ parent: null,
318
363
  document: {
319
364
  visibilityState: 'visible'
320
365
  },
@@ -331,7 +376,7 @@ describe('33acrossBidAdapter:', function () {
331
376
 
332
377
  sandbox = sinon.sandbox.create();
333
378
  sandbox.stub(Date, 'now').returns(1);
334
- sandbox.stub(document, 'getElementById').withArgs('div-id').returns(element);
379
+ sandbox.stub(document, 'getElementById').returns(element);
335
380
  sandbox.stub(utils, 'getWindowTop').returns(win);
336
381
  sandbox.stub(utils, 'getWindowSelf').returns(win);
337
382
  });
@@ -1376,10 +1421,146 @@ describe('33acrossBidAdapter:', function () {
1376
1421
  });
1377
1422
  });
1378
1423
  });
1424
+
1425
+ context('when SRA mode is enabled', function() {
1426
+ it('builds a single request with multiple imps corresponding to each group {siteId, productId}', function() {
1427
+ sandbox.stub(config, 'getConfig').callsFake(() => {
1428
+ return {
1429
+ enableSRAMode: true
1430
+ }
1431
+ });
1432
+
1433
+ const bidRequests = new BidRequestsBuilder()
1434
+ .addBid()
1435
+ .addBid({
1436
+ bidId: 'b3',
1437
+ adUnitCode: 'div-id',
1438
+ params: {
1439
+ siteId: 'sample33xGUID123456780',
1440
+ productId: 'siab'
1441
+ }
1442
+ })
1443
+ .addBid({
1444
+ bidId: 'b4',
1445
+ adUnitCode: 'div-id',
1446
+ params: {
1447
+ siteId: 'sample33xGUID123456780',
1448
+ productId: 'inview'
1449
+ }
1450
+ })
1451
+ .withBanner()
1452
+ .withVideo({context: 'outstream'})
1453
+ .build();
1454
+
1455
+ const req1 = new TtxRequestBuilder()
1456
+ .addImp()
1457
+ .withProduct('siab')
1458
+ .withBanner()
1459
+ .withVideo()
1460
+ .build();
1461
+
1462
+ const req2 = new TtxRequestBuilder('sample33xGUID123456780')
1463
+ .withProduct('siab')
1464
+ .withBanner()
1465
+ .withVideo()
1466
+ .build();
1467
+
1468
+ req2.imp[0].id = 'b3';
1469
+
1470
+ const req3 = new TtxRequestBuilder('sample33xGUID123456780')
1471
+ .withProduct('inview')
1472
+ .withBanner()
1473
+ .withVideo()
1474
+ .build();
1475
+
1476
+ req3.imp[0].id = 'b4';
1477
+
1478
+ const serverReq1 = new ServerRequestBuilder()
1479
+ .withData(req1)
1480
+ .build();
1481
+
1482
+ const serverReq2 = new ServerRequestBuilder()
1483
+ .withData(req2)
1484
+ .withUrl('https://ssc.33across.com/api/v1/hb?guid=sample33xGUID123456780')
1485
+ .build();
1486
+
1487
+ const serverReq3 = new ServerRequestBuilder()
1488
+ .withData(req3)
1489
+ .withUrl('https://ssc.33across.com/api/v1/hb?guid=sample33xGUID123456780')
1490
+ .build();
1491
+
1492
+ const builtServerRequests = spec.buildRequests(bidRequests, {});
1493
+
1494
+ expect(builtServerRequests).to.deep.equal([serverReq1, serverReq2, serverReq3]);
1495
+ });
1496
+ });
1497
+
1498
+ context('when SRA mode is not enabled', function() {
1499
+ it('builds multiple requests, one corresponding to each Ad Unit', function() {
1500
+ const bidRequests = new BidRequestsBuilder()
1501
+ .addBid()
1502
+ .addBid({
1503
+ bidId: 'b3',
1504
+ adUnitCode: 'div-id',
1505
+ params: {
1506
+ siteId: 'sample33xGUID123456780',
1507
+ productId: 'siab'
1508
+ }
1509
+ })
1510
+ .withBanner()
1511
+ .withVideo({context: 'outstream'})
1512
+ .build();
1513
+
1514
+ const req1 = new TtxRequestBuilder()
1515
+ .withProduct('siab')
1516
+ .withBanner()
1517
+ .withVideo()
1518
+ .build();
1519
+
1520
+ const req2 = new TtxRequestBuilder()
1521
+ .withProduct('siab')
1522
+ .withBanner()
1523
+ .withVideo()
1524
+ .build();
1525
+
1526
+ req2.imp[0].id = 'b2';
1527
+
1528
+ const req3 = new TtxRequestBuilder('sample33xGUID123456780')
1529
+ .withProduct('siab')
1530
+ .withBanner()
1531
+ .withVideo()
1532
+ .build();
1533
+
1534
+ req3.imp[0].id = 'b3';
1535
+
1536
+ const serverReq1 = new ServerRequestBuilder()
1537
+ .withData(req1)
1538
+ .build();
1539
+
1540
+ const serverReq2 = new ServerRequestBuilder()
1541
+ .withData(req2)
1542
+ .build();
1543
+
1544
+ const serverReq3 = new ServerRequestBuilder()
1545
+ .withData(req3)
1546
+ .withUrl('https://ssc.33across.com/api/v1/hb?guid=sample33xGUID123456780')
1547
+ .build();
1548
+
1549
+ const builtServerRequests = spec.buildRequests(bidRequests, {});
1550
+
1551
+ expect(builtServerRequests)
1552
+ .to.deep.equal([
1553
+ serverReq1,
1554
+ serverReq2,
1555
+ serverReq3
1556
+ ]);
1557
+ });
1558
+ });
1379
1559
  });
1380
1560
 
1381
1561
  describe('interpretResponse', function() {
1382
1562
  let ttxRequest, serverRequest;
1563
+ const videoBid = '<VAST version="3.0"><Ad></Ad></VAST>';
1383
1564
 
1384
1565
  beforeEach(function() {
1385
1566
  ttxRequest = new TtxRequestBuilder()
@@ -1390,6 +1571,7 @@ describe('33acrossBidAdapter:', function () {
1390
1571
  page: 'https://test-url.com'
1391
1572
  })
1392
1573
  .build();
1574
+
1393
1575
  serverRequest = new ServerRequestBuilder()
1394
1576
  .withUrl('https://staging-ssc.33across.com/api/v1/hb')
1395
1577
  .withData(ttxRequest)
@@ -1405,11 +1587,12 @@ describe('33acrossBidAdapter:', function () {
1405
1587
  const serverResponse = {
1406
1588
  cur: 'USD',
1407
1589
  ext: {},
1408
- id: 'b1',
1590
+ id: 'r1',
1409
1591
  seatbid: [
1410
1592
  {
1411
1593
  bid: [{
1412
1594
  id: '1',
1595
+ impid: 'b1',
1413
1596
  adm: '<html><h3>I am an ad</h3></html>',
1414
1597
  crid: 1,
1415
1598
  h: 250,
@@ -1441,15 +1624,15 @@ describe('33acrossBidAdapter:', function () {
1441
1624
  });
1442
1625
 
1443
1626
  it('interprets and returns the single video bid response', function() {
1444
- const videoBid = '<VAST version="3.0"><Ad></Ad></VAST>';
1445
1627
  const serverResponse = {
1446
1628
  cur: 'USD',
1447
1629
  ext: {},
1448
- id: 'b1',
1630
+ id: 'r1',
1449
1631
  seatbid: [
1450
1632
  {
1451
1633
  bid: [{
1452
1634
  id: '1',
1635
+ impid: 'b1',
1453
1636
  adm: videoBid,
1454
1637
  ext: {
1455
1638
  ttx: {
@@ -1497,6 +1680,7 @@ describe('33acrossBidAdapter:', function () {
1497
1680
  {
1498
1681
  bid: [{
1499
1682
  id: '1',
1683
+ impid: 'b1',
1500
1684
  adm: '<html><h3>I am an ad</h3></html>',
1501
1685
  crid: 1,
1502
1686
  h: 250,
@@ -1533,7 +1717,7 @@ describe('33acrossBidAdapter:', function () {
1533
1717
  const serverResponse = {
1534
1718
  cur: 'USD',
1535
1719
  ext: {},
1536
- id: 'b1',
1720
+ id: 'r1',
1537
1721
  seatbid: []
1538
1722
  };
1539
1723
 
@@ -1542,15 +1726,16 @@ describe('33acrossBidAdapter:', function () {
1542
1726
  });
1543
1727
 
1544
1728
  context('when more than one bids are returned', function() {
1545
- it('interprets and returns the the first bid of the first seatbid', function() {
1729
+ it('interprets and returns all bids', function() {
1546
1730
  const serverResponse = {
1547
1731
  cur: 'USD',
1548
1732
  ext: {},
1549
- id: 'b1',
1733
+ id: 'r1',
1550
1734
  seatbid: [
1551
1735
  {
1552
1736
  bid: [{
1553
1737
  id: '1',
1738
+ impid: 'b1',
1554
1739
  adm: '<html><h3>I am an ad</h3></html>',
1555
1740
  crid: 1,
1556
1741
  h: 250,
@@ -1559,6 +1744,7 @@ describe('33acrossBidAdapter:', function () {
1559
1744
  },
1560
1745
  {
1561
1746
  id: '2',
1747
+ impid: 'b2',
1562
1748
  adm: '<html><h3>I am an ad</h3></html>',
1563
1749
  crid: 2,
1564
1750
  h: 250,
@@ -1570,7 +1756,14 @@ describe('33acrossBidAdapter:', function () {
1570
1756
  {
1571
1757
  bid: [{
1572
1758
  id: '3',
1573
- adm: '<html><h3>I am an ad</h3></html>',
1759
+ impid: 'b3',
1760
+ adm: videoBid,
1761
+ ext: {
1762
+ ttx: {
1763
+ mediaType: 'video',
1764
+ vastType: 'xml'
1765
+ }
1766
+ },
1574
1767
  crid: 3,
1575
1768
  h: 250,
1576
1769
  w: 300,
@@ -1579,21 +1772,50 @@ describe('33acrossBidAdapter:', function () {
1579
1772
  }
1580
1773
  ]
1581
1774
  };
1582
- const bidResponse = {
1583
- requestId: 'b1',
1584
- bidderCode: BIDDER_CODE,
1585
- cpm: 0.0940,
1586
- width: 300,
1587
- height: 250,
1588
- ad: '<html><h3>I am an ad</h3></html>',
1589
- ttl: 60,
1590
- creativeId: 1,
1591
- mediaType: 'banner',
1592
- currency: 'USD',
1593
- netRevenue: true
1594
- };
1775
+ const bidResponse = [
1776
+ {
1777
+ requestId: 'b1',
1778
+ bidderCode: BIDDER_CODE,
1779
+ cpm: 0.0940,
1780
+ width: 300,
1781
+ height: 250,
1782
+ ad: '<html><h3>I am an ad</h3></html>',
1783
+ ttl: 60,
1784
+ creativeId: 1,
1785
+ mediaType: 'banner',
1786
+ currency: 'USD',
1787
+ netRevenue: true
1788
+ },
1789
+ {
1790
+ requestId: 'b2',
1791
+ bidderCode: BIDDER_CODE,
1792
+ cpm: 0.0938,
1793
+ width: 300,
1794
+ height: 250,
1795
+ ad: '<html><h3>I am an ad</h3></html>',
1796
+ ttl: 60,
1797
+ creativeId: 2,
1798
+ mediaType: 'banner',
1799
+ currency: 'USD',
1800
+ netRevenue: true
1801
+ },
1802
+ {
1803
+ requestId: 'b3',
1804
+ bidderCode: BIDDER_CODE,
1805
+ cpm: 0.0938,
1806
+ width: 300,
1807
+ height: 250,
1808
+ ad: videoBid,
1809
+ vastXml: '<VAST version=\"3.0\"><Ad></Ad></VAST>',
1810
+ ttl: 60,
1811
+ creativeId: 3,
1812
+ mediaType: 'video',
1813
+ currency: 'USD',
1814
+ netRevenue: true
1815
+ }
1816
+ ];
1595
1817
 
1596
- expect(spec.interpretResponse({ body: serverResponse }, serverRequest)).to.deep.equal([bidResponse]);
1818
+ expect(spec.interpretResponse({ body: serverResponse }, serverRequest)).to.deep.equal(bidResponse);
1597
1819
  });
1598
1820
  });
1599
1821
  });