prebid.js 6.2.0 → 6.6.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 (169) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/gulpfile.js +87 -82
  3. package/integrationExamples/gpt/weboramaRtdProvider_example.html +23 -14
  4. package/karma.conf.maker.js +1 -1
  5. package/modules/.submodules.json +2 -1
  6. package/modules/33acrossBidAdapter.js +189 -102
  7. package/modules/adagioBidAdapter.js +1 -1
  8. package/modules/addefendBidAdapter.js +1 -0
  9. package/modules/adkernelBidAdapter.js +148 -62
  10. package/modules/adlooxAdServerVideo.js +2 -2
  11. package/modules/adlooxAnalyticsAdapter.js +4 -4
  12. package/modules/admanBidAdapter.js +11 -4
  13. package/modules/admixerBidAdapter.js +1 -1
  14. package/modules/adnuntiusBidAdapter.js +3 -1
  15. package/modules/adomikAnalyticsAdapter.js +27 -9
  16. package/modules/adqueryIdSystem.js +103 -0
  17. package/modules/adqueryIdSystem.md +35 -0
  18. package/modules/adxcgBidAdapter.js +311 -359
  19. package/modules/adxcgBidAdapter.md +22 -21
  20. package/modules/adyoulikeBidAdapter.js +13 -9
  21. package/modules/aniviewBidAdapter.js +1 -1
  22. package/modules/appnexusBidAdapter.js +0 -1
  23. package/modules/beopBidAdapter.js +6 -4
  24. package/modules/bidViewability.js +3 -3
  25. package/modules/bidViewabilityIO.js +3 -3
  26. package/modules/bliinkBidAdapter.js +3 -2
  27. package/modules/colossussspBidAdapter.js +7 -0
  28. package/modules/compassBidAdapter.js +208 -0
  29. package/modules/compassBidAdapter.md +79 -0
  30. package/modules/consentManagement.js +7 -1
  31. package/modules/criteoBidAdapter.js +1 -1
  32. package/modules/criteoIdSystem.js +29 -7
  33. package/modules/currency.js +2 -2
  34. package/modules/cwireBidAdapter.js +3 -0
  35. package/modules/dailyhuntBidAdapter.js +435 -0
  36. package/modules/dailyhuntBidAdapter.md +4 -0
  37. package/modules/docereeBidAdapter.js +10 -1
  38. package/modules/docereeBidAdapter.md +2 -0
  39. package/modules/dspxBidAdapter.js +1 -1
  40. package/modules/engageyaBidAdapter.js +1 -1
  41. package/modules/feedadBidAdapter.js +2 -2
  42. package/modules/feedadBidAdapter.md +4 -2
  43. package/modules/futureads.md +48 -0
  44. package/modules/glimpseBidAdapter.js +82 -47
  45. package/modules/gptPreAuction.js +55 -7
  46. package/modules/gridBidAdapter.js +4 -3
  47. package/modules/gumgumBidAdapter.js +2 -2
  48. package/modules/idImportLibrary.js +45 -8
  49. package/modules/idImportLibrary.md +4 -0
  50. package/modules/improvedigitalBidAdapter.js +42 -4
  51. package/modules/instreamTracking.js +4 -4
  52. package/modules/invibesBidAdapter.js +49 -5
  53. package/modules/invibesBidAdapter.md +2 -1
  54. package/modules/ixBidAdapter.js +53 -18
  55. package/modules/kinessoIdSystem.js +1 -1
  56. package/modules/limelightDigitalBidAdapter.js +2 -1
  57. package/modules/livewrappedAnalyticsAdapter.js +3 -1
  58. package/modules/livewrappedBidAdapter.js +8 -2
  59. package/modules/loglyliftBidAdapter.js +79 -0
  60. package/modules/loglyliftBidAdapter.md +55 -0
  61. package/modules/lotamePanoramaIdSystem.js +80 -8
  62. package/modules/mediasquareBidAdapter.js +1 -9
  63. package/modules/nextMillenniumBidAdapter.js +39 -7
  64. package/modules/oguryBidAdapter.js +9 -2
  65. package/modules/onetagBidAdapter.js +4 -2
  66. package/modules/optimeraRtdProvider.js +8 -1
  67. package/modules/ozoneBidAdapter.js +21 -64
  68. package/modules/prebidServerBidAdapter/index.js +16 -12
  69. package/modules/proxistoreBidAdapter.js +0 -2
  70. package/modules/pubgeniusBidAdapter.js +1 -1
  71. package/modules/pubmaticAnalyticsAdapter.js +16 -0
  72. package/modules/pubxaiAnalyticsAdapter.js +17 -0
  73. package/modules/richaudienceBidAdapter.js +4 -4
  74. package/modules/riseBidAdapter.js +1 -1
  75. package/modules/rtbhouseBidAdapter.js +14 -4
  76. package/modules/rtdModule/index.js +49 -18
  77. package/modules/rubiconBidAdapter.js +31 -19
  78. package/modules/sharedIdSystem.js +27 -1
  79. package/modules/showheroes-bsBidAdapter.js +13 -2
  80. package/modules/tappxBidAdapter.js +8 -5
  81. package/modules/targetVideoBidAdapter.js +187 -0
  82. package/modules/targetVideoBidAdapter.md +34 -0
  83. package/modules/teadsBidAdapter.js +1 -2
  84. package/modules/telariaBidAdapter.js +2 -2
  85. package/modules/trustxBidAdapter.js +8 -16
  86. package/modules/userId/eids.js +7 -1
  87. package/modules/userId/userId.md +8 -0
  88. package/modules/vidoomyBidAdapter.js +16 -10
  89. package/modules/weboramaRtdProvider.js +288 -73
  90. package/modules/weboramaRtdProvider.md +27 -10
  91. package/modules/welectBidAdapter.js +106 -0
  92. package/modules/yahoosspBidAdapter.js +5 -1
  93. package/modules/yieldmoBidAdapter.js +23 -5
  94. package/modules/zetaSspBidAdapter.md +33 -1
  95. package/modules/zeta_global_sspAnalyticsAdapter.js +97 -0
  96. package/modules/zeta_global_sspAnalyticsAdapter.md +24 -0
  97. package/modules/zeta_global_sspBidAdapter.js +22 -1
  98. package/package.json +1 -1
  99. package/plugins/pbjsGlobals.js +28 -1
  100. package/src/auction.js +2 -2
  101. package/src/config.js +27 -3
  102. package/src/hook.js +5 -1
  103. package/src/prebid.js +21 -6
  104. package/src/targeting.js +22 -1
  105. package/src/utils.js +46 -8
  106. package/test/helpers/prebidGlobal.js +1 -0
  107. package/test/spec/config_spec.js +279 -0
  108. package/test/spec/modules/33acrossBidAdapter_spec.js +300 -78
  109. package/test/spec/modules/adlooxAnalyticsAdapter_spec.js +6 -6
  110. package/test/spec/modules/admanBidAdapter_spec.js +2 -2
  111. package/test/spec/modules/adnuntiusBidAdapter_spec.js +17 -0
  112. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +9 -1
  113. package/test/spec/modules/adqueryIdSystem_spec.js +74 -0
  114. package/test/spec/modules/adxcgBidAdapter_spec.js +820 -571
  115. package/test/spec/modules/adyoulikeBidAdapter_spec.js +49 -0
  116. package/test/spec/modules/beopBidAdapter_spec.js +1 -1
  117. package/test/spec/modules/bidViewabilityIO_spec.js +2 -2
  118. package/test/spec/modules/bidViewability_spec.js +4 -4
  119. package/test/spec/modules/bliinkBidAdapter_spec.js +2 -0
  120. package/test/spec/modules/colossussspBidAdapter_spec.js +9 -0
  121. package/test/spec/modules/compassBidAdapter_spec.js +398 -0
  122. package/test/spec/modules/consentManagement_spec.js +20 -0
  123. package/test/spec/modules/criteoIdSystem_spec.js +6 -3
  124. package/test/spec/modules/cwireBidAdapter_spec.js +10 -8
  125. package/test/spec/modules/dailyhuntBidAdapter_spec.js +404 -0
  126. package/test/spec/modules/docereeBidAdapter_spec.js +9 -1
  127. package/test/spec/modules/eids_spec.js +15 -0
  128. package/test/spec/modules/feedadBidAdapter_spec.js +15 -0
  129. package/test/spec/modules/glimpseBidAdapter_spec.js +0 -18
  130. package/test/spec/modules/gptPreAuction_spec.js +177 -2
  131. package/test/spec/modules/idImportLibrary_spec.js +197 -10
  132. package/test/spec/modules/improvedigitalBidAdapter_spec.js +45 -1
  133. package/test/spec/modules/invibesBidAdapter_spec.js +119 -0
  134. package/test/spec/modules/ixBidAdapter_spec.js +112 -62
  135. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +75 -17
  136. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +22 -0
  137. package/test/spec/modules/livewrappedBidAdapter_spec.js +31 -0
  138. package/test/spec/modules/loglyliftBidAdapter_spec.js +172 -0
  139. package/test/spec/modules/lotamePanoramaIdSystem_spec.js +227 -0
  140. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -4
  141. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +26 -1
  142. package/test/spec/modules/oguryBidAdapter_spec.js +10 -2
  143. package/test/spec/modules/optimeraRtdProvider_spec.js +14 -1
  144. package/test/spec/modules/ozoneBidAdapter_spec.js +43 -31
  145. package/test/spec/modules/prebidServerBidAdapter_spec.js +43 -0
  146. package/test/spec/modules/pubgeniusBidAdapter_spec.js +3 -3
  147. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +13 -1
  148. package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +11 -0
  149. package/test/spec/modules/realTimeDataModule_spec.js +147 -48
  150. package/test/spec/modules/richaudienceBidAdapter_spec.js +42 -2
  151. package/test/spec/modules/riseBidAdapter_spec.js +1 -1
  152. package/test/spec/modules/rtbhouseBidAdapter_spec.js +20 -0
  153. package/test/spec/modules/rubiconBidAdapter_spec.js +65 -9
  154. package/test/spec/modules/sharedIdSystem_spec.js +52 -6
  155. package/test/spec/modules/showheroes-bsBidAdapter_spec.js +2 -0
  156. package/test/spec/modules/tappxBidAdapter_spec.js +0 -19
  157. package/test/spec/modules/targetVideoBidAdapter_spec.js +96 -0
  158. package/test/spec/modules/teadsBidAdapter_spec.js +14 -59
  159. package/test/spec/modules/userId_spec.js +68 -19
  160. package/test/spec/modules/weboramaRtdProvider_spec.js +408 -214
  161. package/test/spec/modules/welectBidAdapter_spec.js +211 -0
  162. package/test/spec/modules/yahoosspBidAdapter_spec.js +28 -1
  163. package/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js +427 -0
  164. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +33 -1
  165. package/test/spec/unit/core/targeting_spec.js +72 -0
  166. package/test/spec/unit/pbjs_api_spec.js +3 -1
  167. package/test/spec/utils_spec.js +38 -0
  168. package/test/test_deps.js +3 -0
  169. package/test/test_index.js +1 -3
