prebid.js 6.7.0 → 6.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/.eslintrc.js +8 -1
  2. package/integrationExamples/gpt/{haloRtdProvider_example.html → hadronRtdProvider_example.html} +9 -9
  3. package/integrationExamples/gpt/idImportLibrary_example.html +2 -2
  4. package/integrationExamples/gpt/userId_example.html +2 -2
  5. package/integrationExamples/gpt/weboramaRtdProvider_example.html +154 -115
  6. package/integrationExamples/gpt/x-domain/creative.html +63 -29
  7. package/modules/.submodules.json +3 -0
  8. package/modules/adagioBidAdapter.js +0 -8
  9. package/modules/adagioBidAdapter.md +1 -1
  10. package/modules/adkernelBidAdapter.js +2 -1
  11. package/modules/adnuntiusRtdProvider.js +96 -0
  12. package/modules/adnuntiusRtdProvider.md +41 -0
  13. package/modules/adotBidAdapter.js +516 -567
  14. package/modules/adotBidAdapter.md +6 -44
  15. package/modules/adpod.js +12 -14
  16. package/modules/adyoulikeBidAdapter.js +2 -0
  17. package/modules/appnexusBidAdapter.js +14 -2
  18. package/modules/asealBidAdapter.js +58 -0
  19. package/modules/asealBidAdapter.md +52 -0
  20. package/modules/brandmetricsRtdProvider.js +168 -0
  21. package/modules/brandmetricsRtdProvider.md +40 -0
  22. package/modules/conversantBidAdapter.js +7 -0
  23. package/modules/criteoBidAdapter.js +9 -0
  24. package/modules/currency.js +27 -5
  25. package/modules/displayioBidAdapter.js +157 -0
  26. package/modules/displayioBidAdapter.md +148 -0
  27. package/modules/dspxBidAdapter.js +69 -29
  28. package/modules/dspxBidAdapter.md +2 -1
  29. package/modules/e_volutionBidAdapter.js +158 -0
  30. package/modules/gridBidAdapter.js +15 -1
  31. package/modules/gumgumBidAdapter.js +52 -38
  32. package/modules/hadronIdSystem.js +96 -0
  33. package/modules/hadronIdSystem.md +35 -0
  34. package/modules/hadronRtdProvider.js +254 -0
  35. package/modules/hadronRtdProvider.md +126 -0
  36. package/modules/haloIdSystem.md +4 -35
  37. package/modules/haloRtdProvider.md +3 -126
  38. package/modules/imRtdProvider.js +10 -0
  39. package/modules/improvedigitalBidAdapter.js +5 -0
  40. package/modules/interactiveOffersBidAdapter.js +9 -6
  41. package/modules/iqzoneBidAdapter.js +10 -3
  42. package/modules/iqzoneBidAdapter.md +16 -0
  43. package/modules/ixBidAdapter.js +2 -6
  44. package/modules/kubientBidAdapter.js +50 -19
  45. package/modules/lunamediahbBidAdapter.js +32 -4
  46. package/modules/malltvBidAdapter.js +7 -3
  47. package/modules/malltvBidAdapter.md +64 -51
  48. package/modules/mass.js +3 -5
  49. package/modules/mediakeysBidAdapter.js +0 -5
  50. package/modules/medianetAnalyticsAdapter.js +1 -1
  51. package/modules/mediasquareBidAdapter.js +9 -1
  52. package/modules/nextMillenniumBidAdapter.js +1 -0
  53. package/modules/oguryBidAdapter.js +7 -14
  54. package/modules/prebidServerBidAdapter/index.js +61 -39
  55. package/modules/priceFloors.js +20 -12
  56. package/modules/pubmaticBidAdapter.js +1 -1
  57. package/modules/richaudienceBidAdapter.js +8 -3
  58. package/modules/riseBidAdapter.js +17 -6
  59. package/modules/rtbhouseBidAdapter.js +2 -0
  60. package/modules/rubiconAnalyticsAdapter.js +5 -0
  61. package/modules/rubiconBidAdapter.js +2 -2
  62. package/modules/sizeMappingV2.js +1 -8
  63. package/modules/sortableAnalyticsAdapter.js +5 -4
  64. package/modules/sovrnBidAdapter.js +93 -18
  65. package/modules/sovrnBidAdapter.md +80 -2
  66. package/modules/sspBCBidAdapter.js +53 -20
  67. package/modules/telariaBidAdapter.js +22 -29
  68. package/modules/trustpidSystem.js +197 -0
  69. package/modules/trustpidSystem.md +45 -0
  70. package/modules/undertoneBidAdapter.js +17 -1
  71. package/modules/userId/eids.js +16 -1
  72. package/modules/userId/eids.md +10 -2
  73. package/modules/userId/userId.md +17 -2
  74. package/modules/vibrantmediaBidAdapter.js +220 -0
  75. package/modules/vibrantmediaBidAdapter.md +92 -0
  76. package/modules/vidoomyBidAdapter.js +8 -0
  77. package/modules/vidoomyBidAdapter.md +4 -2
  78. package/modules/weboramaRtdProvider.js +264 -34
  79. package/modules/weboramaRtdProvider.md +110 -40
  80. package/modules/yahoosspBidAdapter.js +3 -1
  81. package/modules/yieldoneBidAdapter.js +6 -0
  82. package/package.json +2 -1
  83. package/src/adRendering.js +38 -0
  84. package/src/adapterManager.js +24 -19
  85. package/src/adapters/bidderFactory.js +14 -11
  86. package/src/adloader.js +2 -1
  87. package/src/auction.js +138 -115
  88. package/src/auctionIndex.js +85 -0
  89. package/src/auctionManager.js +3 -0
  90. package/src/bidderSettings.js +69 -0
  91. package/src/bidfactory.js +18 -6
  92. package/src/native.js +29 -21
  93. package/src/prebid.js +3 -19
  94. package/src/secureCreatives.js +128 -45
  95. package/src/targeting.js +11 -2
  96. package/src/utils.js +14 -17
  97. package/src/video.js +10 -11
  98. package/src/videoCache.js +10 -9
  99. package/test/fixtures/fixtures.js +2 -1
  100. package/test/helpers/indexStub.js +28 -0
  101. package/test/helpers/syncPromise.js +71 -0
  102. package/test/spec/auctionmanager_spec.js +268 -89
  103. package/test/spec/config_spec.js +24 -1
  104. package/test/spec/modules/adagioBidAdapter_spec.js +0 -10
  105. package/test/spec/modules/adnuntiusRtdProvider_spec.js +145 -0
  106. package/test/spec/modules/adotBidAdapter_spec.js +294 -3124
  107. package/test/spec/modules/adpod_spec.js +91 -156
  108. package/test/spec/modules/adyoulikeBidAdapter_spec.js +4 -0
  109. package/test/spec/modules/appnexusBidAdapter_spec.js +27 -0
  110. package/test/spec/modules/asealBidAdapter_spec.js +144 -0
  111. package/test/spec/modules/brandmetricsRtdProvider_spec.js +191 -0
  112. package/test/spec/modules/conversantBidAdapter_spec.js +54 -2
  113. package/test/spec/modules/criteoBidAdapter_spec.js +21 -0
  114. package/test/spec/modules/currency_spec.js +36 -15
  115. package/test/spec/modules/displayioBidAdapter_spec.js +239 -0
  116. package/test/spec/modules/dspxBidAdapter_spec.js +20 -15
  117. package/test/spec/modules/e_volutionBidAdapter_spec.js +242 -0
  118. package/test/spec/modules/eids_spec.js +2 -2
  119. package/test/spec/modules/gridBidAdapter_spec.js +18 -0
  120. package/test/spec/modules/gumgumBidAdapter_spec.js +49 -3
  121. package/test/spec/modules/hadronIdSystem_spec.js +57 -0
  122. package/test/spec/modules/hadronRtdProvider_spec.js +762 -0
  123. package/test/spec/modules/imRtdProvider_spec.js +30 -1
  124. package/test/spec/modules/improvedigitalBidAdapter_spec.js +19 -0
  125. package/test/spec/modules/iqzoneBidAdapter_spec.js +1 -0
  126. package/test/spec/modules/ixBidAdapter_spec.js +1 -1
  127. package/test/spec/modules/kubientBidAdapter_spec.js +182 -84
  128. package/test/spec/modules/lunamediahbBidAdapter_spec.js +27 -1
  129. package/test/spec/modules/mass_spec.js +2 -14
  130. package/test/spec/modules/mediakeysBidAdapter_spec.js +9 -5
  131. package/test/spec/modules/mediasquareBidAdapter_spec.js +25 -1
  132. package/test/spec/modules/oguryBidAdapter_spec.js +63 -5
  133. package/test/spec/modules/prebidServerBidAdapter_spec.js +43 -6
  134. package/test/spec/modules/priceFloors_spec.js +83 -24
  135. package/test/spec/modules/pubmaticBidAdapter_spec.js +40 -0
  136. package/test/spec/modules/riseBidAdapter_spec.js +30 -4
  137. package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +31 -1
  138. package/test/spec/modules/rubiconBidAdapter_spec.js +1 -1
  139. package/test/spec/modules/sortableAnalyticsAdapter_spec.js +2 -3
  140. package/test/spec/modules/sovrnBidAdapter_spec.js +413 -333
  141. package/test/spec/modules/sspBCBidAdapter_spec.js +7 -7
  142. package/test/spec/modules/telariaBidAdapter_spec.js +1 -3
  143. package/test/spec/modules/trustpidSystem_spec.js +232 -0
  144. package/test/spec/modules/undertoneBidAdapter_spec.js +55 -2
  145. package/test/spec/modules/userId_spec.js +39 -39
  146. package/test/spec/modules/vibrantmediaBidAdapter_spec.js +1237 -0
  147. package/test/spec/modules/vidoomyBidAdapter_spec.js +7 -1
  148. package/test/spec/modules/weboramaRtdProvider_spec.js +536 -20
  149. package/test/spec/modules/yahoosspBidAdapter_spec.js +10 -0
  150. package/test/spec/modules/yieldoneBidAdapter_spec.js +33 -0
  151. package/test/spec/native_spec.js +62 -40
  152. package/test/spec/unit/core/adapterManager_spec.js +22 -0
  153. package/test/spec/unit/core/auctionIndex_spec.js +129 -0
  154. package/test/spec/unit/core/bidderFactory_spec.js +65 -12
  155. package/test/spec/unit/core/bidderSettings_spec.js +123 -0
  156. package/test/spec/unit/core/targeting_spec.js +93 -0
  157. package/test/spec/unit/pbjs_api_spec.js +80 -42
  158. package/test/spec/unit/secureCreatives_spec.js +143 -24
  159. package/test/spec/videoCache_spec.js +18 -19
  160. package/test/spec/video_spec.js +51 -61
