prebid.js 7.6.0 → 7.7.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 (159) hide show
  1. package/dist/1plusXRtdProvider.js +1 -0
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adoceanBidAdapter.js +1 -1
  7. package/dist/adrelevantisBidAdapter.js +1 -1
  8. package/dist/adxcgBidAdapter.js +1 -1
  9. package/dist/ajaBidAdapter.js +1 -1
  10. package/dist/amxBidAdapter.js +1 -1
  11. package/dist/amxIdSystem.js +1 -1
  12. package/dist/appierAnalyticsAdapter.js +1 -1
  13. package/dist/appnexusBidAdapter.js +1 -1
  14. package/dist/asoBidAdapter.js +1 -1
  15. package/dist/axonixBidAdapter.js +1 -1
  16. package/dist/bidglassBidAdapter.js +1 -1
  17. package/dist/big-richmediaBidAdapter.js +1 -1
  18. package/dist/bliinkBidAdapter.js +1 -1
  19. package/dist/bridgewellBidAdapter.js +1 -1
  20. package/dist/brightMountainMediaBidAdapter.js +1 -1
  21. package/dist/concertBidAdapter.js +1 -1
  22. package/dist/connectadBidAdapter.js +1 -1
  23. package/dist/consumableBidAdapter.js +1 -1
  24. package/dist/conversantBidAdapter.js +1 -1
  25. package/dist/craftBidAdapter.js +1 -1
  26. package/dist/criteoBidAdapter.js +1 -1
  27. package/dist/currency.js +1 -1
  28. package/dist/dspxBidAdapter.js +1 -1
  29. package/dist/eplanningBidAdapter.js +1 -1
  30. package/dist/finativeBidAdapter.js +1 -1
  31. package/dist/glimpseBidAdapter.js +1 -1
  32. package/dist/gmosspBidAdapter.js +1 -1
  33. package/dist/goldbachBidAdapter.js +1 -1
  34. package/dist/gridBidAdapter.js +1 -1
  35. package/dist/gridNMBidAdapter.js +1 -1
  36. package/dist/gumgumBidAdapter.js +1 -1
  37. package/dist/h12mediaBidAdapter.js +1 -1
  38. package/dist/id5IdSystem.js +1 -1
  39. package/dist/impactifyBidAdapter.js +1 -1
  40. package/dist/improvedigitalBidAdapter.js +1 -1
  41. package/dist/inmarBidAdapter.js +1 -1
  42. package/dist/insticatorBidAdapter.js +1 -1
  43. package/dist/ixBidAdapter.js +1 -1
  44. package/dist/jixieBidAdapter.js +1 -1
  45. package/dist/justpremiumBidAdapter.js +1 -1
  46. package/dist/konduitAnalyticsAdapter.js +1 -1
  47. package/dist/kueezBidAdapter.js +1 -1
  48. package/dist/lassoBidAdapter.js +1 -1
  49. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  50. package/dist/logicadBidAdapter.js +1 -1
  51. package/dist/loglyliftBidAdapter.js +1 -1
  52. package/dist/malltvAnalyticsAdapter.js +1 -1
  53. package/dist/marsmediaBidAdapter.js +1 -1
  54. package/dist/mediafuseBidAdapter.js +1 -1
  55. package/dist/mediasquareBidAdapter.js +1 -1
  56. package/dist/mgidBidAdapter.js +1 -1
  57. package/dist/minutemediaBidAdapter.js +1 -1
  58. package/dist/naveggIdSystem.js +1 -1
  59. package/dist/not-for-prod/prebid.js +112 -111
  60. package/dist/oguryBidAdapter.js +1 -1
  61. package/dist/onetagBidAdapter.js +1 -1
  62. package/dist/ooloAnalyticsAdapter.js +1 -1
  63. package/dist/outbrainBidAdapter.js +1 -1
  64. package/dist/parrableIdSystem.js +1 -1
  65. package/dist/pixfutureBidAdapter.js +1 -1
  66. package/dist/prebid-core.js +1 -1
  67. package/dist/prebidServerBidAdapter.js +1 -1
  68. package/dist/publinkIdSystem.js +1 -1
  69. package/dist/pubmaticBidAdapter.js +1 -1
  70. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  71. package/dist/pxyzBidAdapter.js +1 -1
  72. package/dist/quantcastBidAdapter.js +1 -1
  73. package/dist/readpeakBidAdapter.js +1 -1
  74. package/dist/relaidoBidAdapter.js +1 -1
  75. package/dist/rhythmoneBidAdapter.js +1 -1
  76. package/dist/riseBidAdapter.js +1 -1
  77. package/dist/rubiconAnalyticsAdapter.js +1 -1
  78. package/dist/rubiconBidAdapter.js +1 -1
  79. package/dist/seedingAllianceBidAdapter.js +1 -1
  80. package/dist/seedtagBidAdapter.js +1 -1
  81. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  82. package/dist/sharethroughBidAdapter.js +1 -1
  83. package/dist/shinezBidAdapter.js +1 -1
  84. package/dist/smaatoBidAdapter.js +1 -1
  85. package/dist/smartadserverBidAdapter.js +1 -1
  86. package/dist/smartxBidAdapter.js +1 -1
  87. package/dist/smilewantedBidAdapter.js +1 -1
  88. package/dist/sonobiBidAdapter.js +1 -1
  89. package/dist/sovrnAnalyticsAdapter.js +1 -1
  90. package/dist/sovrnBidAdapter.js +1 -1
  91. package/dist/sspBCBidAdapter.js +1 -1
  92. package/dist/sublimeBidAdapter.js +1 -1
  93. package/dist/synacormediaBidAdapter.js +1 -1
  94. package/dist/targetVideoBidAdapter.js +1 -1
  95. package/dist/teadsBidAdapter.js +1 -1
  96. package/dist/trionBidAdapter.js +1 -1
  97. package/dist/tripleliftBidAdapter.js +1 -1
  98. package/dist/ttdBidAdapter.js +1 -1
  99. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  100. package/dist/underdogmediaBidAdapter.js +1 -1
  101. package/dist/undertoneBidAdapter.js +1 -1
  102. package/dist/userId.js +1 -1
  103. package/dist/vidazooBidAdapter.js +1 -1
  104. package/dist/videobyteBidAdapter.js +1 -1
  105. package/dist/visxBidAdapter.js +1 -1
  106. package/dist/vuukleBidAdapter.js +1 -1
  107. package/dist/widespaceBidAdapter.js +1 -1
  108. package/dist/winrBidAdapter.js +1 -1
  109. package/dist/yahoosspBidAdapter.js +1 -1
  110. package/dist/yieldmoBidAdapter.js +1 -1
  111. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  112. package/integrationExamples/gpt/1plusXRtdProviderExample.html +112 -0
  113. package/modules/.submodules.json +2 -1
  114. package/modules/1plusXRtdProvider.js +251 -0
  115. package/modules/1plusXRtdProvider.md +65 -0
  116. package/modules/adoceanBidAdapter.js +10 -3
  117. package/modules/big-richmediaBidAdapter.js +3 -3
  118. package/modules/bliinkBidAdapter.js +120 -193
  119. package/modules/bliinkBidAdapter.md +2 -5
  120. package/modules/consumableBidAdapter.js +9 -0
  121. package/modules/currency.js +2 -2
  122. package/modules/impactifyBidAdapter.js +6 -2
  123. package/modules/ixBidAdapter.js +61 -14
  124. package/modules/ixBidAdapter.md +2 -5
  125. package/modules/jixieBidAdapter.js +10 -10
  126. package/modules/naveggIdSystem.js +1 -12
  127. package/modules/nextMillenniumBidAdapter.md +1 -1
  128. package/modules/onetagBidAdapter.js +44 -7
  129. package/modules/prebidServerBidAdapter/index.js +7 -0
  130. package/modules/rubiconBidAdapter.js +5 -0
  131. package/modules/seedingAllianceBidAdapter.js +3 -0
  132. package/modules/targetVideoBidAdapter.js +18 -0
  133. package/modules/userId/index.js +39 -21
  134. package/package.json +1 -1
  135. package/src/auction.js +6 -5
  136. package/src/consentHandler.js +11 -11
  137. package/src/debugging.js +5 -3
  138. package/src/hook.js +2 -2
  139. package/src/utils/promise.js +96 -21
  140. package/src/utils.js +3 -2
  141. package/test/helpers/consentData.js +2 -1
  142. package/test/spec/auctionmanager_spec.js +1 -6
  143. package/test/spec/debugging_spec.js +2 -2
  144. package/test/spec/modules/1plusXRtdProvider_spec.js +430 -0
  145. package/test/spec/modules/adoceanBidAdapter_spec.js +4 -1
  146. package/test/spec/modules/bliinkBidAdapter_spec.js +323 -136
  147. package/test/spec/modules/consumableBidAdapter_spec.js +47 -1
  148. package/test/spec/modules/idxIdSystem_spec.js +1 -1
  149. package/test/spec/modules/ixBidAdapter_spec.js +77 -2
  150. package/test/spec/modules/jixieBidAdapter_spec.js +8 -8
  151. package/test/spec/modules/onetagBidAdapter_spec.js +53 -4
  152. package/test/spec/modules/parrableIdSystem_spec.js +2 -1
  153. package/test/spec/modules/prebidServerBidAdapter_spec.js +20 -0
  154. package/test/spec/modules/rubiconBidAdapter_spec.js +27 -0
  155. package/test/spec/modules/targetVideoBidAdapter_spec.js +43 -0
  156. package/test/spec/modules/userId_spec.js +15 -2
  157. package/test/spec/unit/pbjs_api_spec.js +1 -5
  158. package/test/spec/unit/utils/promise_spec.js +283 -38
  159. package/test/helpers/syncPromise.js +0 -71
