prebid.js 5.17.0 → 6.0.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.
- package/.babelrc.js +3 -6
- package/README.md +3 -1
- package/browsers.json +1 -8
- package/integrationExamples/gpt/akamaidap_segments_example.html +132 -0
- package/modules/.submodules.json +1 -0
- package/modules/adfBidAdapter.js +21 -16
- package/modules/adgenerationBidAdapter.js +28 -4
- package/modules/adkernelBidAdapter.js +2 -1
- package/modules/admixerBidAdapter.js +11 -0
- package/modules/adtelligentBidAdapter.js +2 -1
- package/modules/airgridRtdProvider.js +1 -1
- package/modules/akamaiDapRtdProvider.js +474 -0
- package/modules/akamaiDapRtdProvider.md +47 -0
- package/modules/aolBidAdapter.js +2 -1
- package/modules/appnexusBidAdapter.js +5 -3
- package/modules/atsAnalyticsAdapter.js +67 -46
- package/modules/atsAnalyticsAdapter.md +1 -0
- package/modules/betweenBidAdapter.js +20 -3
- package/modules/bliinkBidAdapter.js +58 -32
- package/modules/bliinkBidAdapter.md +29 -6
- package/modules/browsiRtdProvider.js +106 -18
- package/modules/cleanioRtdProvider.js +192 -0
- package/modules/cleanioRtdProvider.md +59 -0
- package/modules/codefuelBidAdapter.js +183 -0
- package/modules/codefuelBidAdapter.md +111 -0
- package/modules/connectIdSystem.js +104 -0
- package/modules/connectIdSystem.md +33 -0
- package/modules/cwireBidAdapter.js +272 -0
- package/modules/cwireBidAdapter.md +43 -0
- package/modules/deepintentBidAdapter.js +106 -9
- package/modules/deepintentBidAdapter.md +36 -1
- package/modules/deltaprojectsBidAdapter.js +252 -0
- package/modules/deltaprojectsBidAdapter.md +32 -0
- package/modules/dgkeywordRtdProvider.js +0 -1
- package/modules/engageyaBidAdapter.js +157 -0
- package/modules/gridBidAdapter.js +1 -0
- package/modules/gumgumBidAdapter.js +8 -0
- package/modules/inskinBidAdapter.js +7 -3
- package/modules/ixBidAdapter.js +8 -1
- package/modules/jixieBidAdapter.js +8 -2
- package/modules/justpremiumBidAdapter.js +6 -1
- package/modules/limelightDigitalBidAdapter.js +22 -2
- package/modules/livewrappedAnalyticsAdapter.js +53 -3
- package/modules/mediakeysBidAdapter.js +2 -1
- package/modules/multibid/index.js +3 -3
- package/modules/nativoBidAdapter.js +6 -2
- package/modules/nextMillenniumBidAdapter.js +12 -3
- package/modules/oguryBidAdapter.js +36 -7
- package/modules/openxBidAdapter.js +34 -22
- package/modules/operaadsBidAdapter.js +21 -1
- package/modules/otmBidAdapter.js +146 -0
- package/modules/otmBidAdapter.md +27 -26
- package/modules/outbrainBidAdapter.js +5 -0
- package/modules/pixfutureBidAdapter.js +24 -4
- package/modules/pixfutureBidAdapter.md +127 -0
- package/modules/playwireBidAdapter.md +61 -0
- package/modules/prebidServerBidAdapter/index.js +1 -1
- package/modules/proxistoreBidAdapter.js +4 -6
- package/modules/publinkIdSystem.js +11 -6
- package/modules/pubmaticBidAdapter.js +9 -0
- package/modules/pubmaticBidAdapter.md +1 -1
- package/modules/rtdModule/index.js +2 -2
- package/modules/sonobiBidAdapter.js +7 -0
- package/modules/sortableBidAdapter.js +1 -0
- package/modules/talkadsBidAdapter.js +129 -0
- package/modules/talkadsBidAdapter.md +60 -0
- package/modules/teadsBidAdapter.js +3 -0
- package/modules/tripleliftBidAdapter.js +22 -5
- package/modules/trustxBidAdapter.js +8 -6
- package/modules/undertoneBidAdapter.js +9 -5
- package/modules/undertoneBidAdapter.md +5 -1
- package/modules/unicornBidAdapter.js +3 -3
- package/modules/userId/eids.js +18 -0
- package/modules/userId/eids.md +7 -0
- package/modules/userId/userId.md +12 -0
- package/modules/ventesBidAdapter.js +370 -0
- package/modules/ventesBidAdapter.md +94 -0
- package/modules/videobyteBidAdapter.js +13 -6
- package/modules/videobyteBidAdapter.md +49 -0
- package/modules/visxBidAdapter.js +15 -22
- package/modules/yahoosspBidAdapter.js +637 -0
- package/modules/yahoosspBidAdapter.md +795 -0
- package/modules/yieldlabBidAdapter.js +48 -3
- package/modules/yieldlabBidAdapter.md +16 -1
- package/modules/yieldmoSyntheticInventoryModule.js +46 -0
- package/modules/yieldmoSyntheticInventoryModule.md +68 -0
- package/package.json +1 -1
- package/src/adapterManager.js +5 -0
- package/src/adapters/bidderFactory.js +4 -3
- package/src/auction.js +11 -11
- package/src/constants.json +1 -0
- package/src/secureCreatives.js +6 -7
- package/src/targeting.js +11 -9
- package/test/spec/modules/adfBidAdapter_spec.js +83 -29
- package/test/spec/modules/adgenerationBidAdapter_spec.js +121 -50
- package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
- package/test/spec/modules/akamaiDapRtdProvider_spec.js +246 -0
- package/test/spec/modules/appnexusBidAdapter_spec.js +2 -1
- package/test/spec/modules/atsAnalyticsAdapter_spec.js +42 -9
- package/test/spec/modules/betweenBidAdapter_spec.js +41 -0
- package/test/spec/modules/bliinkBidAdapter_spec.js +87 -36
- package/test/spec/modules/browsiRtdProvider_spec.js +62 -7
- package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
- package/test/spec/modules/codefuelBidAdapter_spec.js +316 -0
- package/test/spec/modules/connectIdSystem_spec.js +189 -0
- package/test/spec/modules/cwireBidAdapter_spec.js +246 -0
- package/test/spec/modules/deepintentBidAdapter_spec.js +153 -3
- package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
- package/test/spec/modules/engageyaBidAdapter_spec.js +286 -0
- package/test/spec/modules/gumgumBidAdapter_spec.js +5 -1
- package/test/spec/modules/ixBidAdapter_spec.js +13 -3
- package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
- package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
- package/test/spec/modules/limelightDigitalBidAdapter_spec.js +155 -1
- package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +67 -12
- package/test/spec/modules/multibid_spec.js +31 -31
- package/test/spec/modules/nextMillenniumBidAdapter_spec.js +13 -1
- package/test/spec/modules/oguryBidAdapter_spec.js +125 -37
- package/test/spec/modules/openxBidAdapter_spec.js +85 -13
- package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
- package/test/spec/modules/otmBidAdapter_spec.js +67 -0
- package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
- package/test/spec/modules/publinkIdSystem_spec.js +6 -6
- package/test/spec/modules/pubmaticBidAdapter_spec.js +39 -1
- package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
- package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
- package/test/spec/modules/talkadsBidAdapter_spec.js +231 -0
- package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
- package/test/spec/modules/tripleliftBidAdapter_spec.js +128 -0
- package/test/spec/modules/trustxBidAdapter_spec.js +3 -3
- package/test/spec/modules/undertoneBidAdapter_spec.js +52 -0
- package/test/spec/modules/unicornBidAdapter_spec.js +4 -4
- package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
- package/test/spec/modules/videobyteBidAdapter_spec.js +2 -2
- package/test/spec/modules/visxBidAdapter_spec.js +48 -4
- package/test/spec/modules/yahoosspBidAdapter_spec.js +1332 -0
- package/test/spec/modules/yieldlabBidAdapter_spec.js +65 -1
- package/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js +89 -0
- package/test/spec/unit/core/adapterManager_spec.js +32 -0
- package/test/spec/unit/core/bidderFactory_spec.js +61 -1
- package/test/spec/unit/pbjs_api_spec.js +37 -2
- package/test/spec/unit/secureCreatives_spec.js +54 -25
- package/wdio.conf.js +1 -1
- package/modules/turktelekomBidAdapter.md +0 -49
- package/yarn.lock +0 -13122
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as utils from '../../../src/utils.js';
|
|
2
|
+
import * as hook from '../../../src/hook.js'
|
|
3
|
+
|
|
4
|
+
import { __TEST__ } from '../../../modules/cleanioRtdProvider.js';
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
readConfig,
|
|
8
|
+
ConfigError,
|
|
9
|
+
pageInitStepPreloadScript,
|
|
10
|
+
pageInitStepProtectPage,
|
|
11
|
+
bidWrapStepAugmentHtml,
|
|
12
|
+
bidWrapStepProtectByWrapping,
|
|
13
|
+
beforeInit,
|
|
14
|
+
} = __TEST__;
|
|
15
|
+
|
|
16
|
+
sinon.assert.expose(chai.assert, { prefix: 'sinon' });
|
|
17
|
+
|
|
18
|
+
const fakeScriptURL = 'https://example.com/script.js';
|
|
19
|
+
|
|
20
|
+
function makeFakeBidResponse() {
|
|
21
|
+
return {
|
|
22
|
+
ad: '<body>hello ad</body>',
|
|
23
|
+
bidderCode: 'BIDDER',
|
|
24
|
+
creativeId: 'CREATIVE',
|
|
25
|
+
cpm: 1.23,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('clean.io RTD module', function () {
|
|
30
|
+
describe('readConfig()', function() {
|
|
31
|
+
it('should throw ConfigError on invalid configurations', function() {
|
|
32
|
+
expect(() => readConfig({})).to.throw(ConfigError);
|
|
33
|
+
expect(() => readConfig({ params: {} })).to.throw(ConfigError);
|
|
34
|
+
expect(() => readConfig({ params: { protectionMode: 'bids' } })).to.throw(ConfigError);
|
|
35
|
+
expect(() => readConfig({ params: { cdnUrl: 'abc' } })).to.throw(ConfigError);
|
|
36
|
+
expect(() => readConfig({ params: { cdnUrl: 'abc', protectionMode: 'bids' } })).to.throw(ConfigError);
|
|
37
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: '123' } })).to.throw(ConfigError);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should accept valid configurations', function() {
|
|
41
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'full' } })).to.not.throw();
|
|
42
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids' } })).to.not.throw();
|
|
43
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids-nowait' } })).to.not.throw();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('Module initialization step', function() {
|
|
48
|
+
let insertElementStub;
|
|
49
|
+
beforeEach(function() {
|
|
50
|
+
insertElementStub = sinon.stub(utils, 'insertElement');
|
|
51
|
+
});
|
|
52
|
+
afterEach(function() {
|
|
53
|
+
utils.insertElement.restore();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('pageInitStepPreloadScript() should insert link/preload element', function() {
|
|
57
|
+
pageInitStepPreloadScript(fakeScriptURL);
|
|
58
|
+
|
|
59
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
60
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK'));
|
|
61
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.rel === 'preload'));
|
|
62
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.as === 'script'));
|
|
63
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.href === fakeScriptURL));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('pageInitStepProtectPage() should insert script element', function() {
|
|
67
|
+
pageInitStepProtectPage(fakeScriptURL);
|
|
68
|
+
|
|
69
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
70
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'SCRIPT'));
|
|
71
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.type === 'text/javascript'));
|
|
72
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.src === fakeScriptURL));
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
function ensurePrependToBidResponse(fakeBidResponse) {
|
|
77
|
+
expect(fakeBidResponse).to.have.own.property('ad').which.is.a('string');
|
|
78
|
+
expect(fakeBidResponse.ad).to.contain('<!-- pbad://creativeId=CREATIVE&bidderCode=BIDDER&cpm=1.23 -->');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function ensureWrapBidResponse(fakeBidResponse, scriptUrl) {
|
|
82
|
+
expect(fakeBidResponse).to.have.own.property('ad').which.is.a('string');
|
|
83
|
+
expect(fakeBidResponse.ad).to.contain(`src="${scriptUrl}"`);
|
|
84
|
+
expect(fakeBidResponse.ad).to.contain('agent.put(ad)');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
describe('Bid processing step', function() {
|
|
88
|
+
it('bidWrapStepAugmentHtml() should prepend bid-specific information in a comment', function() {
|
|
89
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
90
|
+
bidWrapStepAugmentHtml(fakeBidResponse);
|
|
91
|
+
ensurePrependToBidResponse(fakeBidResponse);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('bidWrapStepProtectByWrapping() should wrap payload into a script tag', function() {
|
|
95
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
96
|
+
bidWrapStepProtectByWrapping(fakeScriptURL, 0, fakeBidResponse);
|
|
97
|
+
ensureWrapBidResponse(fakeBidResponse, fakeScriptURL);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('Sumbodule execution', function() {
|
|
102
|
+
let submoduleStub;
|
|
103
|
+
let insertElementStub;
|
|
104
|
+
beforeEach(function () {
|
|
105
|
+
submoduleStub = sinon.stub(hook, 'submodule');
|
|
106
|
+
insertElementStub = sinon.stub(utils, 'insertElement');
|
|
107
|
+
});
|
|
108
|
+
afterEach(function () {
|
|
109
|
+
utils.insertElement.restore();
|
|
110
|
+
submoduleStub.restore();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
function getModule() {
|
|
114
|
+
beforeInit();
|
|
115
|
+
|
|
116
|
+
expect(submoduleStub.calledOnceWith('realTimeData')).to.equal(true);
|
|
117
|
+
|
|
118
|
+
const registeredSubmoduleDefinition = submoduleStub.getCall(0).args[1];
|
|
119
|
+
expect(registeredSubmoduleDefinition).to.be.an('object');
|
|
120
|
+
expect(registeredSubmoduleDefinition).to.have.own.property('name', 'clean.io');
|
|
121
|
+
expect(registeredSubmoduleDefinition).to.have.own.property('init').that.is.a('function');
|
|
122
|
+
expect(registeredSubmoduleDefinition).to.have.own.property('onBidResponseEvent').that.is.a('function');
|
|
123
|
+
|
|
124
|
+
return registeredSubmoduleDefinition;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
it('should register clean.io RTD submodule provider', function () {
|
|
128
|
+
getModule();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should refuse initialization with incorrect parameters', function () {
|
|
132
|
+
const { init } = getModule();
|
|
133
|
+
expect(init({ params: { cdnUrl: 'abc', protectionMode: 'full' } }, {})).to.equal(false); // too short distribution name
|
|
134
|
+
sinon.assert.notCalled(insertElementStub);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should iniitalize in full (page) protection mode', function () {
|
|
138
|
+
const { init, onBidResponseEvent } = getModule();
|
|
139
|
+
expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'full' } }, {})).to.equal(true);
|
|
140
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
141
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'SCRIPT'));
|
|
142
|
+
|
|
143
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
144
|
+
onBidResponseEvent(fakeBidResponse, {}, {});
|
|
145
|
+
ensurePrependToBidResponse(fakeBidResponse);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should iniitalize in bids (frame) protection mode', function () {
|
|
149
|
+
const { init, onBidResponseEvent } = getModule();
|
|
150
|
+
expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids' } }, {})).to.equal(true);
|
|
151
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
152
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK'));
|
|
153
|
+
|
|
154
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
155
|
+
onBidResponseEvent(fakeBidResponse, {}, {});
|
|
156
|
+
ensureWrapBidResponse(fakeBidResponse, 'https://abc1234567890.cloudfront.net/script.js');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should respect preload status in bids-nowait protection mode', function () {
|
|
160
|
+
const { init, onBidResponseEvent } = getModule();
|
|
161
|
+
expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids-nowait' } }, {})).to.equal(true);
|
|
162
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
163
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK'));
|
|
164
|
+
const preloadLink = insertElementStub.getCall(0).args[0];
|
|
165
|
+
expect(preloadLink).to.have.property('onload').which.is.a('function');
|
|
166
|
+
expect(preloadLink).to.have.property('onerror').which.is.a('function');
|
|
167
|
+
|
|
168
|
+
const fakeBidResponse1 = makeFakeBidResponse();
|
|
169
|
+
onBidResponseEvent(fakeBidResponse1, {}, {});
|
|
170
|
+
ensurePrependToBidResponse(fakeBidResponse1);
|
|
171
|
+
|
|
172
|
+
// Simulate successful preloading
|
|
173
|
+
preloadLink.onload();
|
|
174
|
+
|
|
175
|
+
const fakeBidResponse2 = makeFakeBidResponse();
|
|
176
|
+
onBidResponseEvent(fakeBidResponse2, {}, {});
|
|
177
|
+
ensureWrapBidResponse(fakeBidResponse2, 'https://abc1234567890.cloudfront.net/script.js');
|
|
178
|
+
|
|
179
|
+
// Simulate error
|
|
180
|
+
preloadLink.onerror();
|
|
181
|
+
|
|
182
|
+
// Now we should fallback to just prepending
|
|
183
|
+
const fakeBidResponse3 = makeFakeBidResponse();
|
|
184
|
+
onBidResponseEvent(fakeBidResponse3, {}, {});
|
|
185
|
+
ensurePrependToBidResponse(fakeBidResponse3);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {spec} from 'modules/codefuelBidAdapter.js';
|
|
3
|
+
import {config} from 'src/config.js';
|
|
4
|
+
import {server} from 'test/mocks/xhr';
|
|
5
|
+
|
|
6
|
+
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4515.159 Safari/537.36';
|
|
7
|
+
const DEFAULT_USER_AGENT = window.navigator.userAgent;
|
|
8
|
+
const setUADefault = () => { window.navigator.__defineGetter__('userAgent', function () { return DEFAULT_USER_AGENT }) };
|
|
9
|
+
const setUAMock = () => { window.navigator.__defineGetter__('userAgent', function () { return USER_AGENT }) };
|
|
10
|
+
|
|
11
|
+
describe('Codefuel Adapter', function () {
|
|
12
|
+
describe('Bid request and response', function () {
|
|
13
|
+
const commonBidRequest = {
|
|
14
|
+
bidder: 'codefuel',
|
|
15
|
+
params: {
|
|
16
|
+
publisher: {
|
|
17
|
+
id: 'publisher-id'
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
bidId: '2d6815a92ba1ba',
|
|
21
|
+
auctionId: '12043683-3254-4f74-8934-f941b085579e',
|
|
22
|
+
}
|
|
23
|
+
const nativeBidRequestParams = {
|
|
24
|
+
nativeParams: {
|
|
25
|
+
image: {
|
|
26
|
+
required: true,
|
|
27
|
+
sizes: [
|
|
28
|
+
120,
|
|
29
|
+
100
|
|
30
|
+
],
|
|
31
|
+
sendId: true
|
|
32
|
+
},
|
|
33
|
+
title: {
|
|
34
|
+
required: true,
|
|
35
|
+
sendId: true
|
|
36
|
+
},
|
|
37
|
+
sponsoredBy: {
|
|
38
|
+
required: false
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const displayBidRequestParams = {
|
|
44
|
+
sizes: [
|
|
45
|
+
[
|
|
46
|
+
300,
|
|
47
|
+
250
|
|
48
|
+
]
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe('isBidRequestValid', function () {
|
|
53
|
+
before(() => {
|
|
54
|
+
config.setConfig({
|
|
55
|
+
codefuel: {
|
|
56
|
+
bidderUrl: 'https://bidder-url.com',
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
after(() => {
|
|
62
|
+
config.resetConfig()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('should fail when bid is invalid', function () {
|
|
66
|
+
const bid = {
|
|
67
|
+
bidder: 'codefuel',
|
|
68
|
+
params: {
|
|
69
|
+
publisher: {
|
|
70
|
+
id: 'publisher-id',
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
expect(spec.isBidRequestValid(bid)).to.equal(false)
|
|
75
|
+
})
|
|
76
|
+
it('should not succeed when bid contains native params', function () {
|
|
77
|
+
const bid = {
|
|
78
|
+
bidder: 'codefuel',
|
|
79
|
+
params: {
|
|
80
|
+
publisher: {
|
|
81
|
+
id: 'publisher-id',
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
...nativeBidRequestParams,
|
|
85
|
+
}
|
|
86
|
+
expect(spec.isBidRequestValid(bid)).to.equal(false)
|
|
87
|
+
})
|
|
88
|
+
it('should not succeed when bid contains only sizes', function () {
|
|
89
|
+
const bid = {
|
|
90
|
+
bidder: 'codefuel',
|
|
91
|
+
params: {
|
|
92
|
+
publisher: {
|
|
93
|
+
id: 'publisher-id',
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
...displayBidRequestParams,
|
|
97
|
+
}
|
|
98
|
+
expect(spec.isBidRequestValid(bid)).to.equal(false)
|
|
99
|
+
})
|
|
100
|
+
it('should fail if publisher id is not set', function () {
|
|
101
|
+
const bid = {
|
|
102
|
+
bidder: 'codefuel',
|
|
103
|
+
...nativeBidRequestParams,
|
|
104
|
+
}
|
|
105
|
+
expect(spec.isBidRequestValid(bid)).to.equal(false)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('should fail if bidder url is not set', function () {
|
|
109
|
+
const bid = {
|
|
110
|
+
bidder: 'codefuel',
|
|
111
|
+
params: {
|
|
112
|
+
publisher: {
|
|
113
|
+
id: 'publisher-id',
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
...nativeBidRequestParams,
|
|
117
|
+
}
|
|
118
|
+
config.resetConfig()
|
|
119
|
+
expect(spec.isBidRequestValid(bid)).to.equal(false)
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
describe('buildRequests', function () {
|
|
124
|
+
before(() => {
|
|
125
|
+
setUAMock()
|
|
126
|
+
config.setConfig({
|
|
127
|
+
codefuel: {
|
|
128
|
+
bidderUrl: 'https://bidder-url.com',
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
})
|
|
133
|
+
after(() => {
|
|
134
|
+
config.resetConfig()
|
|
135
|
+
setUADefault()
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const commonBidderRequest = {
|
|
139
|
+
timeout: 500,
|
|
140
|
+
auctionId: '12043683-3254-4f74-8934-f941b085579e',
|
|
141
|
+
refererInfo: {
|
|
142
|
+
referer: 'https://example.com/',
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
it('should build display request', function () {
|
|
147
|
+
const bidRequest = {
|
|
148
|
+
...commonBidRequest,
|
|
149
|
+
...displayBidRequestParams,
|
|
150
|
+
}
|
|
151
|
+
const expectedData = {
|
|
152
|
+
cur: [
|
|
153
|
+
'USD'
|
|
154
|
+
],
|
|
155
|
+
device: {
|
|
156
|
+
devicetype: 2,
|
|
157
|
+
ua: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4515.159 Safari/537.36'
|
|
158
|
+
},
|
|
159
|
+
id: '12043683-3254-4f74-8934-f941b085579e',
|
|
160
|
+
imp: [
|
|
161
|
+
{
|
|
162
|
+
banner: {
|
|
163
|
+
format: [
|
|
164
|
+
{
|
|
165
|
+
h: 250,
|
|
166
|
+
w: 300
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
id: '1'
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
site: {
|
|
174
|
+
domain: 'example.com',
|
|
175
|
+
page: 'https://example.com/',
|
|
176
|
+
publisher: {
|
|
177
|
+
id: 'publisher-id'
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
source: {
|
|
181
|
+
fd: 1
|
|
182
|
+
},
|
|
183
|
+
tmax: 500
|
|
184
|
+
}
|
|
185
|
+
const res = spec.buildRequests([bidRequest], commonBidderRequest)
|
|
186
|
+
expect(res.url).to.equal('https://bidder-url.com')
|
|
187
|
+
expect(res.data).to.deep.equal(expectedData)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
it('should pass bidder timeout', function () {
|
|
191
|
+
const bidRequest = {
|
|
192
|
+
...commonBidRequest,
|
|
193
|
+
}
|
|
194
|
+
const bidderRequest = {
|
|
195
|
+
...commonBidderRequest,
|
|
196
|
+
timeout: 500
|
|
197
|
+
}
|
|
198
|
+
const res = spec.buildRequests([bidRequest], bidderRequest)
|
|
199
|
+
const resData = res.data
|
|
200
|
+
expect(resData.tmax).to.equal(500)
|
|
201
|
+
});
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
describe('interpretResponse', function () {
|
|
205
|
+
it('should return empty array if no valid bids', function () {
|
|
206
|
+
const res = spec.interpretResponse({}, [])
|
|
207
|
+
expect(res).to.be.an('array').that.is.empty
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should interpret display response', function () {
|
|
211
|
+
const serverResponse = {
|
|
212
|
+
body: {
|
|
213
|
+
id: '6b2eedc8-8ff5-46ef-adcf-e701b508943e',
|
|
214
|
+
seatbid: [
|
|
215
|
+
{
|
|
216
|
+
bid: [
|
|
217
|
+
{
|
|
218
|
+
id: 'd90fe7fa-28d7-11eb-8ce4-462a842a7cf9',
|
|
219
|
+
impid: '1',
|
|
220
|
+
price: 1.1,
|
|
221
|
+
nurl: 'http://example.com/win/${AUCTION_PRICE}',
|
|
222
|
+
adm: '<div>ad</div>',
|
|
223
|
+
adomain: [
|
|
224
|
+
'example.com'
|
|
225
|
+
],
|
|
226
|
+
cid: '3865084',
|
|
227
|
+
crid: '29998660',
|
|
228
|
+
cat: [
|
|
229
|
+
'IAB10-2'
|
|
230
|
+
],
|
|
231
|
+
w: 300,
|
|
232
|
+
h: 250
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
seat: 'acc-6536'
|
|
236
|
+
}
|
|
237
|
+
],
|
|
238
|
+
bidid: 'd90fe7fa-28d7-11eb-8ce4-13d94bfa26f9',
|
|
239
|
+
cur: 'USD'
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const request = {
|
|
243
|
+
bids: [
|
|
244
|
+
{
|
|
245
|
+
...commonBidRequest,
|
|
246
|
+
...displayBidRequestParams
|
|
247
|
+
}
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
const expectedRes = [
|
|
251
|
+
{
|
|
252
|
+
requestId: request.bids[0].bidId,
|
|
253
|
+
cpm: 1.1,
|
|
254
|
+
creativeId: '29998660',
|
|
255
|
+
ttl: 360,
|
|
256
|
+
netRevenue: true,
|
|
257
|
+
currency: 'USD',
|
|
258
|
+
mediaType: 'banner',
|
|
259
|
+
ad: '<div>ad</div>',
|
|
260
|
+
width: 300,
|
|
261
|
+
height: 250,
|
|
262
|
+
meta: {'advertiserDomains': []}
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
|
|
266
|
+
const res = spec.interpretResponse(serverResponse, request)
|
|
267
|
+
expect(res).to.deep.equal(expectedRes)
|
|
268
|
+
});
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
describe('getUserSyncs', function () {
|
|
273
|
+
const usersyncUrl = 'https://usersync-url.com';
|
|
274
|
+
beforeEach(() => {
|
|
275
|
+
config.setConfig({
|
|
276
|
+
codefuel: {
|
|
277
|
+
usersyncUrl: usersyncUrl,
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
)
|
|
281
|
+
})
|
|
282
|
+
after(() => {
|
|
283
|
+
config.resetConfig()
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it('should not return user sync if pixel enabled with codefuel config', function () {
|
|
287
|
+
const ret = spec.getUserSyncs({pixelEnabled: true})
|
|
288
|
+
expect(ret).to.be.an('array').that.is.empty
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
it('should not return user sync if pixel disabled', function () {
|
|
292
|
+
const ret = spec.getUserSyncs({pixelEnabled: false})
|
|
293
|
+
expect(ret).to.be.an('array').that.is.empty
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
it('should not return user sync if url is not set', function () {
|
|
297
|
+
config.resetConfig()
|
|
298
|
+
const ret = spec.getUserSyncs({pixelEnabled: true})
|
|
299
|
+
expect(ret).to.be.an('array').that.is.empty
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
it('should not pass GDPR consent', function() {
|
|
303
|
+
expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, undefined)).to.to.be.an('array').that.is.empty
|
|
304
|
+
expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: false, consentString: 'foo'}, undefined)).to.be.an('array').that.is.empty
|
|
305
|
+
expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: undefined}, undefined)).to.be.an('array').that.is.empty
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should not pass US consent', function() {
|
|
309
|
+
expect(spec.getUserSyncs({ pixelEnabled: true }, {}, undefined, '1NYN')).to.be.an('array').that.is.empty
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('should pass GDPR and US consent', function() {
|
|
313
|
+
expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, '1NYN')).to.be.an('array').that.is.empty
|
|
314
|
+
});
|
|
315
|
+
})
|
|
316
|
+
})
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {parseQS} from 'src/utils.js';
|
|
3
|
+
import {connectIdSubmodule} from 'modules/connectIdSystem.js';
|
|
4
|
+
|
|
5
|
+
describe('Yahoo ConnectID Submodule', () => {
|
|
6
|
+
const HASHED_EMAIL = '6bda6f2fa268bf0438b5423a9861a2cedaa5dec163c03f743cfe05c08a8397b2';
|
|
7
|
+
const PIXEL_ID = '1234';
|
|
8
|
+
const PROD_ENDPOINT = `https://ups.analytics.yahoo.com/ups/${PIXEL_ID}/fed`;
|
|
9
|
+
const OVERRIDE_ENDPOINT = 'https://foo/bar';
|
|
10
|
+
|
|
11
|
+
it('should have the correct module name declared', () => {
|
|
12
|
+
expect(connectIdSubmodule.name).to.equal('connectId');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should have the correct TCFv2 Vendor ID declared', () => {
|
|
16
|
+
expect(connectIdSubmodule.gvlid).to.equal(25);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('getId()', () => {
|
|
20
|
+
let ajaxStub;
|
|
21
|
+
let getAjaxFnStub;
|
|
22
|
+
let consentData;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
ajaxStub = sinon.stub();
|
|
25
|
+
getAjaxFnStub = sinon.stub(connectIdSubmodule, 'getAjaxFn');
|
|
26
|
+
getAjaxFnStub.returns(ajaxStub);
|
|
27
|
+
|
|
28
|
+
consentData = {
|
|
29
|
+
gdpr: {
|
|
30
|
+
gdprApplies: 1,
|
|
31
|
+
consentString: 'GDPR_CONSENT_STRING'
|
|
32
|
+
},
|
|
33
|
+
uspConsent: 'USP_CONSENT_STRING'
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
getAjaxFnStub.restore();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
function invokeGetIdAPI(configParams, consentData) {
|
|
42
|
+
let result = connectIdSubmodule.getId({
|
|
43
|
+
params: configParams
|
|
44
|
+
}, consentData);
|
|
45
|
+
if (typeof result === 'object') {
|
|
46
|
+
result.callback(sinon.stub());
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
it('returns undefined if he and pixelId params are not passed', () => {
|
|
52
|
+
expect(invokeGetIdAPI({}, consentData)).to.be.undefined;
|
|
53
|
+
expect(ajaxStub.callCount).to.equal(0);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('returns undefined if the pixelId param is not passed', () => {
|
|
57
|
+
expect(invokeGetIdAPI({
|
|
58
|
+
he: HASHED_EMAIL
|
|
59
|
+
}, consentData)).to.be.undefined;
|
|
60
|
+
expect(ajaxStub.callCount).to.equal(0);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('returns undefined if the he param is not passed', () => {
|
|
64
|
+
expect(invokeGetIdAPI({
|
|
65
|
+
pixelId: PIXEL_ID
|
|
66
|
+
}, consentData)).to.be.undefined;
|
|
67
|
+
expect(ajaxStub.callCount).to.equal(0);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('returns an object with the callback function if the correct params are passed', () => {
|
|
71
|
+
let result = invokeGetIdAPI({
|
|
72
|
+
he: HASHED_EMAIL,
|
|
73
|
+
pixelId: PIXEL_ID
|
|
74
|
+
}, consentData);
|
|
75
|
+
expect(result).to.be.an('object').that.has.all.keys('callback');
|
|
76
|
+
expect(result.callback).to.be.a('function');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('Makes an ajax GET request to the production API endpoint with query params', () => {
|
|
80
|
+
invokeGetIdAPI({
|
|
81
|
+
he: HASHED_EMAIL,
|
|
82
|
+
pixelId: PIXEL_ID
|
|
83
|
+
}, consentData);
|
|
84
|
+
|
|
85
|
+
const expectedParams = {
|
|
86
|
+
he: HASHED_EMAIL,
|
|
87
|
+
pixelId: PIXEL_ID,
|
|
88
|
+
'1p': '0',
|
|
89
|
+
gdpr: '1',
|
|
90
|
+
gdpr_consent: consentData.gdpr.consentString,
|
|
91
|
+
us_privacy: consentData.uspConsent
|
|
92
|
+
};
|
|
93
|
+
const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]);
|
|
94
|
+
|
|
95
|
+
expect(ajaxStub.firstCall.args[0].indexOf(`${PROD_ENDPOINT}?`)).to.equal(0);
|
|
96
|
+
expect(requestQueryParams).to.deep.equal(expectedParams);
|
|
97
|
+
expect(ajaxStub.firstCall.args[3]).to.deep.equal({method: 'GET', withCredentials: true});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('Makes an ajax GET request to the specified override API endpoint with query params', () => {
|
|
101
|
+
invokeGetIdAPI({
|
|
102
|
+
he: HASHED_EMAIL,
|
|
103
|
+
endpoint: OVERRIDE_ENDPOINT
|
|
104
|
+
}, consentData);
|
|
105
|
+
|
|
106
|
+
const expectedParams = {
|
|
107
|
+
he: HASHED_EMAIL,
|
|
108
|
+
'1p': '0',
|
|
109
|
+
gdpr: '1',
|
|
110
|
+
gdpr_consent: consentData.gdpr.consentString,
|
|
111
|
+
us_privacy: consentData.uspConsent
|
|
112
|
+
};
|
|
113
|
+
const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]);
|
|
114
|
+
|
|
115
|
+
expect(ajaxStub.firstCall.args[0].indexOf(`${OVERRIDE_ENDPOINT}?`)).to.equal(0);
|
|
116
|
+
expect(requestQueryParams).to.deep.equal(expectedParams);
|
|
117
|
+
expect(ajaxStub.firstCall.args[3]).to.deep.equal({method: 'GET', withCredentials: true});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('sets the callbacks param of the ajax function call correctly', () => {
|
|
121
|
+
invokeGetIdAPI({
|
|
122
|
+
he: HASHED_EMAIL,
|
|
123
|
+
pixelId: PIXEL_ID,
|
|
124
|
+
}, consentData);
|
|
125
|
+
|
|
126
|
+
expect(ajaxStub.firstCall.args[1]).to.be.an('object').that.has.all.keys(['success', 'error']);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('sets GDPR consent data flag correctly when call is under GDPR jurisdiction.', () => {
|
|
130
|
+
invokeGetIdAPI({
|
|
131
|
+
he: HASHED_EMAIL,
|
|
132
|
+
pixelId: PIXEL_ID,
|
|
133
|
+
}, consentData);
|
|
134
|
+
|
|
135
|
+
const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]);
|
|
136
|
+
expect(requestQueryParams.gdpr).to.equal('1');
|
|
137
|
+
expect(requestQueryParams.gdpr_consent).to.equal(consentData.gdpr.consentString);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('sets GDPR consent data flag correctly when call is NOT under GDPR jurisdiction.', () => {
|
|
141
|
+
consentData.gdpr.gdprApplies = false;
|
|
142
|
+
|
|
143
|
+
invokeGetIdAPI({
|
|
144
|
+
he: HASHED_EMAIL,
|
|
145
|
+
pixelId: PIXEL_ID,
|
|
146
|
+
}, consentData);
|
|
147
|
+
|
|
148
|
+
const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]);
|
|
149
|
+
expect(requestQueryParams.gdpr).to.equal('0');
|
|
150
|
+
expect(requestQueryParams.gdpr_consent).to.equal('');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
[1, '1', true].forEach(firstPartyParamValue => {
|
|
154
|
+
it(`sets 1p payload property to '1' for a config value of ${firstPartyParamValue}`, () => {
|
|
155
|
+
invokeGetIdAPI({
|
|
156
|
+
'1p': firstPartyParamValue,
|
|
157
|
+
he: HASHED_EMAIL,
|
|
158
|
+
pixelId: PIXEL_ID,
|
|
159
|
+
}, consentData);
|
|
160
|
+
|
|
161
|
+
const requestQueryParams = parseQS(ajaxStub.firstCall.args[0].split('?')[1]);
|
|
162
|
+
expect(requestQueryParams['1p']).to.equal('1');
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('decode()', () => {
|
|
168
|
+
const VALID_API_RESPONSES = [{
|
|
169
|
+
key: 'connectid',
|
|
170
|
+
expected: '4567',
|
|
171
|
+
payload: {
|
|
172
|
+
connectid: '4567'
|
|
173
|
+
}
|
|
174
|
+
}];
|
|
175
|
+
VALID_API_RESPONSES.forEach(responseData => {
|
|
176
|
+
it('should return a newly constructed object with the connect ID for a payload with ${responseData.key} key(s)', () => {
|
|
177
|
+
expect(connectIdSubmodule.decode(responseData.payload)).to.deep.equal(
|
|
178
|
+
{connectId: responseData.expected}
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
[{}, '', {foo: 'bar'}].forEach((response) => {
|
|
184
|
+
it(`should return undefined for an invalid response "${JSON.stringify(response)}"`, () => {
|
|
185
|
+
expect(connectIdSubmodule.decode(response)).to.be.undefined;
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|