@@ -1,653 +1,902 @@
1
- import {expect} from 'chai';
1
+ // jshint esversion: 6, es3: false, node: true
2
+ import {assert} from 'chai';
2
3
  import {spec} from 'modules/adxcgBidAdapter.js';
3
- import {deepClone, parseUrl} from 'src/utils.js';
4
- import * as utils from '../../../src/utils.js';
5
-
6
- describe('AdxcgAdapter', function () {
7
- let bidBanner = {
8
- bidder: 'adxcg',
9
- params: {
10
- adzoneid: '1'
11
- },
12
- adUnitCode: 'adunit-code',
13
- mediaTypes: {
14
- banner: {
15
- sizes: [
16
- [300, 250],
17
- [640, 360],
18
- [1, 1]
19
- ]
20
- }
21
- },
22
- bidId: '84ab500420319d',
23
- bidderRequestId: '7101db09af0db2',
24
- auctionId: '1d1a030790a475'
25
- };
26
-
27
- let bidVideo = {
28
- bidder: 'adxcg',
29
- params: {
30
- adzoneid: '20',
31
- video: {
32
- api: [2],
33
- maxduration: 30
34
- }
35
- },
36
- mediaTypes: {
37
- video: {
38
- context: 'instream',
39
- playerSize: [[640, 480]],
40
- protocols: [1, 2],
41
- mimes: ['video/mp4'],
42
- }
43
- },
44
- adUnitCode: 'adunit-code',
45
- bidId: '84ab500420319d',
46
- bidderRequestId: '7101db09af0db2',
47
- auctionId: '1d1a030790a475'
48
- };
49
-
50
- let bidNative = {
51
- bidder: 'adxcg',
52
- params: {
53
- adzoneid: '2379'
54
- },
55
- mediaTypes: {
56
- native: {
57
- image: {
58
- sendId: false,
59
- required: true,
60
- sizes: [80, 80]
61
- },
62
- title: {
63
- required: true,
64
- len: 75
65
- },
66
- body: {
67
- required: true,
68
- len: 200
69
- },
70
- sponsoredBy: {
71
- required: false,
72
- len: 20
73
- }
74
- }
75
- },
76
- adUnitCode: 'adunit-code',
77
- bidId: '84ab500420319d',
78
- bidderRequestId: '7101db09af0db2',
79
- auctionId: '1d1a030790a475'
80
- };
4
+ import {config} from 'src/config.js';
5
+ import {createEidsArray} from 'modules/userId/eids.js';
6
+ const utils = require('src/utils');
81
7
 
82
- describe('isBidRequestValid', function () {
83
- it('should return true when required params found bidNative', function () {
84
- expect(spec.isBidRequestValid(bidNative)).to.equal(true);
85
- });
8
+ describe('Adxcg adapter', function () {
9
+ let bids = [];
86
10
 
87
- it('should return true when required params found bidVideo', function () {
88
- expect(spec.isBidRequestValid(bidVideo)).to.equal(true);
89
- });
11
+ describe('isBidRequestValid', function () {
12
+ let bid = {
13
+ 'bidder': 'adxcg',
14
+ 'params': {
15
+ 'adzoneid': '19910113'
16
+ }
17
+ };
90
18
 
91
- it('should return true when required params found bidBanner', function () {
92
- expect(spec.isBidRequestValid(bidBanner)).to.equal(true);
93
- });
19
+ it('should return true when required params found', function () {
20
+ assert(spec.isBidRequestValid(bid));
94
21
 
95
- it('should return false when required params not found', function () {
96
- expect(spec.isBidRequestValid({})).to.be.false;
22
+ bid.params = {
23
+ adzoneid: 4332,
24
+ };
25
+ assert(spec.isBidRequestValid(bid));
97
26
  });
98
27
 
99
- it('should return false when required params are not passed', function () {
100
- let bid = Object.assign({}, bidBanner);
101
- delete bid.params;
28
+ it('should return false when required params are missing', function () {
102
29
  bid.params = {};
103
- expect(spec.isBidRequestValid(bid)).to.equal(false);
104
- });
30
+ assert.isFalse(spec.isBidRequestValid(bid));
105
31
 
106
- it('should return true when required video params not found', function () {
107
- const simpleVideo = JSON.parse(JSON.stringify(bidVideo));
108
- simpleVideo.params.adzoneid = 123;
109
- expect(spec.isBidRequestValid(simpleVideo)).to.be.false;
32
+ bid.params = {
33
+ mname: 'some-placement'
34
+ };
35
+ assert.isFalse(spec.isBidRequestValid(bid));
36
+
37
+ bid.params = {
38
+ inv: 1234
39
+ };
40
+ assert.isFalse(spec.isBidRequestValid(bid));
110
41
  });
111
42
  });
112
43
 
113
- describe('request function http', function () {
114
- it('creates a valid adxcg request url bidBanner', function () {
115
- let request = spec.buildRequests([bidBanner]);
116
- expect(request).to.exist;
117
- expect(request.method).to.equal('GET');
118
- let parsedRequestUrl = parseUrl(request.url);
119
- expect(parsedRequestUrl.hostname).to.equal('hbps.adxcg.net');
120
- expect(parsedRequestUrl.pathname).to.equal('/get/adi');
121
-
122
- let query = parsedRequestUrl.search;
123
- expect(query.renderformat).to.equal('javascript');
124
- expect(query.ver).to.equal('r20210330PB40');
125
- expect(query.source).to.equal('pbjs10');
126
- expect(query.pbjs).to.equal('$prebid.version$');
127
- expect(query.adzoneid).to.equal('1');
128
- expect(query.format).to.equal('300x250|640x360|1x1');
129
- expect(query.jsonp).to.be.undefined;
130
- expect(query.prebidBidIds).to.equal('84ab500420319d');
131
- expect(query.bidfloors).to.equal('0');
132
-
133
- expect(query).to.have.property('secure');
134
- expect(query).to.have.property('uw');
135
- expect(query).to.have.property('uh');
136
- expect(query).to.have.property('dpr');
137
- expect(query).to.have.property('bt');
138
- expect(query).to.have.property('cookies');
139
- expect(query).to.have.property('tz');
140
- expect(query).to.have.property('dt');
141
- expect(query).to.have.property('iob');
142
- expect(query).to.have.property('rndid');
143
- expect(query).to.have.property('ref');
144
- expect(query).to.have.property('url');
44
+ describe('buildRequests', function () {
45
+ beforeEach(function () {
46
+ config.resetConfig();
145
47
  });
48
+ it('should send request with correct structure', function () {
49
+ let validBidRequests = [{
50
+ bidId: 'bidId',
51
+ params: {
52
+ adzoneid: '19910113'
53
+ }
54
+ }];
55
+ let request = spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}});
146
56
 
147
- it('creates a valid adxcg request url bidVideo', function () {
148
- let request = spec.buildRequests([bidVideo]);
149
- expect(request).to.exist;
150
- expect(request.method).to.equal('GET');
151
- let parsedRequestUrl = parseUrl(request.url);
152
- expect(parsedRequestUrl.hostname).to.equal('hbps.adxcg.net');
153
- expect(parsedRequestUrl.pathname).to.equal('/get/adi');
154
-
155
- let query = parsedRequestUrl.search;
156
- // general part
157
- expect(query.renderformat).to.equal('javascript');
158
- expect(query.ver).to.equal('r20210330PB40');
159
- expect(query.source).to.equal('pbjs10');
160
- expect(query.pbjs).to.equal('$prebid.version$');
161
- expect(query.adzoneid).to.equal('20');
162
- expect(query.format).to.equal('640x480');
163
- expect(query.jsonp).to.be.undefined;
164
- expect(query.prebidBidIds).to.equal('84ab500420319d');
165
- expect(query.bidfloors).to.equal('0');
166
-
167
- expect(query).to.have.property('secure');
168
- expect(query).to.have.property('uw');
169
- expect(query).to.have.property('uh');
170
- expect(query).to.have.property('dpr');
171
- expect(query).to.have.property('bt');
172
- expect(query).to.have.property('cookies');
173
- expect(query).to.have.property('tz');
174
- expect(query).to.have.property('dt');
175
- expect(query).to.have.property('iob');
176
- expect(query).to.have.property('rndid');
177
- expect(query).to.have.property('ref');
178
- expect(query).to.have.property('url');
179
-
180
- // video specific part
181
- expect(query['video.maxduration.0']).to.equal('30');
182
- expect(query['video.mimes.0']).to.equal('video/mp4');
183
- expect(query['video.context.0']).to.equal('instream');
57
+ assert.equal(request.method, 'POST');
58
+ assert.equal(request.url, 'https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1');
59
+ assert.deepEqual(request.options, {contentType: 'application/json'});
60
+ assert.ok(request.data);
184
61
  });
185
62
 
186
- it('creates a valid adxcg request url bidNative', function () {
187
- let request = spec.buildRequests([bidNative]);
188
- expect(request).to.exist;
189
- expect(request.method).to.equal('GET');
190
- let parsedRequestUrl = parseUrl(request.url);
191
- expect(parsedRequestUrl.hostname).to.equal('hbps.adxcg.net');
192
- expect(parsedRequestUrl.pathname).to.equal('/get/adi');
193
-
194
- let query = parsedRequestUrl.search;
195
- expect(query.renderformat).to.equal('javascript');
196
- expect(query.ver).to.equal('r20210330PB40');
197
- expect(query.source).to.equal('pbjs10');
198
- expect(query.pbjs).to.equal('$prebid.version$');
199
- expect(query.adzoneid).to.equal('2379');
200
- expect(query.format).to.equal('0x0');
201
- expect(query.jsonp).to.be.undefined;
202
- expect(query.prebidBidIds).to.equal('84ab500420319d');
203
- expect(query.bidfloors).to.equal('0');
204
-
205
- expect(query).to.have.property('secure');
206
- expect(query).to.have.property('uw');
207
- expect(query).to.have.property('uh');
208
- expect(query).to.have.property('dpr');
209
- expect(query).to.have.property('bt');
210
- expect(query).to.have.property('cookies');
211
- expect(query).to.have.property('tz');
212
- expect(query).to.have.property('dt');
213
- expect(query).to.have.property('iob');
214
- expect(query).to.have.property('rndid');
215
- expect(query).to.have.property('ref');
216
- expect(query).to.have.property('url');
217
- });
218
- });
63
+ describe('user privacy', function () {
64
+ it('should send GDPR Consent data to exchange if gdprApplies', function () {
65
+ let validBidRequests = [{bidId: 'bidId', params: {test: 1}}];
66
+ let bidderRequest = {
67
+ gdprConsent: {gdprApplies: true, consentString: 'consentDataString'},
68
+ refererInfo: {referer: 'page'}
69
+ };
70
+ let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
71
+
72
+ assert.equal(request.user.ext.consent, bidderRequest.gdprConsent.consentString);
73
+ assert.equal(request.regs.ext.gdpr, bidderRequest.gdprConsent.gdprApplies);
74
+ assert.equal(typeof request.regs.ext.gdpr, 'number');
75
+ });
219
76
 
220
- describe('gdpr compliance', function () {
221
- it('should send GDPR Consent data if gdprApplies', function () {
222
- let request = spec.buildRequests([bidBanner], {
223
- gdprConsent: {
224
- gdprApplies: true,
225
- consentString: 'consentDataString'
226
- }
77
+ it('should send gdpr as number', function () {
78
+ let validBidRequests = [{bidId: 'bidId', params: {test: 1}}];
79
+ let bidderRequest = {
80
+ gdprConsent: {gdprApplies: true, consentString: 'consentDataString'},
81
+ refererInfo: {referer: 'page'}
82
+ };
83
+ let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
84
+
85
+ assert.equal(typeof request.regs.ext.gdpr, 'number');
86
+ assert.equal(request.regs.ext.gdpr, 1);
227
87
  });
228
- let parsedRequestUrl = parseUrl(request.url);
229
- let query = parsedRequestUrl.search;
230
88
 
231
- expect(query.gdpr).to.equal('1');
232
- expect(query.gdpr_consent).to.equal('consentDataString');
233
- });
89
+ it('should send CCPA Consent data to exchange', function () {
90
+ let validBidRequests = [{bidId: 'bidId', params: {test: 1}}];
91
+ let bidderRequest = {uspConsent: '1YA-', refererInfo: {referer: 'page'}};
92
+ let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
234
93
 
235
- it('should not send GDPR Consent data if gdprApplies is false or undefined', function () {
236
- let request = spec.buildRequests([bidBanner], {
237
- gdprConsent: {
238
- gdprApplies: false,
239
- consentString: 'consentDataString'
240
- }
94
+ assert.equal(request.regs.ext.us_privacy, '1YA-');
95
+
96
+ bidderRequest = {
97
+ uspConsent: '1YA-',
98
+ gdprConsent: {gdprApplies: true, consentString: 'consentDataString'},
99
+ refererInfo: {referer: 'page'}
100
+ };
101
+ request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
102
+
103
+ assert.equal(request.regs.ext.us_privacy, '1YA-');
104
+ assert.equal(request.user.ext.consent, 'consentDataString');
105
+ assert.equal(request.regs.ext.gdpr, 1);
241
106
  });
242
- let parsedRequestUrl = parseUrl(request.url);
243
- let query = parsedRequestUrl.search;
244
107
 
245
- expect(query.gdpr).to.be.undefined;
246
- expect(query.gdpr_consent).to.be.undefined;
108
+ it('should not send GDPR Consent data to adxcg if gdprApplies is undefined', function () {
109
+ let validBidRequests = [{
110
+ bidId: 'bidId',
111
+ params: {siteId: 'siteId'}
112
+ }];
113
+ let bidderRequest = {
114
+ gdprConsent: {gdprApplies: false, consentString: 'consentDataString'},
115
+ refererInfo: {referer: 'page'}
116
+ };
117
+ let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
118
+
119
+ assert.equal(request.user.ext.consent, 'consentDataString');
120
+ assert.equal(request.regs.ext.gdpr, 0);
121
+
122
+ bidderRequest = {gdprConsent: {consentString: 'consentDataString'}, refererInfo: {referer: 'page'}};
123
+ request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
124
+
125
+ assert.equal(request.user, undefined);
126
+ assert.equal(request.regs, undefined);
127
+ });
128
+ it('should send default GDPR Consent data to exchange', function () {
129
+ let validBidRequests = [{
130
+ bidId: 'bidId',
131
+ params: {siteId: 'siteId'}
132
+ }];
133
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
134
+
135
+ assert.equal(request.user, undefined);
136
+ assert.equal(request.regs, undefined);
137
+ });
247
138
  });
248
- });
249
139
 
250
- describe('userid pubcid should be passed to querystring', function () {
251
- let bidderRequests = {};
252
- let bid = deepClone([bidBanner]);
253
- bid[0].userId = {pubcid: 'pubcidabcd'};
140
+ it('should add test and is_debug to request, if test is set in parameters', function () {
141
+ let validBidRequests = [{
142
+ bidId: 'bidId',
143
+ params: {test: 1}
144
+ }];
145
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
254
146
 
255
- it('should send pubcid if available', function () {
256
- let request = spec.buildRequests(bid, bidderRequests);
257
- let parsedRequestUrl = parseUrl(request.url);
258
- let query = parsedRequestUrl.search;
259
- expect(query.pubcid).to.equal('pubcidabcd');
147
+ assert.ok(request.is_debug);
148
+ assert.equal(request.test, 1);
260
149
  });
261
- });
262
150
 
263
- describe('userid tdid should be passed to querystring', function () {
264
- let bid = deepClone([bidBanner]);
265
- let bidderRequests = {};
151
+ it('should have default request structure', function () {
152
+ let keys = 'site,geo,device,source,ext,imp'.split(',');
153
+ let validBidRequests = [{
154
+ bidId: 'bidId',
155
+ params: {siteId: 'siteId'}
156
+ }];
157
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
158
+ let data = Object.keys(request);
159
+
160
+ assert.deepEqual(keys, data);
161
+ });
266
162
 
267
- bid[0].userId = {tdid: 'tdidabcd'};
163
+ it('should set request keys correct values', function () {
164
+ let validBidRequests = [{
165
+ bidId: 'bidId',
166
+ params: {siteId: 'siteId'},
167
+ transactionId: 'transactionId'
168
+ }];
169
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
268
170
 
269
- it('should send pubcid if available', function () {
270
- let request = spec.buildRequests(bid, bidderRequests);
271
- let parsedRequestUrl = parseUrl(request.url);
272
- let query = parsedRequestUrl.search;
273
- expect(query.tdid).to.equal('tdidabcd');
171
+ assert.equal(request.source.tid, validBidRequests[0].transactionId);
172
+ assert.equal(request.source.fd, 1);
173
+ });
174
+
175
+ it('should send info about device', function () {
176
+ config.setConfig({
177
+ device: {w: 100, h: 100}
178
+ });
179
+ let validBidRequests = [{
180
+ bidId: 'bidId',
181
+ params: {adzoneid: '1000'}
182
+ }];
183
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
184
+
185
+ assert.equal(request.device.ua, navigator.userAgent);
186
+ assert.equal(request.device.w, 100);
187
+ assert.equal(request.device.h, 100);
274
188
  });
275
- });
276
189
 
277
- describe('userid id5id should be passed to querystring', function () {
278
- let bid = deepClone([bidBanner]);
279
- let bidderRequests = {};
190
+ it('should send app info', function () {
191
+ config.setConfig({
192
+ app: {id: 'appid'},
193
+ ortb2: {app: {name: 'appname'}}
194
+ });
195
+ let validBidRequests = [{
196
+ bidId: 'bidId',
197
+ params: {adzoneid: '1000'}
198
+ }];
199
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
200
+
201
+ assert.equal(request.app.id, 'appid');
202
+ assert.equal(request.app.name, 'appname');
203
+ assert.equal(request.site, undefined);
204
+ });
280
205
 
281
- bid[0].userId = {id5id: {uid: 'id5idsample'}};
206
+ it('should send info about the site', function () {
207
+ config.setConfig({
208
+ site: {
209
+ id: '123123',
210
+ publisher: {
211
+ domain: 'publisher.domain.com'
212
+ }
213
+ },
214
+ ortb2: {
215
+ site: {
216
+ publisher: {
217
+ id: 4441,
218
+ name: 'publisher\'s name'
219
+ }
220
+ }
221
+ }
222
+ });
223
+ let validBidRequests = [{
224
+ bidId: 'bidId',
225
+ params: {adzoneid: '1000'}
226
+ }];
227
+ let refererInfo = {referer: 'page'};
228
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo}).data);
229
+
230
+ assert.deepEqual(request.site, {
231
+ domain: 'localhost',
232
+ id: '123123',
233
+ page: refererInfo.referer,
234
+ publisher: {
235
+ domain: 'publisher.domain.com',
236
+ id: 4441,
237
+ name: 'publisher\'s name'
238
+ }
239
+ });
240
+ });
282
241
 
283
- it('should send pubcid if available', function () {
284
- let request = spec.buildRequests(bid, bidderRequests);
285
- let parsedRequestUrl = parseUrl(request.url);
286
- let query = parsedRequestUrl.search;
287
- expect(query.id5id).to.equal('id5idsample');
242
+ it('should pass extended ids', function () {
243
+ let validBidRequests = [{
244
+ bidId: 'bidId',
245
+ params: {},
246
+ userIdAsEids: createEidsArray({
247
+ tdid: 'TTD_ID_FROM_USER_ID_MODULE',
248
+ pubcid: 'pubCommonId_FROM_USER_ID_MODULE'
249
+ })
250
+ }];
251
+
252
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
253
+ assert.deepEqual(request.user.ext.eids, [
254
+ {source: 'adserver.org', uids: [{id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: {rtiPartner: 'TDID'}}]},
255
+ {source: 'pubcid.org', uids: [{id: 'pubCommonId_FROM_USER_ID_MODULE', atype: 1}]}
256
+ ]);
288
257
  });
289
- });
290
258
 
291
- describe('userid idl_env should be passed to querystring', function () {
292
- let bid = deepClone([bidBanner]);
293
- let bidderRequests = {};
259
+ it('should send currency if defined', function () {
260
+ config.setConfig({currency: {adServerCurrency: 'EUR'}});
261
+ let validBidRequests = [{params: {}}];
262
+ let refererInfo = {referer: 'page'};
263
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo}).data);
264
+
265
+ assert.deepEqual(request.cur, ['EUR']);
266
+ });
294
267
 
295
- bid[0].userId = {idl_env: 'idl_envsample'};
268
+ it('should pass supply chain object', function () {
269
+ let validBidRequests = [{
270
+ bidId: 'bidId',
271
+ params: {},
272
+ schain: {
273
+ validation: 'strict',
274
+ config: {
275
+ ver: '1.0'
276
+ }
277
+ }
278
+ }];
296
279
 
297
- it('should send pubcid if available', function () {
298
- let request = spec.buildRequests(bid, bidderRequests);
299
- let parsedRequestUrl = parseUrl(request.url);
300
- let query = parsedRequestUrl.search;
301
- expect(query.idl_env).to.equal('idl_envsample');
280
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
281
+ assert.deepEqual(request.source.ext.schain, {
282
+ validation: 'strict',
283
+ config: {
284
+ ver: '1.0'
285
+ }
286
+ });
302
287
  });
303
- });
304
288
 
305
- describe('response handler', function () {
306
- let BIDDER_REQUEST = {
307
- bidder: 'adxcg',
308
- params: {
309
- adzoneid: '1'
310
- },
311
- adUnitCode: 'adunit-code',
312
- mediaTypes: {
313
- banner: {
314
- sizes: [
315
- [300, 250],
316
- [640, 360],
317
- [1, 1]
318
- ]
289
+ describe('bids', function () {
290
+ it('should add more than one bid to the request', function () {
291
+ let validBidRequests = [{
292
+ bidId: 'bidId',
293
+ params: {siteId: 'siteId'}
294
+ }, {
295
+ bidId: 'bidId2',
296
+ params: {siteId: 'siteId'}
297
+ }];
298
+ let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
299
+
300
+ assert.equal(request.imp.length, 2);
301
+ });
302
+ it('should add incrementing values of id', function () {
303
+ let validBidRequests = [{
304
+ bidId: 'bidId',
305
+ params: {adzoneid: '1000'},
306
+ mediaTypes: {video: {}}
307
+ }, {
308
+ bidId: 'bidId2',
309
+ params: {adzoneid: '1000'},
310
+ mediaTypes: {video: {}}
311
+ }, {
312
+ bidId: 'bidId3',
313
+ params: {adzoneid: '1000'},
314
+ mediaTypes: {video: {}}
315
+ }];
316
+ let imps = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
317
+
318
+ for (let i = 0; i < 3; i++) {
319
+ assert.equal(imps[i].id, i + 1);
319
320
  }
320
- },
321
- bidId: '84ab500420319d',
322
- bidderRequestId: '7101db09af0db2',
323
- auctionId: '1d1a030790a475'
324
- };
321
+ });
325
322
 
326
- let BANNER_RESPONSE = {
327
- body: {
328
- id: 'auctionid',
329
- bidid: '84ab500420319d',
330
- seatbid: [{
331
- bid: [
332
- {
333
- impid: '84ab500420319d',
334
- price: 0.45,
335
- crid: '42',
336
- adm: '<!-- adContent -->',
337
- w: 300,
338
- h: 250,
339
- adomain: ['adomain.com'],
340
- cat: ['IAB1-4', 'IAB8-16', 'IAB25-5'],
341
- ext: {
342
- crType: 'banner',
343
- advertiser_id: '777',
344
- advertiser_name: 'advertiser',
345
- agency_name: 'agency'
346
- }
323
+ it('should add adzoneid', function () {
324
+ let validBidRequests = [{bidId: 'bidId', params: {adzoneid: 1000}, mediaTypes: {video: {}}},
325
+ {bidId: 'bidId2', params: {adzoneid: 1001}, mediaTypes: {video: {}}},
326
+ {bidId: 'bidId3', params: {adzoneid: 1002}, mediaTypes: {video: {}}}];
327
+ let imps = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
328
+ for (let i = 0; i < 3; i++) {
329
+ assert.equal(imps[i].tagid, validBidRequests[i].params.adzoneid);
330
+ }
331
+ });
332
+
333
+ describe('price floors', function () {
334
+ it('should not add if floors module not configured', function () {
335
+ const validBidRequests = [{bidId: 'bidId', params: {adzoneid: 1000}, mediaTypes: {video: {}}}];
336
+ let imp = getRequestImps(validBidRequests)[0];
337
+
338
+ assert.equal(imp.bidfloor, undefined);
339
+ assert.equal(imp.bidfloorcur, undefined);
340
+ });
341
+
342
+ it('should not add if floor price not defined', function () {
343
+ const validBidRequests = [getBidWithFloor()];
344
+ let imp = getRequestImps(validBidRequests)[0];
345
+
346
+ assert.equal(imp.bidfloor, undefined);
347
+ assert.equal(imp.bidfloorcur, 'USD');
348
+ });
349
+
350
+ it('should request floor price in adserver currency', function () {
351
+ config.setConfig({currency: {adServerCurrency: 'DKK'}});
352
+ const validBidRequests = [getBidWithFloor()];
353
+ let imp = getRequestImps(validBidRequests)[0];
354
+
355
+ assert.equal(imp.bidfloor, undefined);
356
+ assert.equal(imp.bidfloorcur, 'DKK');
357
+ });
358
+
359
+ it('should add correct floor values', function () {
360
+ const expectedFloors = [1, 1.3, 0.5];
361
+ const validBidRequests = expectedFloors.map(getBidWithFloor);
362
+ let imps = getRequestImps(validBidRequests);
363
+
364
+ expectedFloors.forEach((floor, index) => {
365
+ assert.equal(imps[index].bidfloor, floor);
366
+ assert.equal(imps[index].bidfloorcur, 'USD');
367
+ });
368
+ });
369
+
370
+ function getBidWithFloor(floor) {
371
+ return {
372
+ params: {adzoneid: 1},
373
+ mediaTypes: {video: {}},
374
+ getFloor: ({currency}) => {
375
+ return {
376
+ currency: currency,
377
+ floor
378
+ };
347
379
  }
348
- ]
349
- }],
350
- cur: 'USD'
351
- },
352
- headers: {someheader: 'fakedata'}
353
- };
380
+ };
381
+ }
382
+ });
354
383
 
355
- let BANNER_RESPONSE_WITHDEALID = {
356
- body: {
357
- id: 'auctionid',
358
- bidid: '84ab500420319d',
359
- seatbid: [{
360
- bid: [
361
- {
362
- impid: '84ab500420319d',
363
- price: 0.45,
364
- crid: '42',
365
- dealid: '7722',
366
- adm: '<!-- adContent -->',
367
- w: 300,
368
- h: 250,
369
- adomain: ['adomain.com'],
370
- ext: {
371
- crType: 'banner'
372
- }
384
+ describe('multiple media types', function () {
385
+ it('should use all configured media types for bidding', function () {
386
+ let validBidRequests = [{
387
+ bidId: 'bidId',
388
+ params: {adzoneid: 1000},
389
+ mediaTypes: {
390
+ banner: {
391
+ sizes: [[100, 100], [200, 300]]
392
+ },
393
+ video: {}
373
394
  }
374
- ]
375
- }],
376
- cur: 'USD'
377
- }
378
- };
395
+ }, {
396
+ bidId: 'bidId1',
397
+ params: {adzoneid: 1000},
398
+ mediaTypes: {
399
+ video: {},
400
+ native: {}
401
+ }
402
+ }, {
403
+ bidId: 'bidId2',
404
+ params: {adzoneid: 1000},
405
+ nativeParams: {
406
+ title: {required: true, len: 140}
407
+ },
408
+ mediaTypes: {
409
+ banner: {
410
+ sizes: [[100, 100], [200, 300]]
411
+ },
412
+ native: {},
413
+ video: {}
414
+ }
415
+ }];
416
+ let [first, second, third] = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
379
417
 
380
- let VIDEO_RESPONSE = {
381
- body: {
382
- id: 'auctionid',
383
- bidid: '84ab500420319d',
384
- seatbid: [{
385
- bid: [
386
- {
387
- impid: '84ab500420319d',
388
- price: 0.45,
389
- crid: '42',
390
- nurl: 'vastContentUrl',
391
- adomain: ['adomain.com'],
392
- w: 640,
393
- h: 360,
394
- ext: {
395
- crType: 'video'
418
+ assert.ok(first.banner);
419
+ assert.ok(first.video);
420
+ assert.equal(first.native, undefined);
421
+
422
+ assert.ok(second.video);
423
+ assert.equal(second.banner, undefined);
424
+ assert.equal(second.native, undefined);
425
+
426
+ assert.ok(third.native);
427
+ assert.ok(third.video);
428
+ assert.ok(third.banner);
429
+ });
430
+ });
431
+
432
+ describe('banner', function () {
433
+ it('should convert sizes to openrtb format', function () {
434
+ let validBidRequests = [{
435
+ bidId: 'bidId',
436
+ params: {adzoneid: 1000},
437
+ mediaTypes: {
438
+ banner: {
439
+ sizes: [[100, 100], [200, 300]]
396
440
  }
397
441
  }
398
- ]
399
- }],
400
- cur: 'USD'
401
- },
402
- headers: {someheader: 'fakedata'}
403
- };
404
-
405
- let NATIVE_RESPONSEob = {
406
- assets: [
407
- {
408
- id: 1,
409
- required: 0,
410
- title: {
411
- text: 'titleContent'
412
- }
413
- },
414
- {
415
- id: 2,
416
- required: 0,
417
- img: {
418
- url: 'imageContent',
419
- w: 600,
420
- h: 600
421
- }
422
- },
423
- {
424
- id: 3,
425
- required: 0,
426
- data: {
427
- label: 'DESC',
428
- value: 'descriptionContent'
429
- }
430
- },
431
- {
432
- id: 0,
433
- required: 0,
434
- data: {
435
- label: 'SPONSORED',
436
- value: 'sponsoredByContent'
437
- }
438
- },
439
- {
440
- id: 5,
441
- required: 0,
442
- icon: {
443
- url: 'iconContent',
444
- w: 400,
445
- h: 400
446
- }
447
- }
448
- ],
449
- link: {
450
- url: 'linkContent'
451
- },
452
- imptrackers: ['impressionTracker1', 'impressionTracker2']
453
- }
442
+ }];
443
+ let {banner} = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0];
444
+ assert.deepEqual(banner, {
445
+ format: [{w: 100, h: 100}, {w: 200, h: 300}]
446
+ });
447
+ });
448
+ });
454
449
 
455
- let NATIVE_RESPONSE = {
456
- body: {
457
- id: 'auctionid',
458
- bidid: '84ab500420319d',
459
- seatbid: [{
460
- bid: [
461
- {
462
- impid: '84ab500420319d',
463
- price: 0.45,
464
- crid: '42',
465
- w: 0,
466
- h: 0,
467
- adm: JSON.stringify(NATIVE_RESPONSEob),
468
- adomain: ['adomain.com'],
469
- ext: {
470
- crType: 'native'
450
+ describe('video', function () {
451
+ it('should pass video mediatype config', function () {
452
+ let validBidRequests = [{
453
+ bidId: 'bidId',
454
+ params: {adzoneid: 1000},
455
+ mediaTypes: {
456
+ video: {
457
+ playerSize: [640, 480],
458
+ context: 'outstream',
459
+ mimes: ['video/mp4']
471
460
  }
472
461
  }
473
- ]
474
- }],
475
- cur: 'USD'
476
- },
477
- headers: {someheader: 'fakedata'}
478
- };
462
+ }];
463
+ let {video} = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0];
464
+ assert.deepEqual(video, {
465
+ playerSize: [640, 480],
466
+ context: 'outstream',
467
+ mimes: ['video/mp4']
468
+ });
469
+ });
470
+ });
479
471
 
480
- it('handles regular responses', function () {
481
- expect(BANNER_RESPONSE).to.exist;
482
- expect(BANNER_RESPONSE.body).to.exist;
483
- expect(BANNER_RESPONSE.body.id).to.exist;
484
- expect(BANNER_RESPONSE.body.seatbid[0]).to.exist;
485
- let result = spec.interpretResponse(BANNER_RESPONSE, BIDDER_REQUEST);
486
-
487
- expect(result).to.have.lengthOf(1);
488
-
489
- expect(result[0]).to.exist;
490
- expect(result[0].width).to.equal(300);
491
- expect(result[0].height).to.equal(250);
492
- expect(result[0].creativeId).to.equal(42);
493
- expect(result[0].cpm).to.be.within(0.45, 0.46);
494
- expect(result[0].ad).to.equal('<!-- adContent -->');
495
- expect(result[0].currency).to.equal('USD');
496
- expect(result[0].netRevenue).to.equal(true);
497
- expect(result[0].ttl).to.equal(300);
498
- expect(result[0].dealId).to.not.exist;
499
- expect(result[0].meta.advertiserDomains[0]).to.equal('adomain.com');
500
- expect(result[0].meta.advertiserId).to.be.eql('777');
501
- expect(result[0].meta.advertiserName).to.be.eql('advertiser');
502
- expect(result[0].meta.agencyName).to.be.eql('agency');
503
- expect(result[0].meta.advertiserDomains).to.be.eql(['adomain.com']);
504
- expect(result[0].meta.secondaryCatIds).to.be.eql(['IAB1-4', 'IAB8-16', 'IAB25-5']);
472
+ describe('native', function () {
473
+ describe('assets', function () {
474
+ it('should set correct asset id', function () {
475
+ let validBidRequests = [{
476
+ bidId: 'bidId',
477
+ params: {adzoneid: 1000},
478
+ nativeParams: {
479
+ title: {required: true, len: 140},
480
+ image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
481
+ body: {len: 140}
482
+ }
483
+ }];
484
+ let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
485
+ let assets = JSON.parse(nativeRequest).assets;
486
+
487
+ assert.equal(assets[0].id, 0);
488
+ assert.equal(assets[1].id, 3);
489
+ assert.equal(assets[2].id, 4);
490
+ });
491
+ it('should add required key if it is necessary', function () {
492
+ let validBidRequests = [{
493
+ bidId: 'bidId',
494
+ params: {adzoneid: 1000},
495
+ nativeParams: {
496
+ title: {required: true, len: 140},
497
+ image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
498
+ body: {len: 140},
499
+ sponsoredBy: {required: true, len: 140}
500
+ }
501
+ }];
502
+
503
+ let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
504
+ let assets = JSON.parse(nativeRequest).assets;
505
+
506
+ assert.equal(assets[0].required, 1);
507
+ assert.ok(!assets[1].required);
508
+ assert.ok(!assets[2].required);
509
+ assert.equal(assets[3].required, 1);
510
+ });
511
+
512
+ it('should map img and data assets', function () {
513
+ let validBidRequests = [{
514
+ bidId: 'bidId',
515
+ params: {adzoneid: 1000},
516
+ nativeParams: {
517
+ title: {required: true, len: 140},
518
+ image: {required: true, sizes: [150, 50]},
519
+ icon: {required: false, sizes: [50, 50]},
520
+ body: {required: false, len: 140},
521
+ sponsoredBy: {required: true},
522
+ cta: {required: false},
523
+ clickUrl: {required: false}
524
+ }
525
+ }];
526
+
527
+ let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
528
+ let assets = JSON.parse(nativeRequest).assets;
529
+ assert.ok(assets[0].title);
530
+ assert.equal(assets[0].title.len, 140);
531
+ assert.deepEqual(assets[1].img, {type: 3, w: 150, h: 50});
532
+ assert.deepEqual(assets[2].img, {type: 1, w: 50, h: 50});
533
+ assert.deepEqual(assets[3].data, {type: 2, len: 140});
534
+ assert.deepEqual(assets[4].data, {type: 1});
535
+ assert.deepEqual(assets[5].data, {type: 12});
536
+ assert.ok(!assets[6]);
537
+ });
538
+
539
+ describe('icon/image sizing', function () {
540
+ it('should flatten sizes and utilise first pair', function () {
541
+ const validBidRequests = [{
542
+ bidId: 'bidId',
543
+ params: {adzoneid: 1000},
544
+ nativeParams: {
545
+ image: {
546
+ sizes: [[200, 300], [100, 200]]
547
+ },
548
+ }
549
+ }];
550
+
551
+ let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
552
+ let assets = JSON.parse(nativeRequest).assets;
553
+ assert.ok(assets[0].img);
554
+ assert.equal(assets[0].img.w, 200);
555
+ assert.equal(assets[0].img.h, 300);
556
+ });
557
+ });
558
+
559
+ it('should utilise aspect_ratios', function () {
560
+ const validBidRequests = [{
561
+ bidId: 'bidId',
562
+ params: {adzoneid: 1000},
563
+ nativeParams: {
564
+ image: {
565
+ aspect_ratios: [{
566
+ min_width: 100,
567
+ ratio_height: 3,
568
+ ratio_width: 1
569
+ }]
570
+ },
571
+ icon: {
572
+ aspect_ratios: [{
573
+ min_width: 10,
574
+ ratio_height: 5,
575
+ ratio_width: 2
576
+ }]
577
+ }
578
+ }
579
+ }];
580
+
581
+ let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
582
+ let assets = JSON.parse(nativeRequest).assets;
583
+ assert.ok(assets[0].img);
584
+ assert.equal(assets[0].img.wmin, 100);
585
+ assert.equal(assets[0].img.hmin, 300);
586
+
587
+ assert.ok(assets[1].img);
588
+ assert.equal(assets[1].img.wmin, 10);
589
+ assert.equal(assets[1].img.hmin, 25);
590
+ });
591
+
592
+ it('should not throw error if aspect_ratios config is not defined', function () {
593
+ const validBidRequests = [{
594
+ bidId: 'bidId',
595
+ params: {adzoneid: 1000},
596
+ nativeParams: {
597
+ image: {
598
+ aspect_ratios: []
599
+ },
600
+ icon: {
601
+ aspect_ratios: []
602
+ }
603
+ }
604
+ }];
605
+
606
+ assert.doesNotThrow(() => spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}));
607
+ });
608
+ });
609
+
610
+ it('should expect any dimensions if min_width not passed', function () {
611
+ const validBidRequests = [{
612
+ bidId: 'bidId',
613
+ params: {adzoneid: 1000},
614
+ nativeParams: {
615
+ image: {
616
+ aspect_ratios: [{
617
+ ratio_height: 3,
618
+ ratio_width: 1
619
+ }]
620
+ }
621
+ }
622
+ }];
623
+
624
+ let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
625
+ let assets = JSON.parse(nativeRequest).assets;
626
+ assert.ok(assets[0].img);
627
+ assert.equal(assets[0].img.wmin, 0);
628
+ assert.equal(assets[0].img.hmin, 0);
629
+ assert.ok(!assets[1]);
630
+ });
631
+ });
505
632
  });
506
633
 
507
- it('handles regular responses with dealid', function () {
508
- let result = spec.interpretResponse(BANNER_RESPONSE_WITHDEALID);
634
+ function getRequestImps(validBidRequests) {
635
+ return JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
636
+ }
637
+ });
509
638
 
510
- expect(result).to.have.lengthOf(1);
639
+ describe('interpretResponse', function () {
640
+ it('should return if no body in response', function () {
641
+ let serverResponse = {};
642
+ let bidRequest = {};
511
643
 
512
- expect(result[0].width).to.equal(300);
513
- expect(result[0].height).to.equal(250);
514
- expect(result[0].creativeId).to.equal(42);
515
- // expect(result[0].cpm).to.equal(0.45);
516
- expect(result[0].cpm).to.be.within(0.45, 0.46);
517
- expect(result[0].ad).to.equal('<!-- adContent -->');
518
- expect(result[0].currency).to.equal('USD');
519
- expect(result[0].netRevenue).to.equal(true);
520
- expect(result[0].ttl).to.equal(300);
644
+ assert.ok(!spec.interpretResponse(serverResponse, bidRequest));
521
645
  });
646
+ it('should return more than one bids', function () {
647
+ let serverResponse = {
648
+ body: {
649
+ seatbid: [{
650
+ bid: [{
651
+ impid: '1',
652
+ native: {ver: '1.1', link: {url: 'link'}, assets: [{id: 1, title: {text: 'Asset title text'}}]}
653
+ }]
654
+ }, {
655
+ bid: [{
656
+ impid: '2',
657
+ native: {ver: '1.1', link: {url: 'link'}, assets: [{id: 1, data: {value: 'Asset title text'}}]}
658
+ }]
659
+ }]
660
+ }
661
+ };
662
+ let bidRequest = {
663
+ data: {},
664
+ bids: [
665
+ {
666
+ bidId: 'bidId1',
667
+ params: {adzoneid: 1000},
668
+ nativeParams: {
669
+ title: {required: true, len: 140},
670
+ image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
671
+ body: {len: 140}
672
+ }
673
+ },
674
+ {
675
+ bidId: 'bidId2',
676
+ params: {adzoneid: 1000},
677
+ nativeParams: {
678
+ title: {required: true, len: 140},
679
+ image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
680
+ body: {len: 140}
681
+ }
682
+ }
683
+ ]
684
+ };
522
685
 
523
- it('handles video responses', function () {
524
- let result = spec.interpretResponse(VIDEO_RESPONSE);
525
- expect(result).to.have.lengthOf(1);
526
-
527
- expect(result[0].width).to.equal(640);
528
- expect(result[0].height).to.equal(360);
529
- expect(result[0].mediaType).to.equal('video');
530
- expect(result[0].creativeId).to.equal(42);
531
- expect(result[0].cpm).to.equal(0.45);
532
- expect(result[0].vastUrl).to.equal('vastContentUrl');
533
- expect(result[0].currency).to.equal('USD');
534
- expect(result[0].netRevenue).to.equal(true);
535
- expect(result[0].ttl).to.equal(300);
686
+ bids = spec.interpretResponse(serverResponse, bidRequest);
687
+ assert.equal(spec.interpretResponse(serverResponse, bidRequest).length, 2);
536
688
  });
537
689
 
538
- it('handles native responses', function () {
539
- let result = spec.interpretResponse(NATIVE_RESPONSE);
540
-
541
- expect(result[0].width).to.equal(0);
542
- expect(result[0].height).to.equal(0);
543
-
544
- expect(result[0].creativeId).to.equal(42);
545
- expect(result[0].cpm).to.equal(0.45);
546
- expect(result[0].currency).to.equal('USD');
547
- expect(result[0].netRevenue).to.equal(true);
548
- expect(result[0].ttl).to.equal(300);
690
+ it('should set correct values to bid', function () {
691
+ let nativeExample1 = {
692
+ assets: [],
693
+ link: {url: 'link'},
694
+ imptrackers: ['imptrackers url1', 'imptrackers url2']
695
+ }
549
696
 
550
- expect(result[0].mediaType).to.equal('native');
697
+ let serverResponse = {
698
+ body: {
699
+ id: null,
700
+ bidid: null,
701
+ seatbid: [{
702
+ bid: [
703
+ {
704
+ impid: '1',
705
+ price: 93.1231,
706
+ crid: '12312312',
707
+ adm: JSON.stringify(nativeExample1),
708
+ dealid: 'deal-id',
709
+ adomain: ['demo.com'],
710
+ ext: {
711
+ crType: 'native',
712
+ advertiser_id: 'adv1',
713
+ advertiser_name: 'advname',
714
+ agency_name: 'agname',
715
+ mediaType: 'native'
716
+ }
717
+ }
718
+ ]
719
+ }],
720
+ cur: 'EUR'
721
+ }
722
+ };
723
+ let bidRequest = {
724
+ data: {},
725
+ bids: [
726
+ {
727
+ bidId: 'bidId1',
728
+ params: {adzoneid: 1000},
729
+ nativeParams: {
730
+ title: {required: true, len: 140},
731
+ image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
732
+ body: {len: 140}
733
+ }
734
+ }
735
+ ]
736
+ };
551
737
 
552
- expect(result[0].native.clickUrl).to.equal('linkContent');
553
- expect(result[0].native.impressionTrackers).to.deep.equal([
554
- 'impressionTracker1',
555
- 'impressionTracker2'
556
- ]);
557
- expect(result[0].native.title).to.equal('titleContent');
738
+ const bids = spec.interpretResponse(serverResponse, bidRequest);
739
+ const bid = serverResponse.body.seatbid[0].bid[0];
740
+ assert.deepEqual(bids[0].requestId, bidRequest.bids[0].bidId);
741
+ assert.deepEqual(bids[0].cpm, bid.price);
742
+ assert.deepEqual(bids[0].creativeId, bid.crid);
743
+ assert.deepEqual(bids[0].ttl, 300);
744
+ assert.deepEqual(bids[0].netRevenue, false);
745
+ assert.deepEqual(bids[0].currency, serverResponse.body.cur);
746
+ assert.deepEqual(bids[0].mediaType, 'native');
747
+ assert.deepEqual(bids[0].meta.mediaType, 'native');
748
+ assert.deepEqual(bids[0].meta.advertiserDomains, ['demo.com']);
749
+
750
+ assert.deepEqual(bids[0].meta.advertiserName, 'advname');
751
+ assert.deepEqual(bids[0].meta.agencyName, 'agname');
752
+
753
+ assert.deepEqual(bids[0].dealId, 'deal-id');
754
+ });
558
755
 
559
- expect(result[0].native.image.url).to.equal('imageContent');
560
- expect(result[0].native.image.height).to.equal(600);
561
- expect(result[0].native.image.width).to.equal(600);
756
+ it('should return empty when there is no bids in response', function () {
757
+ const serverResponse = {
758
+ body: {
759
+ id: null,
760
+ bidid: null,
761
+ seatbid: [{bid: []}],
762
+ cur: 'EUR'
763
+ }
764
+ };
765
+ let bidRequest = {
766
+ data: {},
767
+ bids: [{bidId: 'bidId1'}]
768
+ };
769
+ const result = spec.interpretResponse(serverResponse, bidRequest)[0];
770
+ assert.ok(!result);
771
+ });
562
772
 
563
- expect(result[0].native.icon.url).to.equal('iconContent');
564
- expect(result[0].native.icon.height).to.equal(400);
565
- expect(result[0].native.icon.width).to.equal(400);
773
+ describe('banner', function () {
774
+ it('should set ad content on response', function () {
775
+ let serverResponse = {
776
+ body: {
777
+ seatbid: [{
778
+ bid: [{impid: '1', adm: '<banner>', ext: {crType: 'banner'}}]
779
+ }]
780
+ }
781
+ };
782
+ let bidRequest = {
783
+ data: {},
784
+ bids: [
785
+ {
786
+ bidId: 'bidId1',
787
+ params: {adzoneid: 1000}
788
+ }
789
+ ]
790
+ };
566
791
 
567
- expect(result[0].native.body).to.equal('descriptionContent');
568
- expect(result[0].native.sponsoredBy).to.equal('sponsoredByContent');
792
+ bids = spec.interpretResponse(serverResponse, bidRequest);
793
+ assert.equal(bids.length, 1);
794
+ assert.equal(bids[0].ad, '<banner>');
795
+ assert.equal(bids[0].mediaType, 'banner');
796
+ assert.equal(bids[0].meta.mediaType, 'banner');
797
+ });
569
798
  });
570
799
 
571
- it('handles nobid responses', function () {
572
- let response = [];
573
- let bidderRequest = BIDDER_REQUEST;
800
+ describe('video', function () {
801
+ it('should set vastXml on response', function () {
802
+ let serverResponse = {
803
+ body: {
804
+ seatbid: [{
805
+ bid: [{impid: '1', adm: '<vast>', ext: {crType: 'video'}}]
806
+ }]
807
+ }
808
+ };
809
+ let bidRequest = {
810
+ data: {},
811
+ bids: [
812
+ {
813
+ bidId: 'bidId1',
814
+ params: {adzoneid: 1000}
815
+ }
816
+ ]
817
+ };
574
818
 
575
- let result = spec.interpretResponse(response, bidderRequest);
576
- expect(result.length).to.equal(0);
819
+ bids = spec.interpretResponse(serverResponse, bidRequest);
820
+ assert.equal(bids.length, 1);
821
+ assert.equal(bids[0].vastXml, '<vast>');
822
+ assert.equal(bids[0].mediaType, 'video');
823
+ assert.equal(bids[0].meta.mediaType, 'video');
824
+ });
577
825
  });
578
826
  });
579
827
 
580
828
  describe('getUserSyncs', function () {
581
- let syncoptionsIframe = {
582
- iframeEnabled: 'true'
583
- };
829
+ const usersyncUrl = 'https://usersync-url.com';
830
+ beforeEach(() => {
831
+ config.setConfig(
832
+ {
833
+ adxcg: {
834
+ usersyncUrl: usersyncUrl,
835
+ }
836
+ }
837
+ )
838
+ })
839
+ after(() => {
840
+ config.resetConfig()
841
+ })
842
+
843
+ it('should return user sync if pixel enabled with adxcg config', function () {
844
+ const ret = spec.getUserSyncs({pixelEnabled: true})
845
+ expect(ret).to.deep.equal([{type: 'image', url: usersyncUrl}])
846
+ })
847
+
848
+ it('should not return user sync if pixel disabled', function () {
849
+ const ret = spec.getUserSyncs({pixelEnabled: false})
850
+ expect(ret).to.be.an('array').that.is.empty
851
+ })
852
+
853
+ it('should not return user sync if url is not set', function () {
854
+ config.resetConfig()
855
+ const ret = spec.getUserSyncs({pixelEnabled: true})
856
+ expect(ret).to.be.an('array').that.is.empty
857
+ })
858
+
859
+ it('should pass GDPR consent', function() {
860
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, undefined)).to.deep.equal([{
861
+ type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=foo`
862
+ }]);
863
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: false, consentString: 'foo'}, undefined)).to.deep.equal([{
864
+ type: 'image', url: `${usersyncUrl}?gdpr=0&gdpr_consent=foo`
865
+ }]);
866
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: undefined}, undefined)).to.deep.equal([{
867
+ type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=`
868
+ }]);
869
+ });
870
+
871
+ it('should pass US consent', function() {
872
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, undefined, '1NYN')).to.deep.equal([{
873
+ type: 'image', url: `${usersyncUrl}?us_privacy=1NYN`
874
+ }]);
875
+ });
584
876
 
585
- it('should return iframe sync option', function () {
586
- expect(spec.getUserSyncs(syncoptionsIframe)[0].type).to.equal('iframe');
587
- expect(spec.getUserSyncs(syncoptionsIframe)[0].url).to.equal(
588
- 'https://cdn.adxcg.net/pb-sync.html'
589
- );
877
+ it('should pass GDPR and US consent', function() {
878
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, '1NYN')).to.deep.equal([{
879
+ type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=foo&us_privacy=1NYN`
880
+ }]);
590
881
  });
591
882
  });
592
883
 
593
- describe('on bidWon', function () {
594
- beforeEach(function () {
884
+ describe('onBidWon', function() {
885
+ beforeEach(function() {
595
886
  sinon.stub(utils, 'triggerPixel');
596
887
  });
597
- afterEach(function () {
888
+ afterEach(function() {
598
889
  utils.triggerPixel.restore();
599
890
  });
600
- it('should replace burl for banner', function () {
601
- const burl = 'burl=${' + 'AUCTION_PRICE}';
891
+
892
+ it('Should trigger pixel if bid nurl', function() {
602
893
  const bid = {
603
- 'bidderCode': 'adxcg',
604
- 'width': 0,
605
- 'height': 0,
606
- 'statusMessage': 'Bid available',
607
- 'adId': '3d0b6ff1dda89',
608
- 'requestId': '2a423489e058a1',
609
- 'mediaType': 'banner',
610
- 'source': 'client',
611
- 'ad': burl,
612
- 'cpm': 0.66,
613
- 'creativeId': '353538_591471',
614
- 'currency': 'USD',
615
- 'dealId': '',
616
- 'netRevenue': true,
617
- 'ttl': 300,
618
- // 'nurl': nurl,
619
- 'burl': burl,
620
- 'isBurl': true,
621
- 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa',
622
- 'responseTimestamp': 1556867386065,
623
- 'requestTimestamp': 1556867385916,
624
- 'bidder': 'adxcg',
625
- 'adUnitCode': 'div-gpt-ad-1555415275793-0',
626
- 'timeToRespond': 149,
627
- 'pbLg': '0.50',
628
- 'pbMg': '0.60',
629
- 'pbHg': '0.66',
630
- 'pbAg': '0.65',
631
- 'pbDg': '0.66',
632
- 'pbCg': '',
633
- 'size': '0x0',
634
- 'adserverTargeting': {
635
- 'hb_bidder': 'mgid',
636
- 'hb_adid': '3d0b6ff1dda89',
637
- 'hb_pb': '0.66',
638
- 'hb_size': '0x0',
639
- 'hb_source': 'client',
640
- 'hb_format': 'banner',
641
- 'hb_banner_title': 'TITLE',
642
- 'hb_banner_image': 'hb_banner_image:3d0b6ff1dda89',
643
- 'hb_banner_icon': 'IconURL',
644
- 'hb_banner_linkurl': 'hb_banner_linkurl:3d0b6ff1dda89'
645
- },
646
- 'status': 'targetingSet',
647
- 'params': [{'adzoneid': '20'}]
648
- };
894
+ nurl: 'http://example.com/win/${AUCTION_PRICE}',
895
+ cpm: 2.1,
896
+ originalCpm: 1.1,
897
+ }
649
898
  spec.onBidWon(bid);
650
- expect(bid.burl).to.deep.equal(burl);
651
- });
652
- });
899
+ expect(utils.triggerPixel.callCount).to.equal(1)
900
+ })
901
+ })
653
902
  });