@@ -0,0 +1,1237 @@
1
+ import {expect} from 'chai';
2
+ import {spec} from 'modules/vibrantmediaBidAdapter.js';
3
+ import {newBidder} from 'src/adapters/bidderFactory.js';
4
+ import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes.js';
5
+ import {INSTREAM, OUTSTREAM} from 'src/video.js';
6
+
7
+ const EXPECTED_PREBID_SERVER_URL = 'https://prebid.intellitxt.com/prebid';
8
+
9
+ const BANNER_AD =
10
+ '<!DOCTYPE html><html lang="en"><head><title>Test Banner Ad Unit</title></head><body>Hello!</body></html>';
11
+ const VIDEO_AD = '<!DOCTYPE html><html lang="en"><head><title>Test Video Ad Unit</title></head>' +
12
+ '<script type="text/javascript" src="https://www.example.com/myvideo.mp3"></script></body></html>';
13
+
14
+ const VALID_BANNER_BID_PARAMS = Object.freeze({
15
+ member: '1234',
16
+ invCode: 'ABCD',
17
+ placementId: '10433394'
18
+ });
19
+
20
+ const VALID_VIDEO_BID_PARAMS = Object.freeze({
21
+ member: '1234',
22
+ invCode: 'ABCD',
23
+ placementId: '10433394',
24
+ video: {
25
+ skippable: false,
26
+ playback_method: 'auto_play_sound_off'
27
+ }
28
+ });
29
+
30
+ const VALID_NATIVE_BID_PARAMS = VALID_BANNER_BID_PARAMS;
31
+
32
+ const DEFAULT_BID_SIZES = [[300, 250], [600, 240]];
33
+
34
+ const VALID_CONSENT_STRING = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==';
35
+
36
+ const getValidBidderRequest = (bidRequests) => {
37
+ return Object.freeze({
38
+ bidderCode: 'vibrantmedia',
39
+ auctionId: '1d1a030790a475',
40
+ bidderRequestId: '22edbae2733bf6',
41
+ timeout: 3000,
42
+ gdprConsent: {
43
+ consentString: VALID_CONSENT_STRING,
44
+ vendorData: {},
45
+ gdprApplies: true,
46
+ },
47
+ bids: bidRequests,
48
+ });
49
+ };
50
+
51
+ describe('VibrantMediaBidAdapter', function () {
52
+ const adapter = newBidder(spec);
53
+
54
+ describe('constants', function () {
55
+ expect(spec.code).to.equal('vibrantmedia');
56
+ expect(spec.supportedMediaTypes).to.deep.equal([BANNER, NATIVE, VIDEO]);
57
+ });
58
+
59
+ describe('inherited functions', function () {
60
+ it('exists and is a function', function () {
61
+ expect(adapter.callBids).to.exist.and.to.be.a('function');
62
+ });
63
+ });
64
+
65
+ describe('transformBidParams', function () {
66
+ it('transforms bid params correctly', function () {
67
+ expect(spec.transformBidParams(VALID_VIDEO_BID_PARAMS)).to.deep.equal(VALID_VIDEO_BID_PARAMS);
68
+ });
69
+ })
70
+
71
+ let bidRequest;
72
+
73
+ beforeEach(function () {
74
+ bidRequest = {
75
+ bidder: 'vibrantmedia',
76
+ params: {
77
+ // Filled in by individual tests
78
+ },
79
+ mediaTypes: {
80
+ // Filled in by individual tests
81
+ },
82
+ adUnitCode: 'test-div',
83
+ transactionId: '13579acef87623',
84
+ placementId: '7623587623857',
85
+ bidId: '30b31c1838de1e',
86
+ bidderRequestId: '22edbae2733bf6',
87
+ auctionId: '1d1a030790a475'
88
+ };
89
+ });
90
+
91
+ describe('isBidRequestValid', function () {
92
+ describe('with banner bid requests', function () {
93
+ beforeEach(function () {
94
+ bidRequest.mediaTypes.banner = {
95
+ sizes: DEFAULT_BID_SIZES,
96
+ };
97
+ });
98
+
99
+ it('should return true for a valid banner bid request', function () {
100
+ bidRequest.params = VALID_BANNER_BID_PARAMS;
101
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
102
+ });
103
+
104
+ it('should return true for a valid banner bid request with a member id and inventory code', function () {
105
+ bidRequest.params = {
106
+ member: '1234',
107
+ invCode: 'ABCD',
108
+ };
109
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
110
+ });
111
+
112
+ it('should return true for a valid banner bid request with a placement id', function () {
113
+ bidRequest.params = {
114
+ placementId: '10433394',
115
+ };
116
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
117
+ });
118
+
119
+ it('should return false for a valid banner bid request but with a member id and no inventory code', function () {
120
+ bidRequest.params = {
121
+ member: '1234',
122
+ };
123
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
124
+ });
125
+
126
+ it('should return false for a valid banner bid request but with no member id and an inventory code', function () {
127
+ bidRequest.params = {
128
+ invCode: 'ABCD',
129
+ };
130
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
131
+ });
132
+
133
+ it('should return false for a valid banner bid request but with no supported media types', function () {
134
+ bidRequest.params = {
135
+ placementId: '10433394',
136
+ };
137
+ delete bidRequest.mediaTypes.banner;
138
+ bidRequest.mediaTypes.unsupported = {
139
+ sizes: DEFAULT_BID_SIZES,
140
+ }
141
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
142
+ });
143
+
144
+ it('should return false for a valid banner bid request but with no params', function () {
145
+ bidRequest.params = {};
146
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
147
+ });
148
+ });
149
+
150
+ describe('with video bid requests', function () {
151
+ describe('with sizes attribute', function () {
152
+ const validVideoMediaTypes = {
153
+ context: OUTSTREAM,
154
+ sizes: DEFAULT_BID_SIZES,
155
+ minduration: 1,
156
+ maxduration: 60,
157
+ skip: 0,
158
+ skipafter: 5,
159
+ playbackmethod: [2],
160
+ protocols: [1, 2, 3]
161
+ };
162
+
163
+ it('should return true for a valid video bid request', function () {
164
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
165
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
166
+
167
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
168
+ });
169
+
170
+ it('should return false for an instream video bid request', function () {
171
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
172
+ bidRequest.mediaTypes.video = {
173
+ context: INSTREAM,
174
+ sizes: DEFAULT_BID_SIZES,
175
+ };
176
+
177
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
178
+ });
179
+
180
+ it('should return false for a video bid request with an unknown context', function () {
181
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
182
+ bidRequest.mediaTypes.video = {
183
+ context: 'fake',
184
+ sizes: DEFAULT_BID_SIZES,
185
+ };
186
+
187
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
188
+ });
189
+
190
+ it('should return false for a video bid request with no context', function () {
191
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
192
+ bidRequest.mediaTypes.video = {
193
+ sizes: DEFAULT_BID_SIZES,
194
+ };
195
+
196
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
197
+ });
198
+
199
+ it('should return true for a valid video bid request with a member id and inventory code', function () {
200
+ bidRequest.params = {
201
+ member: '1234',
202
+ invCode: 'ABCD',
203
+ };
204
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
205
+
206
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
207
+ });
208
+
209
+ it('should return true for a valid video bid request with a placement id', function () {
210
+ bidRequest.params = {
211
+ placementId: '10433394',
212
+ };
213
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
214
+
215
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
216
+ });
217
+
218
+ it('should return false for a valid video bid request but with a member id and no inventory code', function () {
219
+ bidRequest.params = {
220
+ member: '1234',
221
+ };
222
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
223
+
224
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
225
+ });
226
+
227
+ it('should return false for a valid video bid request but with no member id and an inventory code', function () {
228
+ bidRequest.params = {
229
+ invCode: 'ABCD',
230
+ };
231
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
232
+
233
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
234
+ });
235
+
236
+ it('should return false for a valid video bid request but with no params', function () {
237
+ bidRequest.params = {};
238
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
239
+
240
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
241
+ });
242
+ });
243
+
244
+ describe('with playerSize attribute', function () {
245
+ const validVideoMediaTypes = {
246
+ context: OUTSTREAM,
247
+ playerSize: DEFAULT_BID_SIZES,
248
+ minduration: 1,
249
+ maxduration: 60,
250
+ skip: 0,
251
+ skipafter: 5,
252
+ playbackmethod: [2],
253
+ protocols: [1, 2, 3]
254
+ };
255
+
256
+ beforeEach(function () {
257
+ bidRequest.mediaTypes.video = {
258
+ // Filled in by individual tests
259
+ };
260
+ });
261
+
262
+ it('should return true for a valid video bid request', function () {
263
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
264
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
265
+
266
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
267
+ });
268
+
269
+ it('should return false for an instream video bid request', function () {
270
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
271
+ bidRequest.mediaTypes.video = {
272
+ context: INSTREAM,
273
+ playerSize: DEFAULT_BID_SIZES,
274
+ };
275
+
276
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
277
+ });
278
+
279
+ it('should return false for a video bid request with an unknown context', function () {
280
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
281
+ bidRequest.mediaTypes.video = {
282
+ context: 'fake',
283
+ playerSize: DEFAULT_BID_SIZES,
284
+ };
285
+
286
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
287
+ });
288
+
289
+ it('should return false for a video bid request with no context', function () {
290
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
291
+ bidRequest.mediaTypes.video = {
292
+ playerSize: DEFAULT_BID_SIZES,
293
+ };
294
+
295
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
296
+ });
297
+
298
+ it('should return true for a valid video bid request with a member id and inventory code', function () {
299
+ bidRequest.params = {
300
+ member: '1234',
301
+ invCode: 'ABCD',
302
+ };
303
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
304
+
305
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
306
+ });
307
+
308
+ it('should return true for a valid video bid request with a placement id', function () {
309
+ bidRequest.params = {
310
+ placementId: '10433394',
311
+ };
312
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
313
+
314
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
315
+ });
316
+
317
+ it('should return false for a valid video bid request but with a member id and no inventory code', function () {
318
+ bidRequest.params = {
319
+ member: '1234',
320
+ };
321
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
322
+
323
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
324
+ });
325
+
326
+ it('should return false for a valid video bid request but with no member id and an inventory code', function () {
327
+ bidRequest.params = {
328
+ invCode: 'ABCD',
329
+ };
330
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
331
+
332
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
333
+ });
334
+
335
+ it('should return false for a valid video bid request but with no params', function () {
336
+ bidRequest.params = {};
337
+ bidRequest.mediaTypes.video = validVideoMediaTypes;
338
+
339
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
340
+ });
341
+ });
342
+ });
343
+
344
+ describe('with native bid requests', function () {
345
+ beforeEach(function () {
346
+ bidRequest.mediaTypes.native = {
347
+ image: {
348
+ required: true,
349
+ // Sizes is filled in by individual tests
350
+ },
351
+ title: {
352
+ required: true
353
+ },
354
+ sponsoredBy: {
355
+ required: true
356
+ },
357
+ clickUrl: {
358
+ required: true
359
+ }
360
+ };
361
+ });
362
+
363
+ it('should return true for a valid native bid request with a single size', function () {
364
+ bidRequest.params = VALID_NATIVE_BID_PARAMS;
365
+ bidRequest.mediaTypes.native.image.sizes = [300, 250];
366
+
367
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
368
+ });
369
+
370
+ it('should return true for a valid native bid request with multiple sizes', function () {
371
+ bidRequest.params = VALID_NATIVE_BID_PARAMS;
372
+ bidRequest.mediaTypes.native.image.sizes = [[300, 250], [300, 600]];
373
+
374
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
375
+ });
376
+
377
+ it('should return true for a valid native bid request with a member id and inventory code', function () {
378
+ bidRequest.params = {
379
+ member: '1234',
380
+ invCode: 'ABCD',
381
+ };
382
+ bidRequest.mediaTypes.native.image.sizes = [300, 250];
383
+
384
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
385
+ });
386
+
387
+ it('should return true for a valid native bid request with a placement id', function () {
388
+ bidRequest.params = {
389
+ placementId: '10433394',
390
+ };
391
+ bidRequest.mediaTypes.native.image.sizes = [300, 250];
392
+
393
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
394
+ });
395
+
396
+ it('should return false for a valid native bid request but with a member id and no inventory code', function () {
397
+ bidRequest.params = {
398
+ member: '1234',
399
+ };
400
+ bidRequest.mediaTypes.native.image.sizes = [300, 250];
401
+
402
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
403
+ });
404
+
405
+ it('should return false for a valid native bid request but with no member id and an inventory code', function () {
406
+ bidRequest.params = {
407
+ invCode: 'ABCD',
408
+ };
409
+ bidRequest.mediaTypes.native.image.sizes = [300, 250];
410
+
411
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
412
+ });
413
+
414
+ it('should return false for a valid native bid request but with no params', function () {
415
+ bidRequest.params = {};
416
+ bidRequest.mediaTypes.native.image.sizes = [300, 250];
417
+
418
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
419
+ });
420
+
421
+ it('should return false for a native bid request with no image property', function () {
422
+ bidRequest.params = VALID_NATIVE_BID_PARAMS;
423
+ delete bidRequest.mediaTypes.native.image;
424
+
425
+ expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
426
+ });
427
+ });
428
+ });
429
+
430
+ describe('buildRequests', function () {
431
+ let bidRequests;
432
+
433
+ beforeEach(function () {
434
+ bidRequests = [bidRequest];
435
+
436
+ bidRequests[0].params = VALID_BANNER_BID_PARAMS;
437
+ bidRequests[0].mediaTypes.banner = {
438
+ sizes: DEFAULT_BID_SIZES,
439
+ };
440
+ });
441
+
442
+ it('should use HTTP POST', function () {
443
+ const request = spec.buildRequests(bidRequests, {});
444
+ expect(request.method).to.equal('POST');
445
+ });
446
+
447
+ it('should use the correct prebid server URL', function () {
448
+ const request = spec.buildRequests(bidRequests, {});
449
+ expect(request.url).to.equal(EXPECTED_PREBID_SERVER_URL);
450
+ });
451
+
452
+ it('should add the page URL to the server request', function () {
453
+ const request = spec.buildRequests(bidRequests, {});
454
+ const payload = JSON.parse(request.data);
455
+
456
+ expect(payload.url).to.exist;
457
+ expect(payload.url).to.be.a('string');
458
+ });
459
+
460
+ it('should add GDPR consent to the server request, where present', function () {
461
+ const bidderRequest = {
462
+ bidderCode: 'vibrantmedia',
463
+ auctionId: '1d1a030790a475',
464
+ bidderRequestId: '22edbae2733bf6',
465
+ timeout: 3000,
466
+ gdprConsent: {
467
+ consentString: VALID_CONSENT_STRING,
468
+ gdprApplies: true,
469
+ },
470
+ bids: bidRequests,
471
+ };
472
+
473
+ const request = spec.buildRequests(bidRequests, bidderRequest);
474
+ // TODO: Check that we should not be implementing withCredentials
475
+ // expect(request.options).to.deep.equal({withCredentials: true});
476
+
477
+ const payload = JSON.parse(request.data);
478
+ expect(payload.gdpr).to.exist;
479
+ expect(payload.gdpr.consentString).to.exist.and.to.equal(VALID_CONSENT_STRING);
480
+ expect(payload.gdpr.gdprApplies).to.exist.and.to.be.true;
481
+ });
482
+
483
+ it('should add USP consent to the server request, where present', function () {
484
+ const bidderRequest = {
485
+ bidderCode: 'vibrantmedia',
486
+ auctionId: '1d1a030790a475',
487
+ bidderRequestId: '22edbae2733bf6',
488
+ timeout: 3000,
489
+ uspConsent: {
490
+ cmpApi: 'iab',
491
+ timeout: 10000,
492
+ consentData: {
493
+ testDatum: true
494
+ }
495
+ },
496
+ bids: bidRequests
497
+ };
498
+
499
+ const request = spec.buildRequests(bidRequests, bidderRequest);
500
+ // TODO: Check that we should not be implementing withCredentials
501
+ // expect(request.options).to.deep.equal({withCredentials: true});
502
+
503
+ const payload = JSON.parse(request.data);
504
+ expect(payload.usp).to.exist;
505
+ expect(payload.usp.cmpApi).to.exist.and.to.equal('iab');
506
+ expect(payload.usp.timeout).to.exist.and.to.equal(10000);
507
+ expect(payload.usp.consentData).to.exist.and.to.deep.equal({
508
+ testDatum: true
509
+ });
510
+ });
511
+
512
+ it('should add GDPR and USP consent to the server request, where both present', function () {
513
+ const bidderRequest = {
514
+ bidderCode: 'vibrantmedia',
515
+ auctionId: '1d1a030790a475',
516
+ bidderRequestId: '22edbae2733bf6',
517
+ timeout: 3000,
518
+ gdprConsent: {
519
+ consentString: VALID_CONSENT_STRING,
520
+ gdprApplies: true,
521
+ },
522
+ uspConsent: {
523
+ cmpApi: 'iab',
524
+ timeout: 10000,
525
+ consentData: {
526
+ testDatum: true
527
+ }
528
+ },
529
+ bids: bidRequests,
530
+ };
531
+
532
+ const request = spec.buildRequests(bidRequests, bidderRequest);
533
+ // TODO: Check that we should not be implementing withCredentials
534
+ // expect(request.options).to.deep.equal({withCredentials: true});
535
+
536
+ const payload = JSON.parse(request.data);
537
+
538
+ expect(payload.gdpr).to.exist;
539
+ expect(payload.gdpr.consentString).to.exist.and.to.equal(VALID_CONSENT_STRING);
540
+ expect(payload.gdpr.gdprApplies).to.exist.and.to.be.true;
541
+
542
+ expect(payload.usp).to.exist;
543
+ expect(payload.usp.cmpApi).to.exist.and.to.equal('iab');
544
+ expect(payload.usp.timeout).to.exist.and.to.equal(10000);
545
+ expect(payload.usp.consentData).to.exist.and.to.deep.equal({
546
+ testDatum: true
547
+ });
548
+ });
549
+
550
+ it('should add window dimensions to the server request', function () {
551
+ const request = spec.buildRequests(bidRequests, {});
552
+ const payload = JSON.parse(request.data);
553
+
554
+ expect(payload.window).to.exist;
555
+ expect(payload.window.width).to.equal(window.innerWidth);
556
+ expect(payload.window.height).to.equal(window.innerHeight);
557
+ });
558
+
559
+ it('should add the top-level sizes to the bid request, if present', function () {
560
+ bidRequest.params = VALID_BANNER_BID_PARAMS;
561
+ bidRequest.sizes = DEFAULT_BID_SIZES;
562
+ bidRequest.mediaTypes = {
563
+ banner: {},
564
+ };
565
+
566
+ const request = spec.buildRequests(bidRequests, {}, true);
567
+ const payload = JSON.parse(request.data);
568
+
569
+ expect(payload.biddata).to.exist;
570
+ expect(payload.biddata.length).to.equal(1);
571
+ expect(payload.biddata[0]).to.exist;
572
+ expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode);
573
+ expect(payload.biddata[0].id).to.equal(bidRequest.placementId);
574
+ expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder);
575
+ expect(payload.biddata[0].sizes).to.deep.equal(DEFAULT_BID_SIZES);
576
+ expect(payload.biddata[0].mediaTypes).to.exist;
577
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.exist;
578
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({});
579
+ });
580
+
581
+ it('should add the list of bids to the bid request, if present', function () {
582
+ const testBid = {
583
+ bidder: 'testBidder',
584
+ params: {
585
+ placement: '12345'
586
+ }
587
+ };
588
+
589
+ bidRequest.params = VALID_BANNER_BID_PARAMS;
590
+ bidRequest.bids = [testBid];
591
+ bidRequest.mediaTypes = {
592
+ banner: {},
593
+ };
594
+
595
+ // These will be present in the list of bids instead
596
+ delete bidRequest.bidId;
597
+ delete bidRequest.transactionId;
598
+ delete bidRequest.bidder;
599
+
600
+ const request = spec.buildRequests(bidRequests, {}, true);
601
+ const payload = JSON.parse(request.data);
602
+
603
+ expect(payload.biddata).to.exist;
604
+ expect(payload.biddata.length).to.equal(1);
605
+ expect(payload.biddata[0]).to.exist;
606
+ expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode);
607
+ expect(payload.biddata[0].id).to.equal(bidRequest.placementId);
608
+ expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder);
609
+ expect(payload.biddata[0].bids.length).to.equal(1);
610
+ expect(payload.biddata[0].bids[0]).to.deep.equal(testBid);
611
+ expect(payload.biddata[0].mediaTypes).to.exist;
612
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.exist;
613
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({});
614
+ });
615
+
616
+ it('should add the correct bid data to the server request for one bid request', function () {
617
+ bidRequest.params = VALID_BANNER_BID_PARAMS;
618
+ bidRequest.mediaTypes = {
619
+ banner: {
620
+ sizes: DEFAULT_BID_SIZES,
621
+ },
622
+ };
623
+
624
+ const request = spec.buildRequests(bidRequests, {}, true);
625
+ const payload = JSON.parse(request.data);
626
+
627
+ expect(payload.biddata).to.exist;
628
+ expect(payload.biddata.length).to.equal(1);
629
+ expect(payload.biddata[0]).to.exist;
630
+ expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode);
631
+ expect(payload.biddata[0].id).to.equal(bidRequest.placementId);
632
+ expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder);
633
+ expect(payload.biddata[0].sizes).to.be.undefined;
634
+ expect(payload.biddata[0].mediaTypes).to.exist;
635
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.exist;
636
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({
637
+ sizes: DEFAULT_BID_SIZES,
638
+ });
639
+ });
640
+
641
+ it('should add the correct bid data to the server request for multiple bid requests', function () {
642
+ bidRequest.params = VALID_BANNER_BID_PARAMS;
643
+ bidRequest.mediaTypes = {
644
+ banner: {
645
+ sizes: DEFAULT_BID_SIZES,
646
+ },
647
+ };
648
+ const bid2 = {
649
+ bidder: 'vibrantmedia',
650
+ params: VALID_VIDEO_BID_PARAMS,
651
+ mediaTypes: {
652
+ video: {
653
+ context: OUTSTREAM,
654
+ sizes: DEFAULT_BID_SIZES,
655
+ }
656
+ },
657
+ adUnitCode: 'video-div',
658
+ bidId: '30b31c1838de1f',
659
+ placementId: '135797531abcdef',
660
+ bidderRequestId: '22edbae2733bf6',
661
+ auctionId: '1d1a030790a475',
662
+ };
663
+ const bid3 = {
664
+ bidder: 'vibrantmedia',
665
+ params: VALID_NATIVE_BID_PARAMS,
666
+ mediaTypes: {
667
+ native: {
668
+ image: {
669
+ required: true,
670
+ sizes: [300, 250]
671
+ },
672
+ title: {
673
+ required: true
674
+ },
675
+ sponsoredBy: {
676
+ required: true
677
+ },
678
+ clickUrl: {
679
+ required: true
680
+ }
681
+ }
682
+ },
683
+ adUnitCode: 'native-div',
684
+ bidId: '30b31c1838de14',
685
+ placementId: '918273645abcdef',
686
+ bidderRequestId: '22edbae2733bf6',
687
+ auctionId: '1d1a030790a475',
688
+ };
689
+
690
+ bidRequests.push(bid2, bid3);
691
+
692
+ const request = spec.buildRequests(bidRequests, {}, true);
693
+ const payload = JSON.parse(request.data);
694
+
695
+ expect(payload.biddata).to.exist;
696
+ expect(payload.biddata.length).to.equal(3);
697
+ expect(payload.biddata[0]).to.exist;
698
+ expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode);
699
+ expect(payload.biddata[0].id).to.equal(bidRequest.placementId);
700
+ expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder);
701
+ expect(payload.biddata[0].mediaTypes).to.exist;
702
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.exist;
703
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({
704
+ sizes: DEFAULT_BID_SIZES,
705
+ });
706
+ expect(payload.biddata[1]).to.exist;
707
+ expect(payload.biddata[1].code).to.equal(bid2.adUnitCode);
708
+ expect(payload.biddata[1].id).to.equal(bid2.placementId);
709
+ expect(payload.biddata[1].bidder).to.equal(bid2.bidder);
710
+ expect(payload.biddata[1].mediaTypes).to.exist;
711
+ expect(payload.biddata[1].mediaTypes[VIDEO]).to.exist;
712
+ expect(payload.biddata[1].mediaTypes[VIDEO]).to.deep.equal({
713
+ context: OUTSTREAM,
714
+ sizes: DEFAULT_BID_SIZES,
715
+ });
716
+ expect(payload.biddata[2]).to.exist;
717
+ expect(payload.biddata[2].code).to.equal(bid3.adUnitCode);
718
+ expect(payload.biddata[2].id).to.equal(bid3.placementId);
719
+ expect(payload.biddata[2].bidder).to.equal(bid3.bidder);
720
+ expect(payload.biddata[2].mediaTypes[NATIVE]).to.exist;
721
+ expect(payload.biddata[2].mediaTypes[NATIVE]).to.deep.equal(bid3.mediaTypes.native);
722
+ });
723
+
724
+ it('should add the correct bid data to the bid request where a bid has multiple media types', function () {
725
+ bidRequest.params = VALID_VIDEO_BID_PARAMS;
726
+ bidRequest.mediaTypes = {
727
+ banner: {
728
+ sizes: DEFAULT_BID_SIZES,
729
+ },
730
+ video: {
731
+ context: OUTSTREAM,
732
+ sizes: DEFAULT_BID_SIZES,
733
+ },
734
+ native: {
735
+ image: {
736
+ required: true,
737
+ sizes: [300, 250]
738
+ },
739
+ title: {
740
+ required: true
741
+ },
742
+ sponsoredBy: {
743
+ required: true
744
+ },
745
+ clickUrl: {
746
+ required: true
747
+ }
748
+ }
749
+ };
750
+ bidRequest.adUnitCode = 'mixed-div';
751
+
752
+ const bid2 = {
753
+ bidder: 'vibrantmedia',
754
+ params: VALID_VIDEO_BID_PARAMS,
755
+ mediaTypes: {
756
+ video: {
757
+ context: OUTSTREAM,
758
+ sizes: DEFAULT_BID_SIZES,
759
+ }
760
+ },
761
+ adUnitCode: 'video-div',
762
+ bidId: '30b31c1838de1a',
763
+ bidderRequestId: '22edbae2733bf6',
764
+ placementId: '293857832abfef',
765
+ auctionId: '1d1a030790a475',
766
+ };
767
+
768
+ bidRequests.push(bid2);
769
+
770
+ const request = spec.buildRequests(bidRequests, {}, true);
771
+ const payload = JSON.parse(request.data);
772
+
773
+ expect(payload.biddata).to.exist;
774
+ expect(payload.biddata.length).to.equal(2);
775
+ expect(payload.biddata[0]).to.exist;
776
+ expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode);
777
+ expect(payload.biddata[0].id).to.equal(bidRequest.placementId);
778
+ expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder);
779
+ expect(payload.biddata[0].mediaTypes).to.exist;
780
+ expect(Object.keys(payload.biddata[0].mediaTypes).length).to.equal(3);
781
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.exist;
782
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({
783
+ sizes: DEFAULT_BID_SIZES,
784
+ });
785
+ expect(payload.biddata[0].mediaTypes[VIDEO]).to.exist;
786
+ expect(payload.biddata[0].mediaTypes[VIDEO]).to.deep.equal({
787
+ context: OUTSTREAM,
788
+ sizes: DEFAULT_BID_SIZES,
789
+ });
790
+ expect(payload.biddata[0].code).to.equal(bidRequest.adUnitCode);
791
+ expect(payload.biddata[0].id).to.equal(bidRequest.placementId);
792
+ expect(payload.biddata[0].bidder).to.equal(bidRequest.bidder);
793
+ expect(payload.biddata[0].mediaTypes[NATIVE]).to.exist;
794
+ expect(payload.biddata[0].mediaTypes[NATIVE]).to.deep.equal(bidRequest.mediaTypes.native);
795
+ expect(payload.biddata[1]).to.exist;
796
+ expect(payload.biddata[1].code).to.equal(bid2.adUnitCode);
797
+ expect(payload.biddata[1].id).to.equal(bid2.placementId);
798
+ expect(payload.biddata[1].bidder).to.equal(bid2.bidder);
799
+ expect(payload.biddata[1].mediaTypes).to.exist;
800
+ expect(Object.keys(payload.biddata[1].mediaTypes).length).to.equal(1);
801
+ expect(payload.biddata[1].mediaTypes[VIDEO]).to.exist;
802
+ expect(payload.biddata[1].mediaTypes[VIDEO]).to.deep.equal({
803
+ context: OUTSTREAM,
804
+ sizes: DEFAULT_BID_SIZES,
805
+ });
806
+ });
807
+ });
808
+
809
+ describe('interpretResponse', function () {
810
+ it('returns a valid Prebid API response object for a banner Prebid Server response', function () {
811
+ const prebidServerResponse = {
812
+ body: [{
813
+ mediaType: 'banner',
814
+ requestId: '12345',
815
+ cpm: 1,
816
+ currency: 'USD',
817
+ width: 640,
818
+ height: 240,
819
+ ad: BANNER_AD,
820
+ ttl: 300,
821
+ creativeId: '86f4aef9-2f17-421d-84db-5c9814bf4a79',
822
+ netRevenue: false,
823
+ meta: Object.freeze({
824
+ advertiser: '105600',
825
+ width: 300,
826
+ height: 250,
827
+ isCustom: '1',
828
+ progressBar: false,
829
+ mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg',
830
+ clickURL: '{{click}}'
831
+ })
832
+ }]
833
+ };
834
+
835
+ const interpretedResponse = spec.interpretResponse(prebidServerResponse, {});
836
+
837
+ expect(interpretedResponse).to.be.a('array');
838
+ expect(interpretedResponse.length).to.equal(1);
839
+
840
+ const interpretedBid = interpretedResponse[0];
841
+
842
+ expect(interpretedBid.mediaType).to.equal('banner');
843
+ expect(interpretedBid.requestId).to.equal('12345');
844
+ expect(interpretedBid.cpm).to.equal(1);
845
+ expect(interpretedBid.currency).to.equal('USD');
846
+ expect(interpretedBid.width).to.equal(640);
847
+ expect(interpretedBid.height).to.equal(240);
848
+ expect(interpretedBid.ad).to.equal(BANNER_AD);
849
+ expect(interpretedBid.ttl).to.equal(300);
850
+ expect(interpretedBid.creativeId).to.equal('86f4aef9-2f17-421d-84db-5c9814bf4a79');
851
+ expect(interpretedBid.netRevenue).to.be.false;
852
+ expect(interpretedBid.meta).to.deep.equal(prebidServerResponse.body[0].meta);
853
+ expect(interpretedBid.renderer).to.be.undefined;
854
+ expect(interpretedBid.adResponse).to.deep.equal(prebidServerResponse);
855
+ });
856
+
857
+ it('returns a valid Prebid API response object for a video Prebid Server response', function () {
858
+ const prebidServerResponse = Object.freeze({
859
+ body: [{
860
+ mediaType: 'video',
861
+ requestId: '67890',
862
+ cpm: 2,
863
+ currency: 'USD',
864
+ width: 600,
865
+ height: 300,
866
+ ad: VIDEO_AD,
867
+ ttl: 300,
868
+ creativeId: '248e8e0c-2f17-421d-84db-5c9814bf4a79',
869
+ netRevenue: false,
870
+ meta: {
871
+ advertiser: '105600',
872
+ width: 300,
873
+ height: 250,
874
+ isCustom: '1',
875
+ progressBar: false,
876
+ mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg',
877
+ clickURL: '{{click}}'
878
+ },
879
+ vastUrl: 'https://www.example.com/myVastVideo'
880
+ }]
881
+ });
882
+
883
+ const interpretedResponse = spec.interpretResponse(prebidServerResponse, {});
884
+
885
+ expect(interpretedResponse).to.be.a('array');
886
+ expect(interpretedResponse.length).to.equal(1);
887
+
888
+ const interpretedBid = interpretedResponse[0];
889
+
890
+ expect(interpretedBid.mediaType).to.equal('video');
891
+ expect(interpretedBid.requestId).to.equal('67890');
892
+ expect(interpretedBid.cpm).to.equal(2);
893
+ expect(interpretedBid.currency).to.equal('USD');
894
+ expect(interpretedBid.width).to.equal(600);
895
+ expect(interpretedBid.height).to.equal(300);
896
+ expect(interpretedBid.ad).to.equal(VIDEO_AD);
897
+ expect(interpretedBid.ttl).to.equal(300);
898
+ expect(interpretedBid.creativeId).to.equal('248e8e0c-2f17-421d-84db-5c9814bf4a79');
899
+ expect(interpretedBid.netRevenue).to.be.false;
900
+ expect(interpretedBid.meta).to.deep.equal(prebidServerResponse.body[0].meta);
901
+ expect(interpretedBid.renderer).to.be.undefined;
902
+ expect(interpretedBid.adResponse).to.deep.equal(prebidServerResponse);
903
+ });
904
+
905
+ it('returns a valid Prebid API response object for a native Prebid Server response', function () {
906
+ const prebidServerResponse = Object.freeze({
907
+ body: [{
908
+ mediaType: 'native',
909
+ requestId: '13579',
910
+ cpm: 3,
911
+ currency: 'USD',
912
+ width: 240,
913
+ height: 300,
914
+ ad: 'https://www.example.com/native-display.html',
915
+ ttl: 300,
916
+ creativeId: 'd28e8e0c-2f17-421d-84db-5c9814bf4a81',
917
+ netRevenue: false,
918
+ meta: {},
919
+ title: 'Test native ad bid for 13579',
920
+ sponsoredBy: 'Vibrant Media Ltd',
921
+ clickUrl: 'https://www.example.com/native-ct.html',
922
+ image: {
923
+ url: 'https://www.example.com/native-display.html',
924
+ width: 240,
925
+ height: 300
926
+ }
927
+ }]
928
+ });
929
+
930
+ const interpretedResponse = spec.interpretResponse(prebidServerResponse, {});
931
+
932
+ expect(interpretedResponse).to.be.a('array');
933
+ expect(interpretedResponse.length).to.equal(1);
934
+
935
+ const interpretedBid = interpretedResponse[0];
936
+
937
+ expect(interpretedBid.mediaType).to.equal('native');
938
+ expect(interpretedBid.requestId).to.equal('13579');
939
+ expect(interpretedBid.cpm).to.equal(3);
940
+ expect(interpretedBid.currency).to.equal('USD');
941
+ expect(interpretedBid.width).to.equal(240);
942
+ expect(interpretedBid.height).to.equal(300);
943
+ expect(interpretedBid.ad).to.equal('https://www.example.com/native-display.html');
944
+ expect(interpretedBid.ttl).to.equal(300);
945
+ expect(interpretedBid.creativeId).to.equal('d28e8e0c-2f17-421d-84db-5c9814bf4a81');
946
+ expect(interpretedBid.netRevenue).to.be.false;
947
+ expect(interpretedBid.meta).to.deep.equal(prebidServerResponse.body[0].meta);
948
+ expect(interpretedBid.renderer).to.be.undefined;
949
+ expect(interpretedBid.adResponse).to.deep.equal(prebidServerResponse);
950
+ });
951
+
952
+ it('returns a valid Prebid API response object for a multi-bid Prebid Server response', function () {
953
+ const prebidServerResponse = Object.freeze({
954
+ body: [
955
+ {
956
+ mediaType: 'banner',
957
+ requestId: '12345',
958
+ cpm: 3,
959
+ currency: 'USD',
960
+ width: 640,
961
+ height: 240,
962
+ ad: BANNER_AD,
963
+ ttl: 300,
964
+ creativeId: '86f4aef9-2f17-421d-84db-5c9814bf4a79',
965
+ netRevenue: false,
966
+ meta: {
967
+ advertiser: '105600',
968
+ width: 300,
969
+ height: 250,
970
+ isCustom: '1',
971
+ progressBar: false,
972
+ mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg',
973
+ clickURL: '{{click}}'
974
+ }
975
+ },
976
+ {
977
+ mediaType: 'video',
978
+ requestId: '67890',
979
+ cpm: 4,
980
+ currency: 'USD',
981
+ width: 300,
982
+ height: 300,
983
+ ad: VIDEO_AD,
984
+ ttl: 300,
985
+ creativeId: 'd28e8e0c-2f17-421d-84db-5c9814bf4a79',
986
+ netRevenue: false,
987
+ meta: {
988
+ advertiser: '105600',
989
+ width: 300,
990
+ height: 250,
991
+ isCustom: '1',
992
+ progressBar: false,
993
+ mpuSrc: '//images.intellitxt.com/a/105600/Genpact/genpact.jpg',
994
+ clickURL: '{{click}}'
995
+ },
996
+ vastUrl: 'https://www.example.com/myVastVideo'
997
+ },
998
+ {
999
+ mediaType: 'native',
1000
+ requestId: '13579',
1001
+ cpm: 5,
1002
+ currency: 'USD',
1003
+ width: 640,
1004
+ height: 240,
1005
+ ad: 'https://www.example.com/native-display.html',
1006
+ ttl: 300,
1007
+ creativeId: '888e8e0c-2f17-421d-84db-5c9814bf4a81',
1008
+ netRevenue: false,
1009
+ meta: {},
1010
+ title: 'Test native ad bid for 13579',
1011
+ sponsoredBy: 'Vibrant Media Ltd',
1012
+ clickUrl: 'https://www.example.com/native-ct.html',
1013
+ image: {
1014
+ url: 'https://www.example.com/native-display.html',
1015
+ width: 640,
1016
+ height: 240
1017
+ }
1018
+ }
1019
+ ]
1020
+ });
1021
+
1022
+ const interpretedResponse = spec.interpretResponse(prebidServerResponse, {});
1023
+
1024
+ expect(interpretedResponse).to.be.a('array');
1025
+ expect(interpretedResponse.length).to.equal(3);
1026
+
1027
+ const interpretedBannerBid = interpretedResponse[0];
1028
+
1029
+ expect(interpretedBannerBid.mediaType).to.equal('banner');
1030
+ expect(interpretedBannerBid.requestId).to.equal('12345');
1031
+ expect(interpretedBannerBid.cpm).to.equal(3);
1032
+ expect(interpretedBannerBid.currency).to.equal('USD');
1033
+ expect(interpretedBannerBid.width).to.equal(640);
1034
+ expect(interpretedBannerBid.height).to.equal(240);
1035
+ expect(interpretedBannerBid.ad).to.equal(BANNER_AD);
1036
+ expect(interpretedBannerBid.ttl).to.equal(300);
1037
+ expect(interpretedBannerBid.creativeId).to.equal('86f4aef9-2f17-421d-84db-5c9814bf4a79');
1038
+ expect(interpretedBannerBid.netRevenue).to.be.false;
1039
+ expect(interpretedBannerBid.meta).to.deep.equal(prebidServerResponse.body[0].meta);
1040
+ expect(interpretedBannerBid.renderer).to.be.undefined;
1041
+ expect(interpretedBannerBid.adResponse).to.deep.equal(prebidServerResponse);
1042
+
1043
+ const interpretedVideoBid = interpretedResponse[1];
1044
+
1045
+ expect(interpretedVideoBid.mediaType).to.equal('video');
1046
+ expect(interpretedVideoBid.requestId).to.equal('67890');
1047
+ expect(interpretedVideoBid.cpm).to.equal(4);
1048
+ expect(interpretedVideoBid.currency).to.equal('USD');
1049
+ expect(interpretedVideoBid.width).to.equal(300);
1050
+ expect(interpretedVideoBid.height).to.equal(300);
1051
+ expect(interpretedVideoBid.ad).to.equal(VIDEO_AD);
1052
+ expect(interpretedVideoBid.ttl).to.equal(300);
1053
+ expect(interpretedVideoBid.creativeId).to.equal('d28e8e0c-2f17-421d-84db-5c9814bf4a79');
1054
+ expect(interpretedVideoBid.netRevenue).to.be.false;
1055
+ expect(interpretedVideoBid.meta).to.deep.equal(prebidServerResponse.body[1].meta);
1056
+ expect(interpretedVideoBid.renderer).to.be.undefined;
1057
+ expect(interpretedVideoBid.adResponse).to.deep.equal(prebidServerResponse);
1058
+
1059
+ const interpretedNativeBid = interpretedResponse[2];
1060
+
1061
+ expect(interpretedNativeBid.mediaType).to.equal('native');
1062
+ expect(interpretedNativeBid.requestId).to.equal('13579');
1063
+ expect(interpretedNativeBid.cpm).to.equal(5);
1064
+ expect(interpretedNativeBid.currency).to.equal('USD');
1065
+ expect(interpretedNativeBid.width).to.equal(640);
1066
+ expect(interpretedNativeBid.height).to.equal(240);
1067
+ expect(interpretedNativeBid.ad).to.equal('https://www.example.com/native-display.html');
1068
+ expect(interpretedNativeBid.ttl).to.equal(300);
1069
+ expect(interpretedNativeBid.creativeId).to.equal('888e8e0c-2f17-421d-84db-5c9814bf4a81');
1070
+ expect(interpretedNativeBid.netRevenue).to.be.false;
1071
+ expect(interpretedNativeBid.meta).to.deep.equal(prebidServerResponse.body[2].meta);
1072
+ expect(interpretedNativeBid.renderer).to.be.undefined;
1073
+ expect(interpretedNativeBid.adResponse).to.deep.equal(prebidServerResponse);
1074
+ });
1075
+ });
1076
+
1077
+ describe('Flow tests', function () {
1078
+ describe('For successive API calls to the public functions', function () {
1079
+ it('should succeed with one media type per bid', function () {
1080
+ const transformedBannerBidParams = spec.transformBidParams(VALID_BANNER_BID_PARAMS);
1081
+ const transformedVideoBidParams = spec.transformBidParams(VALID_VIDEO_BID_PARAMS);
1082
+ const transformedNativeBidParams = spec.transformBidParams(VALID_NATIVE_BID_PARAMS);
1083
+
1084
+ const bannerBid = {
1085
+ bidder: 'vibrantmedia',
1086
+ params: transformedBannerBidParams,
1087
+ mediaTypes: {
1088
+ banner: {
1089
+ sizes: DEFAULT_BID_SIZES,
1090
+ },
1091
+ },
1092
+ adUnitCode: 'banner-div',
1093
+ bidId: '30b31c1838de11',
1094
+ bidderRequestId: '22edbae2733bf6',
1095
+ placementId: '293857832abfef',
1096
+ auctionId: '1d1a030790a475',
1097
+ };
1098
+ const videoBid = {
1099
+ bidder: 'vibrantmedia',
1100
+ params: transformedVideoBidParams,
1101
+ mediaTypes: {
1102
+ video: {
1103
+ context: OUTSTREAM,
1104
+ sizes: DEFAULT_BID_SIZES,
1105
+ },
1106
+ },
1107
+ adUnitCode: 'video-div',
1108
+ bidId: '30b31c1838de15',
1109
+ bidderRequestId: '22edbae2733bf6',
1110
+ placementId: '293857832abfef',
1111
+ auctionId: '1d1a030790a475',
1112
+ };
1113
+ const nativeBid = {
1114
+ bidder: 'vibrantmedia',
1115
+ params: transformedNativeBidParams,
1116
+ mediaTypes: {
1117
+ native: {
1118
+ image: {
1119
+ required: true,
1120
+ sizes: [300, 250]
1121
+ },
1122
+ title: {
1123
+ required: true
1124
+ },
1125
+ sponsoredBy: {
1126
+ required: true
1127
+ },
1128
+ clickUrl: {
1129
+ required: true
1130
+ }
1131
+ }
1132
+ },
1133
+ adUnitCode: 'native-div',
1134
+ bidId: '30b31c1838de12',
1135
+ bidderRequestId: '22edbae2733bf6',
1136
+ placementId: '293857832abfef',
1137
+ auctionId: '1d1a030790a475',
1138
+ };
1139
+
1140
+ expect(spec.isBidRequestValid(bannerBid)).to.be.true;
1141
+ expect(spec.isBidRequestValid(videoBid)).to.be.true;
1142
+ expect(spec.isBidRequestValid(nativeBid)).to.be.true;
1143
+
1144
+ const bidRequests = [bannerBid, videoBid, nativeBid];
1145
+ const validBidderRequest = getValidBidderRequest(bidRequests);
1146
+ const serverRequest = spec.buildRequests(bidRequests, validBidderRequest);
1147
+ expect(serverRequest.method).to.equal('POST');
1148
+ expect(serverRequest.url).to.equal(EXPECTED_PREBID_SERVER_URL);
1149
+
1150
+ const payload = JSON.parse(serverRequest.data);
1151
+ expect(payload.biddata).to.exist;
1152
+ expect(payload.biddata.length).to.equal(3);
1153
+ expect(payload.biddata[0]).to.exist;
1154
+ expect(payload.biddata[0].code).to.equal(bannerBid.adUnitCode);
1155
+ expect(payload.biddata[0].id).to.equal(bannerBid.placementId);
1156
+ expect(payload.biddata[0].bidder).to.equal(bannerBid.bidder);
1157
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.exist;
1158
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({
1159
+ sizes: DEFAULT_BID_SIZES,
1160
+ });
1161
+ expect(payload.biddata[1]).to.exist;
1162
+ expect(payload.biddata[1].code).to.equal(videoBid.adUnitCode);
1163
+ expect(payload.biddata[1].id).to.equal(videoBid.placementId);
1164
+ expect(payload.biddata[1].bidder).to.equal(videoBid.bidder);
1165
+ expect(payload.biddata[1].mediaTypes[VIDEO]).to.exist;
1166
+ expect(payload.biddata[1].mediaTypes[VIDEO]).to.deep.equal({
1167
+ context: OUTSTREAM,
1168
+ sizes: DEFAULT_BID_SIZES
1169
+ });
1170
+ expect(payload.biddata[2]).to.exist;
1171
+ expect(payload.biddata[2].code).to.equal(nativeBid.adUnitCode);
1172
+ expect(payload.biddata[2].id).to.equal(nativeBid.placementId);
1173
+ expect(payload.biddata[2].bidder).to.equal(nativeBid.bidder);
1174
+ expect(payload.biddata[2].mediaTypes[NATIVE]).to.exist;
1175
+ expect(payload.biddata[2].mediaTypes[NATIVE]).to.deep.equal(nativeBid.mediaTypes.native);
1176
+
1177
+ // From here, the API would call the Prebid Server and call interpretResponse, which is covered by tests elsewhere
1178
+ });
1179
+
1180
+ it('should succeed with multiple media types for a single bid', function () {
1181
+ const bidParams = spec.transformBidParams(VALID_VIDEO_BID_PARAMS);
1182
+ const bid = {
1183
+ bidder: 'vibrantmedia',
1184
+ params: bidParams,
1185
+ mediaTypes: {
1186
+ banner: {
1187
+ sizes: DEFAULT_BID_SIZES
1188
+ },
1189
+ video: {
1190
+ context: OUTSTREAM,
1191
+ sizes: DEFAULT_BID_SIZES
1192
+ },
1193
+ native: {
1194
+ sizes: DEFAULT_BID_SIZES
1195
+ }
1196
+ },
1197
+ adUnitCode: 'test-div',
1198
+ bidId: '30b31c1838de13',
1199
+ bidderRequestId: '22edbae2733bf6',
1200
+ placementId: '293857832abfef',
1201
+ auctionId: '1d1a030790a475',
1202
+ };
1203
+
1204
+ expect(spec.isBidRequestValid(bid)).to.be.true;
1205
+
1206
+ const bidRequests = [bid];
1207
+ const validBidderRequest = getValidBidderRequest(bidRequests);
1208
+ const serverRequest = spec.buildRequests(bidRequests, validBidderRequest);
1209
+ expect(serverRequest.method).to.equal('POST');
1210
+ expect(serverRequest.url).to.equal(EXPECTED_PREBID_SERVER_URL);
1211
+
1212
+ const payload = JSON.parse(serverRequest.data);
1213
+ expect(payload.biddata).to.exist;
1214
+ expect(payload.biddata.length).to.equal(1);
1215
+ expect(payload.biddata[0]).to.exist;
1216
+ expect(payload.biddata[0].code).to.equal(bid.adUnitCode);
1217
+ expect(payload.biddata[0].id).to.equal(bid.placementId);
1218
+ expect(payload.biddata[0].bidder).to.equal(bid.bidder);
1219
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.exist;
1220
+ expect(payload.biddata[0].mediaTypes[BANNER]).to.deep.equal({
1221
+ sizes: DEFAULT_BID_SIZES,
1222
+ });
1223
+ expect(payload.biddata[0].mediaTypes[VIDEO]).to.exist;
1224
+ expect(payload.biddata[0].mediaTypes[VIDEO]).to.deep.equal({
1225
+ context: OUTSTREAM,
1226
+ sizes: DEFAULT_BID_SIZES,
1227
+ });
1228
+ expect(payload.biddata[0].mediaTypes[NATIVE]).to.exist;
1229
+ expect(payload.biddata[0].mediaTypes[NATIVE]).to.deep.equal({
1230
+ sizes: DEFAULT_BID_SIZES,
1231
+ });
1232
+
1233
+ // From here, the API would call the Prebid Server and call interpretResponse, which is covered by tests elsewhere
1234
+ });
1235
+ });
1236
+ });
1237
+ });