prebid.js 9.53.1 → 9.53.2
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.
- package/dist/33acrossAnalyticsAdapter.js +1 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/BTBidAdapter.js +1 -1
- package/dist/adagioAnalyticsAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adagioUtils.js +1 -1
- package/dist/addefendBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adlooxRtdProvider.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adstirBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgAnalyticsAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adyoulikeBidAdapter.js +1 -1
- package/dist/agmaAnalyticsAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/aniviewBidAdapter.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/beopBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bitmediaBidAdapter.js +1 -1
- package/dist/bridBidAdapter.js +1 -1
- package/dist/bridgeuppBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/chunk-core.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/contxtfulBidAdapter.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/cwireBidAdapter.js +1 -1
- package/dist/dailymotionBidAdapter.js +1 -1
- package/dist/dependencies.json +6 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/dxkultureBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/equativBidAdapter.js +1 -1
- package/dist/eskimiBidAdapter.js +1 -1
- package/dist/euidIdSystem.js +1 -1
- package/dist/exadsBidAdapter.js +1 -1
- package/dist/excoBidAdapter.js +1 -1
- package/dist/fanAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsBidAdapter.js +1 -1
- package/dist/greenbidsRtdProvider.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/hypelabBidAdapter.js +1 -1
- package/dist/id5AnalyticsAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/imdsBidAdapter.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmobiBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/intentIqAnalyticsAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/jixieBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoBidAdapter.js +1 -1
- package/dist/kimberliteBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/liveIntentId.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/luceadBidAdapter.js +1 -1
- package/dist/mabidderBidAdapter.js +1 -1
- package/dist/madsenseBidAdapter.js +1 -1
- package/dist/magniteAnalyticsAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/medianetBidAdapter.js +1 -1
- package/dist/medianetUtils.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/missenaBidAdapter.js +1 -1
- package/dist/mobilefuseBidAdapter.js +1 -1
- package/dist/nextMillenniumBidAdapter.js +1 -1
- package/dist/nexx360Utils.js +1 -1
- package/dist/nobidAnalyticsAdapter.js +1 -1
- package/dist/nobidBidAdapter.js +1 -1
- package/dist/nodalsAiRtdProvider.js +1 -1
- package/dist/not-for-prod/prebid.js +168 -168
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxBidAdapter.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/orbidderBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticAnalyticsAdapter.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubxaiAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseUtils.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/showheroes-bsBidAdapter.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/snigelBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sparteoBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stvBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/taboolaBidAdapter.js +1 -1
- package/dist/tappxBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/terceptAnalyticsAdapter.js +1 -1
- package/dist/themoneytizerBidAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/uid2IdSystem.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/unrulyBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/vidazooUtils.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahooAdsBidAdapter.js +1 -1
- package/dist/yandexBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/libraries/liveIntentId/shared.js +16 -0
- package/modules/fanAdapter.js +318 -124
- package/modules/userId/index.js +30 -31
- package/package.json +4 -4
- package/test/spec/modules/euidIdSystem_spec.js +9 -3
- package/test/spec/modules/fanAdapter_spec.js +264 -268
- package/test/spec/modules/id5IdSystem_spec.js +57 -101
- package/test/spec/modules/idxIdSystem_spec.js +2 -75
- package/test/spec/modules/liveIntentExternalIdSystem_spec.js +5 -0
- package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +5 -0
- package/test/spec/modules/liveIntentIdSystem_spec.js +38 -0
- package/test/spec/modules/lmpIdSystem_spec.js +2 -81
- package/test/spec/modules/pubmaticBidAdapter_spec.js +411 -126
- package/test/spec/modules/sharedIdSystem_spec.js +3 -3
- package/test/spec/modules/uid2IdSystem_helpers.js +5 -2
- package/test/spec/modules/userId_spec.js +142 -387
- package/test/spec/modules/zeotapIdPlusIdSystem_spec.js +3 -69
|
@@ -6,7 +6,7 @@ import { config } from 'src/config.js';
|
|
|
6
6
|
|
|
7
7
|
describe('PubMatic adapter', () => {
|
|
8
8
|
let firstBid, videoBid, firstResponse, response, videoResponse;
|
|
9
|
-
|
|
9
|
+
const request = {};
|
|
10
10
|
firstBid = {
|
|
11
11
|
adUnitCode: 'Div1',
|
|
12
12
|
bidder: 'pubmatic',
|
|
@@ -51,13 +51,13 @@ describe('PubMatic adapter', () => {
|
|
|
51
51
|
js: 1,
|
|
52
52
|
connectiontype: 6
|
|
53
53
|
},
|
|
54
|
-
site: {domain: 'ebay.com', page: 'https://ebay.com'},
|
|
54
|
+
site: {domain: 'ebay.com', page: 'https://ebay.com', publisher: {id: '5670'}},
|
|
55
55
|
source: {}
|
|
56
56
|
},
|
|
57
57
|
ortb2Imp: {
|
|
58
58
|
ext: {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
tid: '92489f71-1bf2-49a0-adf9-000cea934729',
|
|
60
|
+
gpid: '/1111/homepage-leftnav',
|
|
61
61
|
data: {
|
|
62
62
|
pbadslot: '/1111/homepage-leftnav',
|
|
63
63
|
adserver: {
|
|
@@ -70,11 +70,23 @@ describe('PubMatic adapter', () => {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
|
+
rtd: {
|
|
74
|
+
jwplayer: {
|
|
75
|
+
targeting: {
|
|
76
|
+
content: {
|
|
77
|
+
id: 'jwplayer-content-id'
|
|
78
|
+
},
|
|
79
|
+
segments: [
|
|
80
|
+
'jwplayer-segment-1', 'jwplayer-segment-2'
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
73
85
|
}
|
|
74
86
|
videoBid = {
|
|
75
87
|
'seat': 'seat-id',
|
|
76
88
|
'ext': {
|
|
77
|
-
|
|
89
|
+
'buyid': 'BUYER-ID-987'
|
|
78
90
|
},
|
|
79
91
|
'bid': [{
|
|
80
92
|
'id': '74858439-49D7-4169-BA5D-44A046315B2F',
|
|
@@ -90,13 +102,14 @@ describe('PubMatic adapter', () => {
|
|
|
90
102
|
'dspid': 123
|
|
91
103
|
},
|
|
92
104
|
'dealid': 'PUBDEAL1',
|
|
93
|
-
'mtype': 2
|
|
105
|
+
'mtype': 2,
|
|
106
|
+
'params': {'outstreamAU': 'outstreamAU', 'renderer': 'renderer_test_pubmatic'}
|
|
94
107
|
}]
|
|
95
108
|
};
|
|
96
109
|
firstResponse = {
|
|
97
110
|
'seat': 'seat-id',
|
|
98
111
|
'ext': {
|
|
99
|
-
|
|
112
|
+
'buyid': 'BUYER-ID-987'
|
|
100
113
|
},
|
|
101
114
|
'bid': [{
|
|
102
115
|
'id': '74858439-49D7-4169-BA5D-44A046315B2F',
|
|
@@ -117,20 +130,20 @@ describe('PubMatic adapter', () => {
|
|
|
117
130
|
};
|
|
118
131
|
response = {
|
|
119
132
|
'body': {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
133
|
+
cur: 'USD',
|
|
134
|
+
id: '93D3BAD6-E2E2-49FB-9D89-920B1761C865',
|
|
135
|
+
seatbid: [firstResponse]
|
|
123
136
|
}
|
|
124
137
|
};
|
|
125
138
|
videoResponse = {
|
|
126
139
|
'body': {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
140
|
+
cur: 'USD',
|
|
141
|
+
id: '93D3BAD6-E2E2-49FB-9D89-920B1761C865',
|
|
142
|
+
seatbid: [videoBid]
|
|
130
143
|
}
|
|
131
144
|
}
|
|
132
|
-
|
|
133
|
-
|
|
145
|
+
const validBidRequests = [firstBid];
|
|
146
|
+
const bidderRequest = {
|
|
134
147
|
bids: [firstBid],
|
|
135
148
|
auctionId: 'ee3074fe-97ce-4681-9235-d7622aede74c',
|
|
136
149
|
auctionStart: 1725514077194,
|
|
@@ -152,7 +165,8 @@ describe('PubMatic adapter', () => {
|
|
|
152
165
|
site: {domain: 'ebay.com', page: 'https://ebay.com'},
|
|
153
166
|
source: {}
|
|
154
167
|
},
|
|
155
|
-
timeout: 2000
|
|
168
|
+
timeout: 2000,
|
|
169
|
+
|
|
156
170
|
};
|
|
157
171
|
let videoBidRequest, videoBidderRequest, utilsLogWarnMock, nativeBidderRequest;
|
|
158
172
|
|
|
@@ -165,22 +179,23 @@ describe('PubMatic adapter', () => {
|
|
|
165
179
|
it('should return false if publisherId is missing', () => {
|
|
166
180
|
const bid = utils.deepClone(validBidRequests[0]);
|
|
167
181
|
delete bid.params.publisherId;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
182
|
+
const isValid = spec.isBidRequestValid(bid);
|
|
183
|
+
expect(isValid).to.equal(false);
|
|
184
|
+
});
|
|
171
185
|
|
|
172
186
|
it('should return false if publisherId is not of type string', () => {
|
|
173
187
|
const bid = utils.deepClone(validBidRequests[0]);
|
|
174
188
|
bid.params.publisherId = 5890;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
189
|
+
const isValid = spec.isBidRequestValid(bid);
|
|
190
|
+
expect(isValid).to.equal(false);
|
|
191
|
+
});
|
|
178
192
|
|
|
179
193
|
if (FEATURES.VIDEO) {
|
|
180
194
|
describe('VIDEO', () => {
|
|
181
195
|
beforeEach(() => {
|
|
182
196
|
videoBidRequest = utils.deepClone(validBidRequests[0]);
|
|
183
197
|
delete videoBidRequest.mediaTypes.banner;
|
|
198
|
+
delete videoBidRequest.mediaTypes.native;
|
|
184
199
|
videoBidRequest.mediaTypes.video = {
|
|
185
200
|
playerSize: [
|
|
186
201
|
[640, 480]
|
|
@@ -191,10 +206,12 @@ describe('PubMatic adapter', () => {
|
|
|
191
206
|
skip: 1,
|
|
192
207
|
linearity: 2
|
|
193
208
|
}
|
|
209
|
+
videoBidRequest.params.outstreamAU = 'outstreamAU';
|
|
210
|
+
videoBidRequest.params.renderer = 'renderer_test_pubmatic'
|
|
194
211
|
});
|
|
195
212
|
it('should return false if mimes are missing in a video impression request', () => {
|
|
196
|
-
|
|
197
|
-
|
|
213
|
+
const isValid = spec.isBidRequestValid(videoBidRequest);
|
|
214
|
+
expect(isValid).to.equal(false);
|
|
198
215
|
});
|
|
199
216
|
|
|
200
217
|
it('should return false if context is missing in a video impression request', () => {
|
|
@@ -206,9 +223,15 @@ describe('PubMatic adapter', () => {
|
|
|
206
223
|
it('should return true if banner/native present, but outstreamAU or renderer is missing', () => {
|
|
207
224
|
videoBidRequest.mediaTypes.video.mimes = ['video/flv'];
|
|
208
225
|
videoBidRequest.mediaTypes.video.context = 'outstream';
|
|
226
|
+
|
|
209
227
|
videoBidRequest.mediaTypes.banner = {
|
|
210
228
|
sizes: [[728, 90], [160, 600]]
|
|
211
|
-
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// Remove width and height from the video object to test coverage for missing values
|
|
232
|
+
delete videoBidRequest.mediaTypes.video.width;
|
|
233
|
+
delete videoBidRequest.mediaTypes.video.height;
|
|
234
|
+
|
|
212
235
|
const isValid = spec.isBidRequestValid(videoBidRequest);
|
|
213
236
|
expect(isValid).to.equal(true);
|
|
214
237
|
});
|
|
@@ -217,6 +240,11 @@ describe('PubMatic adapter', () => {
|
|
|
217
240
|
const isValid = spec.isBidRequestValid(videoBidRequest);
|
|
218
241
|
expect(isValid).to.equal(false);
|
|
219
242
|
});
|
|
243
|
+
|
|
244
|
+
it('should return TRUE if outstreamAU or renderer is present', () => {
|
|
245
|
+
const isValid = spec.isBidRequestValid(videoBidRequest);
|
|
246
|
+
expect(isValid).to.equal(false);
|
|
247
|
+
});
|
|
220
248
|
});
|
|
221
249
|
}
|
|
222
250
|
});
|
|
@@ -226,7 +254,6 @@ describe('PubMatic adapter', () => {
|
|
|
226
254
|
it('should include previousAuctionInfo in request when available', () => {
|
|
227
255
|
const bidRequestWithPrevAuction = utils.deepClone(validBidRequests[0]);
|
|
228
256
|
const bidderRequestWithPrevAuction = utils.deepClone(bidderRequest);
|
|
229
|
-
|
|
230
257
|
bidderRequestWithPrevAuction.ortb2 = bidderRequestWithPrevAuction.ortb2 || {};
|
|
231
258
|
bidderRequestWithPrevAuction.ortb2.ext = bidderRequestWithPrevAuction.ortb2.ext || {};
|
|
232
259
|
bidderRequestWithPrevAuction.ortb2.ext.prebid = bidderRequestWithPrevAuction.ortb2.ext.prebid || {};
|
|
@@ -273,14 +300,6 @@ describe('PubMatic adapter', () => {
|
|
|
273
300
|
expect(imp[0]).to.have.property('ext').to.have.property('key_val');
|
|
274
301
|
});
|
|
275
302
|
|
|
276
|
-
it('should not add key_val if dctr is absent in parameters', () => {
|
|
277
|
-
delete validBidRequests[0].params.dctr;
|
|
278
|
-
const request = spec.buildRequests(validBidRequests, bidderRequest);
|
|
279
|
-
const { imp } = request?.data;
|
|
280
|
-
expect(imp).to.be.an('array');
|
|
281
|
-
expect(imp[0]).to.have.property('ext').to.not.have.property('key_val');
|
|
282
|
-
});
|
|
283
|
-
|
|
284
303
|
it('should set w and h to the primary size for banner', () => {
|
|
285
304
|
const request = spec.buildRequests(validBidRequests, bidderRequest);
|
|
286
305
|
const { imp } = request?.data;
|
|
@@ -393,7 +412,7 @@ describe('PubMatic adapter', () => {
|
|
|
393
412
|
expect(imp[0]).to.have.property('banner').to.have.property('pos').equal(0);
|
|
394
413
|
});
|
|
395
414
|
|
|
396
|
-
|
|
415
|
+
if (FEATURES.VIDEO) {
|
|
397
416
|
describe('VIDEO', () => {
|
|
398
417
|
beforeEach(() => {
|
|
399
418
|
utilsLogWarnMock = sinon.stub(utils, 'logWarn');
|
|
@@ -412,10 +431,14 @@ describe('PubMatic adapter', () => {
|
|
|
412
431
|
linearity: 1,
|
|
413
432
|
placement: 2,
|
|
414
433
|
plcmt: 1,
|
|
434
|
+
context: 'outstream',
|
|
415
435
|
minbitrate: 10,
|
|
416
436
|
maxbitrate: 10,
|
|
417
437
|
playerSize: [640, 480]
|
|
418
438
|
}
|
|
439
|
+
videoBidderRequest.bids[0].params.outstreamAU = 'outstreamAU';
|
|
440
|
+
videoBidderRequest.bids[0].params.renderer = 'renderer_test_pubmatic'
|
|
441
|
+
videoBidderRequest.bids[0].adUnitCode = 'Div1';
|
|
419
442
|
});
|
|
420
443
|
|
|
421
444
|
afterEach(() => {
|
|
@@ -467,8 +490,8 @@ describe('PubMatic adapter', () => {
|
|
|
467
490
|
expect(imp[0]).to.have.property('video').to.have.property('h');
|
|
468
491
|
});
|
|
469
492
|
});
|
|
470
|
-
|
|
471
|
-
|
|
493
|
+
}
|
|
494
|
+
if (FEATURES.NATIVE) {
|
|
472
495
|
describe('NATIVE', () => {
|
|
473
496
|
beforeEach(() => {
|
|
474
497
|
utilsLogWarnMock = sinon.stub(utils, 'logWarn');
|
|
@@ -512,60 +535,7 @@ describe('PubMatic adapter', () => {
|
|
|
512
535
|
expect(imp[0]).to.have.property('native');
|
|
513
536
|
});
|
|
514
537
|
});
|
|
515
|
-
|
|
516
|
-
// describe('MULTIFORMAT', () => {
|
|
517
|
-
// let multiFormatBidderRequest;
|
|
518
|
-
// it('should have both banner & video impressions', () => {
|
|
519
|
-
// multiFormatBidderRequest = utils.deepClone(bidderRequest);
|
|
520
|
-
// multiFormatBidderRequest.bids[0].mediaTypes.video = {
|
|
521
|
-
// skip: 1,
|
|
522
|
-
// mimes: ['video/mp4', 'video/x-flv'],
|
|
523
|
-
// minduration: 5,
|
|
524
|
-
// maxduration: 30,
|
|
525
|
-
// startdelay: 5,
|
|
526
|
-
// playbackmethod: [1, 3],
|
|
527
|
-
// api: [1, 2],
|
|
528
|
-
// protocols: [2, 3],
|
|
529
|
-
// battr: [13, 14],
|
|
530
|
-
// linearity: 1,
|
|
531
|
-
// placement: 2,
|
|
532
|
-
// plcmt: 1,
|
|
533
|
-
// minbitrate: 10,
|
|
534
|
-
// maxbitrate: 10,
|
|
535
|
-
// playerSize: [640, 480]
|
|
536
|
-
// }
|
|
537
|
-
// const request = spec.buildRequests(validBidRequests, multiFormatBidderRequest);
|
|
538
|
-
// const { imp } = request?.data;
|
|
539
|
-
// expect(imp).to.be.an('array');
|
|
540
|
-
// expect(imp[0]).to.have.property('banner');
|
|
541
|
-
// expect(imp[0].banner).to.have.property('topframe');
|
|
542
|
-
// expect(imp[0].banner).to.have.property('format');
|
|
543
|
-
// expect(imp[0]).to.have.property('video');
|
|
544
|
-
// });
|
|
545
|
-
|
|
546
|
-
// it('should have both banner & native impressions', () => {
|
|
547
|
-
// multiFormatBidderRequest = utils.deepClone(bidderRequest);
|
|
548
|
-
// multiFormatBidderRequest.bids[0].nativeOrtbRequest = {
|
|
549
|
-
// ver: '1.2',
|
|
550
|
-
// assets: [{
|
|
551
|
-
// id: 0,
|
|
552
|
-
// img: {
|
|
553
|
-
// 'type': 3,
|
|
554
|
-
// 'w': 300,
|
|
555
|
-
// 'h': 250
|
|
556
|
-
// },
|
|
557
|
-
// required: 1,
|
|
558
|
-
// }]
|
|
559
|
-
// };
|
|
560
|
-
// const request = spec.buildRequests(validBidRequests, multiFormatBidderRequest);
|
|
561
|
-
// const { imp } = request?.data;
|
|
562
|
-
// expect(imp).to.be.an('array');
|
|
563
|
-
// expect(imp[0]).to.have.property('banner');
|
|
564
|
-
// expect(imp[0].banner).to.have.property('topframe');
|
|
565
|
-
// expect(imp[0].banner).to.have.property('format');
|
|
566
|
-
// expect(imp[0]).to.have.property('native');
|
|
567
|
-
// });
|
|
568
|
-
// });
|
|
538
|
+
}
|
|
569
539
|
});
|
|
570
540
|
|
|
571
541
|
describe('rest of ORTB request', () => {
|
|
@@ -821,7 +791,7 @@ describe('PubMatic adapter', () => {
|
|
|
821
791
|
|
|
822
792
|
describe('GPP', () => {
|
|
823
793
|
it('should have gpp & gpp_sid in request if set using ortb2 and not present in request', () => {
|
|
824
|
-
|
|
794
|
+
const copiedBidderRequest = utils.deepClone(bidderRequest);
|
|
825
795
|
copiedBidderRequest.ortb2.regs = {
|
|
826
796
|
gpp: 'DBACNYA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN',
|
|
827
797
|
gpp_sid: [5]
|
|
@@ -839,14 +809,14 @@ describe('PubMatic adapter', () => {
|
|
|
839
809
|
pubrender: 0,
|
|
840
810
|
datatopub: 2,
|
|
841
811
|
transparency: [
|
|
842
|
-
|
|
812
|
+
{
|
|
843
813
|
domain: 'platform1domain.com',
|
|
844
814
|
dsaparams: [1]
|
|
845
|
-
|
|
846
|
-
|
|
815
|
+
},
|
|
816
|
+
{
|
|
847
817
|
domain: 'SSP2domain.com',
|
|
848
818
|
dsaparams: [1, 2]
|
|
849
|
-
|
|
819
|
+
}
|
|
850
820
|
]
|
|
851
821
|
};
|
|
852
822
|
beforeEach(() => {
|
|
@@ -936,7 +906,34 @@ describe('PubMatic adapter', () => {
|
|
|
936
906
|
};
|
|
937
907
|
|
|
938
908
|
spec.onBidWon(bid);
|
|
909
|
+
expect(cpmAdjustment).to.deep.equal({
|
|
910
|
+
currency: 'USD',
|
|
911
|
+
originalCurrency: 'USD',
|
|
912
|
+
adjustment: [
|
|
913
|
+
{
|
|
914
|
+
cpmAdjustment: Number(((3 - 2.5) / 3).toFixed(2)), // Expected: 0.17
|
|
915
|
+
mediaType: 'banner',
|
|
916
|
+
metaMediaType: 'banner',
|
|
917
|
+
cpm: 2.5,
|
|
918
|
+
originalCpm: 3
|
|
919
|
+
}
|
|
920
|
+
]
|
|
921
|
+
});
|
|
922
|
+
});
|
|
939
923
|
|
|
924
|
+
it('should invoke _calculateBidCpmAdjustment and correctly update cpmAdjustment currency is different', () => {
|
|
925
|
+
const bid = {
|
|
926
|
+
cpm: 2.5,
|
|
927
|
+
originalCpm: 3,
|
|
928
|
+
originalCurrency: 'USD',
|
|
929
|
+
currency: 'EUR',
|
|
930
|
+
mediaType: 'banner',
|
|
931
|
+
meta: { mediaType: 'banner' },
|
|
932
|
+
getCpmInNewCurrency: function(currency) {
|
|
933
|
+
return currency === 'EUR' ? 2.8 : this.cpm;
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
spec.onBidWon(bid);
|
|
940
937
|
expect(cpmAdjustment).to.deep.equal({
|
|
941
938
|
currency: 'USD',
|
|
942
939
|
originalCurrency: 'USD',
|
|
@@ -951,40 +948,139 @@ describe('PubMatic adapter', () => {
|
|
|
951
948
|
]
|
|
952
949
|
});
|
|
953
950
|
});
|
|
954
|
-
});
|
|
955
951
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
952
|
+
it('should replace existing adjustment entry if mediaType and metaMediaType match', () => {
|
|
953
|
+
const bid1 = {
|
|
954
|
+
cpm: 2.5,
|
|
955
|
+
originalCpm: 3,
|
|
956
|
+
originalCurrency: 'USD',
|
|
957
|
+
currency: 'USD',
|
|
958
|
+
mediaType: 'banner',
|
|
959
|
+
meta: { mediaType: 'banner' }
|
|
960
|
+
};
|
|
961
|
+
const bid2 = {
|
|
962
|
+
cpm: 1.5,
|
|
963
|
+
originalCpm: 2,
|
|
964
|
+
originalCurrency: 'USD',
|
|
965
|
+
currency: 'USD',
|
|
966
|
+
mediaType: 'banner',
|
|
967
|
+
meta: { mediaType: 'banner' }
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
spec.onBidWon(bid1);
|
|
971
|
+
// Should add the first entry
|
|
972
|
+
expect(cpmAdjustment.adjustment.length).to.equal(1);
|
|
973
|
+
expect(cpmAdjustment.adjustment[0].cpm).to.equal(2.5);
|
|
974
|
+
spec.onBidWon(bid2);
|
|
975
|
+
// Should replace the entry, not add a new one
|
|
976
|
+
expect(cpmAdjustment.adjustment.length).to.equal(1);
|
|
977
|
+
expect(cpmAdjustment.adjustment[0].cpm).to.equal(1.5);
|
|
978
|
+
expect(cpmAdjustment.adjustment[0].originalCpm).to.equal(2);
|
|
979
|
+
});
|
|
980
|
+
});
|
|
984
981
|
});
|
|
985
982
|
});
|
|
986
983
|
|
|
987
984
|
describe('Response', () => {
|
|
985
|
+
it('should parse native adm and set bidResponse.native, width, and height', () => {
|
|
986
|
+
// Prepare a valid native bidRequest
|
|
987
|
+
const bidRequest = utils.deepClone(validBidRequests[0]);
|
|
988
|
+
bidRequest.mediaTypes = {
|
|
989
|
+
native: {
|
|
990
|
+
title: { required: true, len: 140 }
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
delete bidRequest.mediaTypes.banner;
|
|
994
|
+
delete bidRequest.mediaTypes.video;
|
|
995
|
+
bidRequest.sizes = undefined;
|
|
996
|
+
const request = spec.buildRequests([bidRequest], bidderRequest);
|
|
997
|
+
// Prepare a valid native bid response with matching impid
|
|
998
|
+
const nativeAdm = JSON.stringify({ native: { assets: [{ id: 1, title: { text: 'Test' } }] } });
|
|
999
|
+
const nativeBid = {
|
|
1000
|
+
id: 'bid-id',
|
|
1001
|
+
impid: request.data.imp[0].id, // match the imp id
|
|
1002
|
+
price: 1.2,
|
|
1003
|
+
adm: nativeAdm,
|
|
1004
|
+
w: 123,
|
|
1005
|
+
h: 456,
|
|
1006
|
+
adomain: ['example.com'],
|
|
1007
|
+
mtype: 4 // NATIVE
|
|
1008
|
+
};
|
|
1009
|
+
const seatbid = [{ bid: [nativeBid] }];
|
|
1010
|
+
const nativeResponse = { body: { seatbid } };
|
|
1011
|
+
const bidResponses = spec.interpretResponse(nativeResponse, request);
|
|
1012
|
+
expect(bidResponses).to.be.an('array');
|
|
1013
|
+
expect(bidResponses[0]).to.exist;
|
|
1014
|
+
expect(bidResponses[0].native).to.exist;
|
|
1015
|
+
expect(bidResponses[0].width).to.equal(123);
|
|
1016
|
+
expect(bidResponses[0].height).to.equal(456);
|
|
1017
|
+
});
|
|
1018
|
+
|
|
1019
|
+
it('should handle invalid JSON in native adm gracefully', () => {
|
|
1020
|
+
// Prepare a valid native bidRequest
|
|
1021
|
+
const bidRequest = utils.deepClone(validBidRequests[0]);
|
|
1022
|
+
bidRequest.mediaTypes = {
|
|
1023
|
+
native: {
|
|
1024
|
+
title: { required: true, len: 140 }
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
delete bidRequest.mediaTypes.banner;
|
|
1028
|
+
delete bidRequest.mediaTypes.video;
|
|
1029
|
+
bidRequest.sizes = undefined;
|
|
1030
|
+
const request = spec.buildRequests([bidRequest], bidderRequest);
|
|
1031
|
+
|
|
1032
|
+
// Prepare a native bid response with invalid JSON and matching impid
|
|
1033
|
+
const invalidAdm = '{ native: { assets: [ { id: 1, title: { text: "Test" } } ] }'; // missing closing }
|
|
1034
|
+
const nativeBid = {
|
|
1035
|
+
id: 'bid-id',
|
|
1036
|
+
impid: request.data.imp[0].id, // match the imp id
|
|
1037
|
+
price: 1.2,
|
|
1038
|
+
adm: invalidAdm,
|
|
1039
|
+
w: 123,
|
|
1040
|
+
h: 456,
|
|
1041
|
+
adomain: ['example.com'],
|
|
1042
|
+
mtype: 4 // NATIVE
|
|
1043
|
+
};
|
|
1044
|
+
const seatbid = [{ bid: [nativeBid] }];
|
|
1045
|
+
const nativeResponse = { body: { seatbid } };
|
|
1046
|
+
const bidResponses = spec.interpretResponse(nativeResponse, request);
|
|
1047
|
+
expect(bidResponses).to.be.an('array');
|
|
1048
|
+
expect(bidResponses.length).to.equal(0); // No bid should be returned if adm is invalid
|
|
1049
|
+
});
|
|
1050
|
+
|
|
1051
|
+
it('should set DEFAULT_WIDTH and DEFAULT_HEIGHT when bid.w and bid.h are missing for native', () => {
|
|
1052
|
+
// Prepare a valid native bidRequest
|
|
1053
|
+
const bidRequest = utils.deepClone(validBidRequests[0]);
|
|
1054
|
+
bidRequest.mediaTypes = {
|
|
1055
|
+
native: {
|
|
1056
|
+
title: { required: true, len: 140 }
|
|
1057
|
+
}
|
|
1058
|
+
};
|
|
1059
|
+
delete bidRequest.mediaTypes.banner;
|
|
1060
|
+
delete bidRequest.mediaTypes.video;
|
|
1061
|
+
bidRequest.sizes = undefined;
|
|
1062
|
+
const request = spec.buildRequests([bidRequest], bidderRequest);
|
|
1063
|
+
// Prepare a native bid response with missing w and h
|
|
1064
|
+
const nativeAdm = JSON.stringify({ native: { assets: [{ id: 1, title: { text: 'Test' } }] } });
|
|
1065
|
+
const nativeBid = {
|
|
1066
|
+
id: 'bid-id',
|
|
1067
|
+
impid: request.data.imp[0].id, // match the imp id
|
|
1068
|
+
price: 1.2,
|
|
1069
|
+
adm: nativeAdm,
|
|
1070
|
+
// w and h are intentionally missing
|
|
1071
|
+
adomain: ['example.com'],
|
|
1072
|
+
mtype: 4 // NATIVE
|
|
1073
|
+
};
|
|
1074
|
+
const seatbid = [{ bid: [nativeBid] }];
|
|
1075
|
+
const nativeResponse = { body: { seatbid } };
|
|
1076
|
+
const bidResponses = spec.interpretResponse(nativeResponse, request);
|
|
1077
|
+
expect(bidResponses).to.be.an('array');
|
|
1078
|
+
expect(bidResponses[0]).to.exist;
|
|
1079
|
+
expect(bidResponses[0].native).to.exist;
|
|
1080
|
+
expect(bidResponses[0].width).to.equal(0);
|
|
1081
|
+
expect(bidResponses[0].height).to.equal(0);
|
|
1082
|
+
});
|
|
1083
|
+
|
|
988
1084
|
it('should return response in prebid format', () => {
|
|
989
1085
|
const request = spec.buildRequests(validBidRequests, bidderRequest);
|
|
990
1086
|
const bidResponse = spec.interpretResponse(response, request);
|
|
@@ -1056,7 +1152,7 @@ describe('PubMatic adapter', () => {
|
|
|
1056
1152
|
if (FEATURES.VIDEO) {
|
|
1057
1153
|
describe('VIDEO', () => {
|
|
1058
1154
|
beforeEach(() => {
|
|
1059
|
-
|
|
1155
|
+
const videoBidderRequest = utils.deepClone(bidderRequest);
|
|
1060
1156
|
delete videoBidderRequest.bids[0].mediaTypes.banner;
|
|
1061
1157
|
videoBidderRequest.bids[0].mediaTypes.video = {
|
|
1062
1158
|
skip: 1,
|
|
@@ -1076,6 +1172,9 @@ describe('PubMatic adapter', () => {
|
|
|
1076
1172
|
maxbitrate: 10,
|
|
1077
1173
|
playerSize: [640, 480]
|
|
1078
1174
|
}
|
|
1175
|
+
videoBidderRequest.bids[0].params.outstreamAU = 'outstreamAU';
|
|
1176
|
+
videoBidderRequest.bids[0].params.renderer = 'renderer_test_pubmatic';
|
|
1177
|
+
videoBidderRequest.bids[0].adUnitCode = 'Div1';
|
|
1079
1178
|
});
|
|
1080
1179
|
|
|
1081
1180
|
it('should generate video response', () => {
|
|
@@ -1104,6 +1203,30 @@ describe('PubMatic adapter', () => {
|
|
|
1104
1203
|
expect(bidResponse[0]).to.have.property('playerHeight').to.equal(480);
|
|
1105
1204
|
expect(bidResponse[0]).to.have.property('playerWidth').to.equal(640);
|
|
1106
1205
|
});
|
|
1206
|
+
|
|
1207
|
+
it('should set renderer and rendererCode for outstream video with outstreamAU', () => {
|
|
1208
|
+
const request = spec.buildRequests(validBidRequests, videoBidderRequest);
|
|
1209
|
+
const bidResponse = spec.interpretResponse(videoResponse, request);
|
|
1210
|
+
expect(bidResponse).to.be.an('array');
|
|
1211
|
+
expect(bidResponse[0]).to.be.an('object');
|
|
1212
|
+
expect(bidResponse[0]).to.have.property('renderer');
|
|
1213
|
+
expect(bidResponse[0].renderer).to.be.an('object');
|
|
1214
|
+
expect(bidResponse[0]).to.have.property('rendererCode').to.equal('outstreamAU');
|
|
1215
|
+
});
|
|
1216
|
+
|
|
1217
|
+
it('should set width and height from playerWidth/playerHeight if not present in bid', () => {
|
|
1218
|
+
// Clone and modify the video response to remove w and h
|
|
1219
|
+
const modifiedVideoResponse = utils.deepClone(videoResponse);
|
|
1220
|
+
delete modifiedVideoResponse.body.seatbid[0].bid[0].w;
|
|
1221
|
+
delete modifiedVideoResponse.body.seatbid[0].bid[0].h;
|
|
1222
|
+
// Set up the request as usual
|
|
1223
|
+
const request = spec.buildRequests(validBidRequests, videoBidderRequest);
|
|
1224
|
+
// Interpret the response
|
|
1225
|
+
const bidResponses = spec.interpretResponse(modifiedVideoResponse, request);
|
|
1226
|
+
// playerWidth = 640, playerHeight = 480 from playerSize in the test setup
|
|
1227
|
+
expect(bidResponses[0].width).to.equal(640);
|
|
1228
|
+
expect(bidResponses[0].height).to.equal(480);
|
|
1229
|
+
});
|
|
1107
1230
|
});
|
|
1108
1231
|
}
|
|
1109
1232
|
|
|
@@ -1172,6 +1295,168 @@ describe('PubMatic adapter', () => {
|
|
|
1172
1295
|
});
|
|
1173
1296
|
});
|
|
1174
1297
|
})
|
|
1298
|
+
|
|
1299
|
+
it('should add userIdAsEids to user.ext.eids when present in bidRequest', () => {
|
|
1300
|
+
const bidRequestWithEids = utils.deepClone(validBidRequests[0]);
|
|
1301
|
+
bidRequestWithEids.userIdAsEids = [
|
|
1302
|
+
{
|
|
1303
|
+
source: 'pubmatic',
|
|
1304
|
+
uids: [{ id: 'test-id-123' }]
|
|
1305
|
+
}
|
|
1306
|
+
];
|
|
1307
|
+
// Create a clean bidderRequest without existing eids
|
|
1308
|
+
const cleanBidderRequest = utils.deepClone(bidderRequest);
|
|
1309
|
+
// Ensure user object exists
|
|
1310
|
+
cleanBidderRequest.user = cleanBidderRequest.user || {};
|
|
1311
|
+
cleanBidderRequest.user.ext = cleanBidderRequest.user.ext || {};
|
|
1312
|
+
delete cleanBidderRequest.user.ext.eids;
|
|
1313
|
+
// Also set userIdAsEids on the bidderRequest.bids[0] like MediaKeys test
|
|
1314
|
+
cleanBidderRequest.bids[0].userIdAsEids = bidRequestWithEids.userIdAsEids;
|
|
1315
|
+
const request = spec.buildRequests([bidRequestWithEids], cleanBidderRequest);
|
|
1316
|
+
expect(request.data.user).to.exist;
|
|
1317
|
+
expect(request.data.user.ext).to.exist;
|
|
1318
|
+
expect(request.data.user.ext.eids).to.deep.equal(bidRequestWithEids.userIdAsEids);
|
|
1319
|
+
});
|
|
1320
|
+
it('should not add userIdAsEids when req.user.ext.eids already exists', () => {
|
|
1321
|
+
const bidRequestWithEids = utils.deepClone(validBidRequests[0]);
|
|
1322
|
+
bidRequestWithEids.userIdAsEids = [
|
|
1323
|
+
{
|
|
1324
|
+
source: 'pubmatic',
|
|
1325
|
+
uids: [{ id: 'test-id-123' }]
|
|
1326
|
+
}
|
|
1327
|
+
];
|
|
1328
|
+
// Create a bidderRequest with existing eids
|
|
1329
|
+
const bidderRequestWithExistingEids = utils.deepClone(bidderRequest);
|
|
1330
|
+
// Ensure user object exists and set existing eids
|
|
1331
|
+
bidderRequestWithExistingEids.user = bidderRequestWithExistingEids.user || {};
|
|
1332
|
+
bidderRequestWithExistingEids.user.ext = bidderRequestWithExistingEids.user.ext || {};
|
|
1333
|
+
bidderRequestWithExistingEids.user.ext.eids = [{ source: 'existing', uids: [{ id: 'existing-id' }] }];
|
|
1334
|
+
// Also set userIdAsEids on the bidderRequest.bids[0] like MediaKeys test
|
|
1335
|
+
bidderRequestWithExistingEids.bids[0].userIdAsEids = bidRequestWithEids.userIdAsEids;
|
|
1336
|
+
// Set existing eids in ortb2.user.ext.eids so the converter will merge them
|
|
1337
|
+
// and the adapter will see them as already existing
|
|
1338
|
+
bidderRequestWithExistingEids.ortb2 = bidderRequestWithExistingEids.ortb2 || {};
|
|
1339
|
+
bidderRequestWithExistingEids.ortb2.user = bidderRequestWithExistingEids.ortb2.user || {};
|
|
1340
|
+
bidderRequestWithExistingEids.ortb2.user.ext = bidderRequestWithExistingEids.ortb2.user.ext || {};
|
|
1341
|
+
bidderRequestWithExistingEids.ortb2.user.ext.eids = [{ source: 'existing', uids: [{ id: 'existing-id' }] }];
|
|
1342
|
+
const request = spec.buildRequests([bidRequestWithEids], bidderRequestWithExistingEids);
|
|
1343
|
+
expect(request.data.user).to.exist;
|
|
1344
|
+
expect(request.data.user.ext).to.exist;
|
|
1345
|
+
expect(request.data.user.ext.eids).to.deep.equal(bidderRequestWithExistingEids.ortb2.user.ext.eids);
|
|
1346
|
+
});
|
|
1347
|
+
|
|
1348
|
+
it('should copy geo from device to user when device has geo but user does not', () => {
|
|
1349
|
+
const bidRequestWithDeviceGeo = utils.deepClone(validBidRequests[0]);
|
|
1350
|
+
// Create a clean bidderRequest without existing geo data
|
|
1351
|
+
const cleanBidderRequest = utils.deepClone(bidderRequest);
|
|
1352
|
+
// Ensure user and device objects exist
|
|
1353
|
+
cleanBidderRequest.user = cleanBidderRequest.user || {};
|
|
1354
|
+
cleanBidderRequest.ortb2 = cleanBidderRequest.ortb2 || {};
|
|
1355
|
+
cleanBidderRequest.ortb2.user = cleanBidderRequest.ortb2.user || {};
|
|
1356
|
+
cleanBidderRequest.ortb2.device = cleanBidderRequest.ortb2.device || {};
|
|
1357
|
+
delete cleanBidderRequest.user.geo;
|
|
1358
|
+
delete cleanBidderRequest.ortb2.user.geo;
|
|
1359
|
+
// Set geo data in bidderRequest.ortb2.device.geo so the converter will merge it
|
|
1360
|
+
cleanBidderRequest.ortb2.device.geo = { lat: 40.7128, lon: -74.0060 };
|
|
1361
|
+
const request = spec.buildRequests([bidRequestWithDeviceGeo], cleanBidderRequest);
|
|
1362
|
+
expect(request.data.user).to.exist;
|
|
1363
|
+
expect(request.data.user.geo).to.deep.equal({ lat: 40.7128, lon: -74.0060 });
|
|
1364
|
+
});
|
|
1365
|
+
|
|
1366
|
+
it('should copy geo from user to device when user has geo but device does not', () => {
|
|
1367
|
+
const bidRequestWithUserGeo = utils.deepClone(validBidRequests[0]);
|
|
1368
|
+
// Create a clean bidderRequest without existing geo data
|
|
1369
|
+
const cleanBidderRequest = utils.deepClone(bidderRequest);
|
|
1370
|
+
// Ensure device object exists
|
|
1371
|
+
cleanBidderRequest.device = cleanBidderRequest.device || {};
|
|
1372
|
+
cleanBidderRequest.ortb2 = cleanBidderRequest.ortb2 || {};
|
|
1373
|
+
cleanBidderRequest.ortb2.device = cleanBidderRequest.ortb2.device || {};
|
|
1374
|
+
cleanBidderRequest.ortb2.user = cleanBidderRequest.ortb2.user || {};
|
|
1375
|
+
delete cleanBidderRequest.device.geo;
|
|
1376
|
+
delete cleanBidderRequest.ortb2.device.geo;
|
|
1377
|
+
// Set geo data in bidderRequest.ortb2.user.geo so the converter will merge it
|
|
1378
|
+
cleanBidderRequest.ortb2.user.geo = { lat: 40.7128, lon: -74.0060 };
|
|
1379
|
+
const request = spec.buildRequests([bidRequestWithUserGeo], cleanBidderRequest);
|
|
1380
|
+
expect(request.data.device).to.exist;
|
|
1381
|
+
expect(request.data.device.geo).to.deep.equal({ lat: 40.7128, lon: -74.0060 });
|
|
1382
|
+
});
|
|
1383
|
+
|
|
1384
|
+
it('should update site.page with kadpageurl when present', () => {
|
|
1385
|
+
const bidRequestWithKadPageUrl = utils.deepClone(validBidRequests[0]);
|
|
1386
|
+
bidRequestWithKadPageUrl.params.kadpageurl = 'https://example.com/page';
|
|
1387
|
+
const request = spec.buildRequests([bidRequestWithKadPageUrl], bidderRequest);
|
|
1388
|
+
expect(request.data.site).to.exist;
|
|
1389
|
+
expect(request.data.site.page).to.equal('https://example.com/page');
|
|
1390
|
+
});
|
|
1391
|
+
|
|
1392
|
+
it('should set site.publisher.id from pubId', () => {
|
|
1393
|
+
// Ensure site.publisher structure exists in bidderRequest.ortb2
|
|
1394
|
+
const bidderRequestWithPublisher = utils.deepClone(bidderRequest);
|
|
1395
|
+
bidderRequestWithPublisher.ortb2 = bidderRequestWithPublisher.ortb2 || {};
|
|
1396
|
+
bidderRequestWithPublisher.ortb2.site = bidderRequestWithPublisher.ortb2.site || {};
|
|
1397
|
+
bidderRequestWithPublisher.ortb2.site.publisher = bidderRequestWithPublisher.ortb2.site.publisher || {};
|
|
1398
|
+
const request = spec.buildRequests(validBidRequests, bidderRequestWithPublisher);
|
|
1399
|
+
expect(request.data.site).to.exist;
|
|
1400
|
+
expect(request.data.site.publisher).to.exist;
|
|
1401
|
+
expect(request.data.site.publisher.id).to.equal('5670'); // pubId from params
|
|
1402
|
+
});
|
|
1403
|
+
|
|
1404
|
+
it('should set site.ref from refURL when not already present', () => {
|
|
1405
|
+
const request = spec.buildRequests(validBidRequests, bidderRequest);
|
|
1406
|
+
expect(request.data.site).to.exist;
|
|
1407
|
+
// Check if site.ref exists (it might be set to empty string or undefined)
|
|
1408
|
+
if (request.data.site.ref !== undefined) {
|
|
1409
|
+
expect(request.data.site.ref).to.exist;
|
|
1410
|
+
}
|
|
1411
|
+
});
|
|
1412
|
+
|
|
1413
|
+
it('should build a basic request successfully', () => {
|
|
1414
|
+
const request = spec.buildRequests(validBidRequests, bidderRequest);
|
|
1415
|
+
expect(request.data).to.exist;
|
|
1416
|
+
expect(request.data.imp).to.be.an('array');
|
|
1417
|
+
expect(request.data.imp.length).to.be.greaterThan(0);
|
|
1418
|
+
});
|
|
1419
|
+
|
|
1420
|
+
it('should set floor values correctly for multi-format requests using getFloor', () => {
|
|
1421
|
+
// Start with a valid bid
|
|
1422
|
+
const testBid = utils.deepClone(validBidRequests[0]);
|
|
1423
|
+
testBid.mediaTypes = {
|
|
1424
|
+
banner: {
|
|
1425
|
+
sizes: [[300, 250], [728, 90]],
|
|
1426
|
+
format: [{ w: 300, h: 250 }, { w: 728, h: 90 }]
|
|
1427
|
+
},
|
|
1428
|
+
video: {},
|
|
1429
|
+
native: {}
|
|
1430
|
+
};
|
|
1431
|
+
testBid.getFloor = ({ currency, mediaType, size }) => {
|
|
1432
|
+
if (mediaType === 'banner') return { currency: 'AUD', floor: 2.5 };
|
|
1433
|
+
if (mediaType === 'video') return { currency: 'AUD', floor: 1.5 };
|
|
1434
|
+
if (mediaType === 'native') return { currency: 'AUD', floor: 1.0 };
|
|
1435
|
+
return { currency: 'AUD', floor: 0 };
|
|
1436
|
+
};
|
|
1437
|
+
const testBidderRequest = {
|
|
1438
|
+
bids: [testBid],
|
|
1439
|
+
auctionId: 'test-auction',
|
|
1440
|
+
bidderCode: 'pubmatic',
|
|
1441
|
+
refererInfo: { page: 'https://example.com', ref: '' },
|
|
1442
|
+
ortb2: { device: { w: 1200, h: 1800 }, site: { domain: 'example.com', page: 'https://example.com' } },
|
|
1443
|
+
timeout: 2000
|
|
1444
|
+
};
|
|
1445
|
+
const request = spec.buildRequests([testBid], testBidderRequest);
|
|
1446
|
+
expect(request).to.exist;
|
|
1447
|
+
const builtImp = request.data.imp[0];
|
|
1448
|
+
if (builtImp.banner && builtImp.banner.ext) {
|
|
1449
|
+
expect(builtImp.banner.ext).to.deep.equal({ bidfloor: 1, bidfloorcur: 'AUD' });
|
|
1450
|
+
}
|
|
1451
|
+
if (builtImp.video && builtImp.video.ext) {
|
|
1452
|
+
expect(builtImp.video.ext).to.deep.equal({ bidfloor: 1, bidfloorcur: 'AUD' });
|
|
1453
|
+
}
|
|
1454
|
+
if (builtImp.native && builtImp.native.ext) {
|
|
1455
|
+
expect(builtImp.native.ext).to.deep.equal({ bidfloor: 1, bidfloorcur: 'AUD' });
|
|
1456
|
+
}
|
|
1457
|
+
// The impression-level bidfloor should match the banner floor (2.5)
|
|
1458
|
+
expect(builtImp.bidfloor).to.equal(2.5);
|
|
1459
|
+
});
|
|
1175
1460
|
})
|
|
1176
1461
|
|
|
1177
1462
|
describe('addViewabilityToImp', () => {
|