package/src/utils.js CHANGED
@@ -2,6 +2,7 @@ import { config } from './config.js';
2
2
  import clone from 'just-clone';
3
3
  import {find, includes} from './polyfill.js';
4
4
  import CONSTANTS from './constants.json';
5
+ import {GreedyPromise} from './utils/promise.js';
5
6
  export { default as deepAccess } from 'dlv/index.js';
6
7
  export { default as deepSetValue } from 'dset';
7
8
 
@@ -487,7 +488,7 @@ export function hasOwn(objectToCheck, propertyToCheckFor) {
487
488
  * @param {HTMLElement} [doc]
488
489
  * @param {HTMLElement} [target]
489
490
  * @param {Boolean} [asLastChildChild]
490
- * @return {HTMLElement}
491
+ * @return {HTML Element}
491
492
  */
492
493
  export function insertElement(elm, doc, target, asLastChildChild) {
493
494
  doc = doc || document;
@@ -517,7 +518,7 @@ export function insertElement(elm, doc, target, asLastChildChild) {
517
518
  */
518
519
  export function waitForElementToLoad(element, timeout) {
519
520
  let timer = null;
520
- return new Promise((resolve) => {
521
+ return new GreedyPromise((resolve) => {
521
522
  const onLoad = function() {
522
523
  element.removeEventListener('load', onLoad);
523
524
  element.removeEventListener('error', onLoad);
@@ -1,6 +1,7 @@
1
1
  import {gdprDataHandler} from 'src/adapterManager.js';
2
+ import {GreedyPromise} from '../../src/utils/promise.js';
2
3
 
3
4
  export function mockGdprConsent(sandbox, getConsentData = () => null) {
4
- sandbox.stub(gdprDataHandler, 'promise').get(() => Promise.resolve(getConsentData()));
5
+ sandbox.stub(gdprDataHandler, 'promise').get(() => GreedyPromise.resolve(getConsentData()));
5
6
  sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(getConsentData)
6
7
  }
@@ -21,7 +21,6 @@ import {auctionManager} from '../../src/auctionManager.js';
21
21
  import 'modules/debugging/index.js' // some tests look for debugging side effects
22
22
  import {AuctionIndex} from '../../src/auctionIndex.js';
23
23
  import {expect} from 'chai';
24
- import {synchronizePromise} from '../helpers/syncPromise.js';
25
24
 
26
25
  var assert = require('assert');
27
26
 
@@ -134,7 +133,7 @@ function mockAjaxBuilder() {
134
133
  }
135
134
 
136
135
  describe('auctionmanager.js', function () {
137
- let indexAuctions, indexStub, promiseSandbox;
136
+ let indexAuctions, indexStub
138
137
 
139
138
  before(() => {
140
139
  // hooks are global and their side effects depend on what has been loaded
@@ -150,13 +149,10 @@ describe('auctionmanager.js', function () {
150
149
  indexAuctions = [];
151
150
  indexStub = sinon.stub(auctionManager, 'index');
152
151
  indexStub.get(() => new AuctionIndex(() => indexAuctions));
153
- promiseSandbox = sinon.createSandbox();
154
- synchronizePromise(promiseSandbox);
155
152
  });
156
153
 
157
154
  afterEach(() => {
158
155
  indexStub.restore();
159
- promiseSandbox.restore();
160
156
  });
161
157
 
162
158
  describe('getKeyValueTargetingPairs', function () {
@@ -1458,7 +1454,6 @@ describe('auctionmanager.js', function () {
1458
1454
  }
1459
1455
 
1460
1456
  beforeEach(() => {
1461
- promiseSandbox.restore();
1462
1457
  bids = [
1463
1458
  mockBid({bidderCode: BIDDER_CODE1}),
1464
1459
  mockBid({bidderCode: BIDDER_CODE})
@@ -1,6 +1,6 @@
1
1
  import {ready, loadSession, getConfig, reset, debuggingModuleLoader, debuggingControls} from '../../src/debugging.js';
2
2
  import {getGlobal} from '../../src/prebidGlobal.js';
3
- import {promiseControls} from '../../src/utils/promise.js';
3
+ import {defer} from '../../src/utils/promise.js';
4
4
  import funHooks from 'fun-hooks/no-eval/index.js';
5
5
 
6
6
  describe('Debugging', () => {
@@ -67,7 +67,7 @@ describe('Debugging', () => {
67
67
  let debugging, loader, hook, hookRan;
68
68
 
69
69
  beforeEach(() => {
70
- loader = promiseControls();
70
+ loader = defer();
71
71
  hookRan = false;
72
72
  hook = funHooks()('sync', () => { hookRan = true });
73
73
  debugging = debuggingControls({load: sinon.stub().returns(loader.promise), hook});
@@ -0,0 +1,430 @@
1
+ import { config } from 'src/config';
2
+ import {
3
+ onePlusXSubmodule,
4
+ segtaxes,
5
+ extractConfig,
6
+ buildOrtb2Updates,
7
+ updateBidderConfig,
8
+ setTargetingDataToConfig
9
+ } from 'modules/1plusXRtdProvider';
10
+
11
+ describe('1plusXRtdProvider', () => {
12
+ // Fake server config
13
+ let fakeServer;
14
+ const fakeResponseHeaders = {
15
+ 'Content-Type': 'application/json',
16
+ 'Access-Control-Allow-Origin': '*'
17
+ };
18
+ const fakeResponse = {
19
+ s: ['segment1', 'segment2', 'segment3'],
20
+ t: ['targeting1', 'targeting2', 'targeting3']
21
+ };
22
+
23
+ // Bid request config
24
+ const reqBidsConfigObj = {
25
+ adUnits: [{
26
+ bids: [
27
+ { bidder: 'appnexus' }
28
+ ]
29
+ }]
30
+ };
31
+
32
+ // Bidder configs
33
+ const bidderConfigInitial = {
34
+ ortb2: {
35
+ user: { keywords: '' },
36
+ site: { ext: {} }
37
+ }
38
+ }
39
+ const bidderConfigInitialWith1plusXUserData = {
40
+ ortb2: {
41
+ user: {
42
+ data: [{ name: '1plusX.com', segment: [{ id: 'initial' }] }]
43
+ },
44
+ site: { content: { data: [] } }
45
+ }
46
+ }
47
+ const bidderConfigInitialWithUserData = {
48
+ ortb2: {
49
+ user: {
50
+ data: [{ name: 'hello.world', segment: [{ id: 'initial' }] }]
51
+ },
52
+ site: { content: { data: [] } }
53
+ }
54
+ }
55
+ const bidderConfigInitialWith1plusXSiteContent = {
56
+ ortb2: {
57
+ user: { data: [] },
58
+ site: {
59
+ content: {
60
+ data: [{
61
+ name: '1plusX.com', segment: [{ id: 'initial' }], ext: { segtax: 525 }
62
+ }]
63
+ }
64
+ },
65
+ }
66
+ }
67
+ const bidderConfigInitialWithSiteContent = {
68
+ ortb2: {
69
+ user: { data: [] },
70
+ site: {
71
+ content: {
72
+ data: [{ name: 'hello.world', segment: [{ id: 'initial' }] }]
73
+ }
74
+ },
75
+ }
76
+ }
77
+ // Util functions
78
+ const randomBidder = (len = 5) => Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, len);
79
+
80
+ before(() => {
81
+ config.resetConfig();
82
+ })
83
+
84
+ after(() => { })
85
+
86
+ beforeEach(() => {
87
+ fakeServer = sinon.createFakeServer();
88
+ fakeServer.respondWith('GET', '*', [200, fakeResponseHeaders, JSON.stringify(fakeResponse)]);
89
+ fakeServer.respondImmediately = true;
90
+ fakeServer.autoRespond = true;
91
+ })
92
+
93
+ describe('onePlusXSubmodule', () => {
94
+ it('init is successfull', () => {
95
+ const initResult = onePlusXSubmodule.init();
96
+ expect(initResult).to.be.true;
97
+ })
98
+
99
+ it('callback is called after getBidRequestData', () => {
100
+ // Nice case; everything runs as expected
101
+ {
102
+ const callbackSpy = sinon.spy();
103
+ const config = { params: { customerId: 'test', bidders: ['appnexus'] } };
104
+ onePlusXSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, config);
105
+ setTimeout(() => {
106
+ expect(callbackSpy.calledOnce).to.be.true
107
+ }, 100)
108
+ }
109
+ // No customer id in config => error but still callback called
110
+ {
111
+ const callbackSpy = sinon.spy();
112
+ const config = {}
113
+ onePlusXSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, config);
114
+ setTimeout(() => {
115
+ expect(callbackSpy.calledOnce).to.be.true
116
+ }, 100);
117
+ }
118
+ // No bidders in config => error but still callback called
119
+ {
120
+ const callbackSpy = sinon.spy();
121
+ const config = { customerId: 'test' }
122
+ onePlusXSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, config);
123
+ setTimeout(() => {
124
+ expect(callbackSpy.calledOnce).to.be.true
125
+ }, 100);
126
+ }
127
+ })
128
+ })
129
+
130
+ describe('extractConfig', () => {
131
+ const customerId = 'test';
132
+ const timeout = 1000;
133
+ const bidders = ['appnexus'];
134
+
135
+ it('Throws an error if no customerId is specified', () => {
136
+ const moduleConfig = { params: { timeout, bidders } };
137
+ expect(() => extractConfig(moduleConfig, reqBidsConfigObj)).to.throw();
138
+ })
139
+ it('Throws an error if no bidder is specified', () => {
140
+ const moduleConfig = { params: { customerId, timeout } };
141
+ expect(() => extractConfig(moduleConfig, reqBidsConfigObj)).to.throw();
142
+ })
143
+ it("Throws an error if there's no bidder in reqBidsConfigObj", () => {
144
+ const moduleConfig = { params: { customerId, timeout, bidders } };
145
+ const reqBidsConfigEmpty = { adUnits: [{ bids: [] }] };
146
+ expect(() => extractConfig(moduleConfig, reqBidsConfigEmpty)).to.throw();
147
+ })
148
+ it('Returns an object containing the parameters specified', () => {
149
+ const moduleConfig = { params: { customerId, timeout, bidders } };
150
+ const expectedKeys = ['customerId', 'timeout', 'bidders']
151
+ const extractedConfig = extractConfig(moduleConfig, reqBidsConfigObj);
152
+ expect(extractedConfig).to.be.an('object').and.to.have.all.keys(expectedKeys);
153
+ expect(extractedConfig.customerId).to.equal(customerId);
154
+ expect(extractedConfig.timeout).to.equal(timeout);
155
+ expect(extractedConfig.bidders).to.deep.equal(bidders);
156
+ })
157
+ /* 1plusX RTD module may only use bidders that are both specified in :
158
+ - the bid request configuration
159
+ - AND in the 1plusX RTD module configuration
160
+ Below 2 tests are enforcing those rules
161
+ */
162
+ it('Returns the intersection of bidders found in bid request config & module config', () => {
163
+ const bidders = ['appnexus', 'rubicon'];
164
+ const moduleConfig = { params: { customerId, timeout, bidders } };
165
+ const { bidders: extractedBidders } = extractConfig(moduleConfig, reqBidsConfigObj);
166
+ expect(extractedBidders).to.be.an('array').and.to.have.length(1); 7
167
+ expect(extractedBidders[0]).to.equal('appnexus');
168
+ })
169
+ it('Throws an error if no bidder can be used by the module', () => {
170
+ const bidders = ['rubicon'];
171
+ const moduleConfig = { params: { customerId, timeout, bidders } };
172
+ expect(() => extractConfig(moduleConfig, reqBidsConfigObj)).to.throw();
173
+ })
174
+ })
175
+
176
+ describe('buildOrtb2Updates', () => {
177
+ it('fills site.content.data & user.data in the ortb2 config', () => {
178
+ const rtdData = { segments: fakeResponse.s, topics: fakeResponse.t };
179
+ const ortb2Updates = buildOrtb2Updates(rtdData, randomBidder());
180
+
181
+ const expectedOutput = {
182
+ siteContentData: {
183
+ name: '1plusX.com',
184
+ segment: rtdData.topics.map((topicId) => ({ id: topicId })),
185
+ ext: { segtax: segtaxes.CONTENT }
186
+ },
187
+ userData: {
188
+ name: '1plusX.com',
189
+ segment: rtdData.segments.map((segmentId) => ({ id: segmentId }))
190
+ }
191
+ }
192
+ expect([ortb2Updates]).to.deep.include.members([expectedOutput]);
193
+ });
194
+ it('fills site.keywords in the ortb2 config (appnexus specific)', () => {
195
+ const rtdData = { segments: fakeResponse.s, topics: fakeResponse.t };
196
+ const ortb2Updates = buildOrtb2Updates(rtdData, 'appnexus');
197
+
198
+ const expectedOutput = {
199
+ site: {
200
+ keywords: rtdData.topics.join(','),
201
+ }
202
+ }
203
+ expect([ortb2Updates]).to.deep.include.members([expectedOutput]);
204
+ });
205
+
206
+ it('defaults to empty array if no segment is given', () => {
207
+ const rtdData = { topics: fakeResponse.t };
208
+ const ortb2Updates = buildOrtb2Updates(rtdData, randomBidder());
209
+
210
+ const expectedOutput = {
211
+ siteContentData: {
212
+ name: '1plusX.com',
213
+ segment: rtdData.topics.map((topicId) => ({ id: topicId })),
214
+ ext: { segtax: segtaxes.CONTENT }
215
+ },
216
+ userData: {
217
+ name: '1plusX.com',
218
+ segment: []
219
+ }
220
+ }
221
+ expect(ortb2Updates).to.deep.include(expectedOutput);
222
+ })
223
+
224
+ it('defaults to empty array if no topic is given', () => {
225
+ const rtdData = { segments: fakeResponse.s };
226
+ const ortb2Updates = buildOrtb2Updates(rtdData, randomBidder());
227
+
228
+ const expectedOutput = {
229
+ siteContentData: {
230
+ name: '1plusX.com',
231
+ segment: [],
232
+ ext: { segtax: segtaxes.CONTENT }
233
+ },
234
+ userData: {
235
+ name: '1plusX.com',
236
+ segment: rtdData.segments.map((segmentId) => ({ id: segmentId }))
237
+ }
238
+ }
239
+ expect(ortb2Updates).to.deep.include(expectedOutput);
240
+ })
241
+ it('defaults to empty string if no topic is given (appnexus specific)', () => {
242
+ const rtdData = { segments: fakeResponse.s };
243
+ const ortb2Updates = buildOrtb2Updates(rtdData, 'appnexus');
244
+
245
+ const expectedOutput = {
246
+ site: {
247
+ keywords: '',
248
+ }
249
+ }
250
+ expect(ortb2Updates).to.deep.include(expectedOutput);
251
+ })
252
+ })
253
+
254
+ describe('updateBidderConfig', () => {
255
+ const ortb2UpdatesAppNexus = {
256
+ site: {
257
+ keywords: fakeResponse.t.join(','),
258
+ },
259
+ userData: {
260
+ name: '1plusX.com',
261
+ segment: fakeResponse.s.map((segmentId) => ({ id: segmentId }))
262
+ }
263
+ }
264
+ const ortb2Updates = {
265
+ siteContentData: {
266
+ name: '1plusX.com',
267
+ segment: fakeResponse.t.map((topicId) => ({ id: topicId })),
268
+ ext: { segtax: segtaxes.CONTENT }
269
+ },
270
+ userData: {
271
+ name: '1plusX.com',
272
+ segment: fakeResponse.s.map((segmentId) => ({ id: segmentId }))
273
+ }
274
+ }
275
+
276
+ it('merges fetched data in bidderConfig for configured bidders', () => {
277
+ const bidder = randomBidder();
278
+ // Set initial config
279
+ config.setBidderConfig({
280
+ bidders: [bidder],
281
+ config: bidderConfigInitial
282
+ });
283
+ // Call submodule's setBidderConfig
284
+ const newBidderConfig = updateBidderConfig(bidder, ortb2Updates, config.getBidderConfig());
285
+ // Check that the targeting data has been set in the config
286
+ expect(newBidderConfig).not.to.be.null;
287
+ expect(newBidderConfig.ortb2.site.content.data).to.deep.include(ortb2Updates.siteContentData);
288
+ expect(newBidderConfig.ortb2.user.data).to.deep.include(ortb2Updates.userData);
289
+ // Check that existing config didn't get erased
290
+ expect(newBidderConfig.ortb2.site).to.deep.include(bidderConfigInitial.ortb2.site);
291
+ expect(newBidderConfig.ortb2.user).to.deep.include(bidderConfigInitial.ortb2.user);
292
+ })
293
+
294
+ it('merges fetched data in bidderConfig for configured bidders (appnexus specific)', () => {
295
+ const bidder = 'appnexus';
296
+ // Set initial config
297
+ config.setBidderConfig({
298
+ bidders: [bidder],
299
+ config: bidderConfigInitial
300
+ });
301
+ // Call submodule's setBidderConfig
302
+ const newBidderConfig = updateBidderConfig(bidder, ortb2UpdatesAppNexus, config.getBidderConfig());
303
+
304
+ // Check that the targeting data has been set in the config
305
+ expect(newBidderConfig).not.to.be.null;
306
+ expect(newBidderConfig.ortb2.site).to.deep.include(ortb2UpdatesAppNexus.site);
307
+ // Check that existing config didn't get erased
308
+ expect(newBidderConfig.ortb2.site).to.deep.include(bidderConfigInitial.ortb2.site);
309
+ expect(newBidderConfig.ortb2.user).to.deep.include(bidderConfigInitial.ortb2.user);
310
+ })
311
+
312
+ it('overwrites an existing 1plus.com entry in ortb2.user.data', () => {
313
+ const bidder = randomBidder();
314
+ // Set initial config
315
+ config.setBidderConfig({
316
+ bidders: [bidder],
317
+ config: bidderConfigInitialWith1plusXUserData
318
+ });
319
+ // Save previous user.data entry
320
+ const previousUserData = bidderConfigInitialWith1plusXUserData.ortb2.user.data[0];
321
+ // Call submodule's setBidderConfig
322
+ const newBidderConfig = updateBidderConfig(bidder, ortb2Updates, config.getBidderConfig());
323
+ // Check that the targeting data has been set in the config
324
+ expect(newBidderConfig).not.to.be.null;
325
+ expect(newBidderConfig.ortb2.user.data).to.deep.include(ortb2Updates.userData);
326
+ expect(newBidderConfig.ortb2.user.data).not.to.include(previousUserData);
327
+ })
328
+ it("doesn't overwrite entries in ortb2.user.data that aren't 1plusx.com", () => {
329
+ const bidder = randomBidder();
330
+ // Set initial config
331
+ config.setBidderConfig({
332
+ bidders: [bidder],
333
+ config: bidderConfigInitialWithUserData
334
+ });
335
+ // Save previous user.data entry
336
+ const previousUserData = bidderConfigInitialWithUserData.ortb2.user.data[0];
337
+ // Call submodule's setBidderConfig
338
+ const newBidderConfig = updateBidderConfig(bidder, ortb2Updates, config.getBidderConfig());
339
+ // Check that the targeting data has been set in the config
340
+ expect(newBidderConfig).not.to.be.null;
341
+ expect(newBidderConfig.ortb2.user.data).to.deep.include(ortb2Updates.userData);
342
+ expect(newBidderConfig.ortb2.user.data).to.deep.include(previousUserData);
343
+ })
344
+
345
+ it('overwrites an existing 1plus.com entry in ortb2.site.content.data', () => {
346
+ const bidder = randomBidder();
347
+ // Set initial config
348
+ config.setBidderConfig({
349
+ bidders: [bidder],
350
+ config: bidderConfigInitialWith1plusXSiteContent
351
+ });
352
+ // Save previous user.data entry
353
+ const previousSiteContent = bidderConfigInitialWith1plusXSiteContent.ortb2.site.content.data[0];
354
+ // Call submodule's setBidderConfig
355
+ const newBidderConfig = updateBidderConfig(bidder, ortb2Updates, config.getBidderConfig());
356
+ // Check that the targeting data has been set in the config
357
+ expect(newBidderConfig).not.to.be.null;
358
+ expect(newBidderConfig.ortb2.site.content.data).to.deep.include(ortb2Updates.siteContentData);
359
+ expect(newBidderConfig.ortb2.site.content.data).not.to.include(previousSiteContent);
360
+ })
361
+ it("doesn't overwrite entries in ortb2.site.content.data that aren't 1plusx.com", () => {
362
+ const bidder = randomBidder();
363
+ // Set initial config
364
+ config.setBidderConfig({
365
+ bidders: [bidder],
366
+ config: bidderConfigInitialWithSiteContent
367
+ });
368
+ // Save previous user.data entry
369
+ const previousSiteContent = bidderConfigInitialWithSiteContent.ortb2.site.content.data[0];
370
+ // Call submodule's setBidderConfig
371
+ const newBidderConfig = updateBidderConfig(bidder, ortb2Updates, config.getBidderConfig());
372
+ // Check that the targeting data has been set in the config
373
+ expect(newBidderConfig).not.to.be.null;
374
+ expect(newBidderConfig.ortb2.site.content.data).to.deep.include(ortb2Updates.siteContentData);
375
+ expect(newBidderConfig.ortb2.site.content.data).to.deep.include(previousSiteContent);
376
+ })
377
+ })
378
+
379
+ describe('setTargetingDataToConfig', () => {
380
+ const expectedKeywords = fakeResponse.t.join(',');
381
+ const expectedSiteContentObj = {
382
+ data: [{
383
+ name: '1plusX.com',
384
+ segment: fakeResponse.t.map((topicId) => ({ id: topicId })),
385
+ ext: { segtax: segtaxes.CONTENT }
386
+ }]
387
+ }
388
+ const expectedUserObj = {
389
+ data: [{
390
+ name: '1plusX.com',
391
+ segment: fakeResponse.s.map((segmentId) => ({ id: segmentId }))
392
+ }]
393
+ }
394
+ const expectedOrtb2 = {
395
+ appnexus: {
396
+ site: { keywords: expectedKeywords }
397
+ },
398
+ rubicon: {
399
+ site: { content: expectedSiteContentObj },
400
+ user: expectedUserObj
401
+ }
402
+ }
403
+
404
+ it('sets the config for the selected bidders', () => {
405
+ const bidders = ['appnexus', 'rubicon'];
406
+ // setting initial config for those bidders
407
+ config.setBidderConfig({
408
+ bidders,
409
+ config: bidderConfigInitial
410
+ })
411
+ // call setTargetingDataToConfig
412
+ setTargetingDataToConfig(fakeResponse, { bidders });
413
+
414
+ // Check that the targeting data has been set in both configs
415
+ for (const bidder of bidders) {
416
+ const newConfig = config.getBidderConfig()[bidder];
417
+ // Check that we got what we expect
418
+ const expectedConfErr = (prop) => `New config for ${bidder} doesn't comply with expected at ${prop}`;
419
+ expect(newConfig.ortb2.site, expectedConfErr('site')).to.deep.include(expectedOrtb2[bidder].site);
420
+ if (expectedOrtb2[bidder].user) {
421
+ expect(newConfig.ortb2.user, expectedConfErr('user')).to.deep.include(expectedOrtb2[bidder].user);
422
+ }
423
+ // Check that existing config didn't get erased
424
+ const existingConfErr = (prop) => `Existing config for ${bidder} got unlawfully overwritten at ${prop}`;
425
+ expect(newConfig.ortb2.site, existingConfErr('site')).to.deep.include(bidderConfigInitial.ortb2.site);
426
+ expect(newConfig.ortb2.user, existingConfErr('user')).to.deep.include(bidderConfigInitial.ortb2.user);
427
+ }
428
+ })
429
+ })
430
+ })
@@ -136,10 +136,12 @@ describe('AdoceanAdapter', function () {
136
136
  expect(request.url).to.include('gdpr_consent=' + bidderRequest.gdprConsent.consentString);
137
137
  });
138
138
 
139
- it('should attach sizes information to url', function () {
139
+ it('should attach sizes and slaves information to url', function () {
140
140
  let requests = spec.buildRequests(bidRequests, bidderRequest);
141
141
  expect(requests[0].url).to.include('aosspsizes=myaozpniqismex~300x250_300x600');
142
+ expect(requests[0].url).to.include('slaves=zpniqismex');
142
143
  expect(requests[1].url).to.include('aosspsizes=myaozpniqismex~300x200_600x250');
144
+ expect(requests[1].url).to.include('slaves=zpniqismex');
143
145
 
144
146
  const differentSlavesBids = deepClone(bidRequests);
145
147
  differentSlavesBids[1].params.slaveId = 'adoceanmyaowafpdwlrks';
@@ -147,6 +149,7 @@ describe('AdoceanAdapter', function () {
147
149
  expect(requests.length).to.equal(1);
148
150
  expect(requests[0].url).to.include('aosspsizes=myaozpniqismex~300x250_300x600-myaowafpdwlrks~300x200_600x250');
149
151
  expect((requests[0].url.match(/aosspsizes=/g) || []).length).to.equal(1);
152
+ expect(requests[0].url).to.include('slaves=zpniqismex,wafpdwlrks');
150
153
  });
151
154
 
152
155
  it('should attach schain parameter if available', function() {