mk9-prebid
Version:
Header Bidding Management Library
895 lines (831 loc) • 27.2 kB
JavaScript
import {expect} from 'chai';
import {spec, resetInvibes, stubDomainOptions, readGdprConsent} from 'modules/invibesBidAdapter.js';
describe('invibesBidAdapter:', function () {
const BIDDER_CODE = 'invibes';
const PLACEMENT_ID = '12345';
const ENDPOINT = 'https://bid.videostep.com/Bid/VideoAdContent';
const SYNC_ENDPOINT = 'https://k.r66net.com/GetUserSync';
let bidRequests = [
{
bidId: 'b1',
bidder: BIDDER_CODE,
bidderRequestId: 'r1',
params: {
placementId: PLACEMENT_ID
},
adUnitCode: 'test-div',
auctionId: 'a1',
sizes: [
[300, 250],
[400, 300],
[125, 125]
],
transactionId: 't1',
userId: {
pubcid: 'pub-cid-code',
pubProvidedId: 'pub-provided-id'
}
}, {
bidId: 'b2',
bidder: BIDDER_CODE,
bidderRequestId: 'r2',
params: {
placementId: 'abcde'
},
adUnitCode: 'test-div',
auctionId: 'a2',
sizes: [
[300, 250],
[400, 300]
],
transactionId: 't2'
}
];
let StubbedPersistence = function (initialValue) {
var value = initialValue;
return {
load: function () {
let str = value || '';
try {
return JSON.parse(str);
} catch (e) {
}
},
save: function (obj) {
value = JSON.stringify(obj);
}
}
};
beforeEach(function () {
resetInvibes();
document.cookie = '';
this.cStub1 = sinon.stub(console, 'info');
});
afterEach(function () {
this.cStub1.restore();
});
describe('isBidRequestValid:', function () {
context('valid bid request:', function () {
it('returns true when bidder params.placementId is set', function () {
const validBid = {
bidder: BIDDER_CODE,
params: {
placementId: PLACEMENT_ID
}
}
expect(spec.isBidRequestValid(validBid)).to.be.true;
})
});
context('invalid bid request:', function () {
it('returns false when no params', function () {
const invalidBid = {
bidder: BIDDER_CODE
}
expect(spec.isBidRequestValid(invalidBid)).to.be.false;
});
it('returns false when placementId is not set', function () {
const invalidBid = {
bidder: BIDDER_CODE,
params: {
id: '5'
}
}
expect(spec.isBidRequestValid(invalidBid)).to.be.false;
});
it('returns false when bid response was previously received', function () {
const validBid = {
bidder: BIDDER_CODE,
params: {
placementId: PLACEMENT_ID
}
}
top.window.invibes.bidResponse = {prop: 'prop'};
expect(spec.isBidRequestValid(validBid)).to.be.false;
});
});
});
describe('buildRequests', function () {
it('sends bid request to ENDPOINT via GET', function () {
const request = spec.buildRequests(bidRequests);
expect(request.url).to.equal(ENDPOINT);
expect(request.method).to.equal('GET');
});
it('sends cookies with the bid request', function () {
const request = spec.buildRequests(bidRequests);
expect(request.options.withCredentials).to.equal(true);
});
it('has location, html id, placement and width/height', function () {
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
const parsedData = request.data;
expect(parsedData.location).to.exist;
expect(parsedData.videoAdHtmlId).to.exist;
expect(parsedData.vId).to.exist;
expect(parsedData.width).to.exist;
expect(parsedData.height).to.exist;
});
it('has capped ids if local storage variable is correctly formatted', function () {
top.window.invibes.optIn = 1;
top.window.invibes.purposes = [true, false, false, false, false, false, false, false, false, false];
localStorage.ivvcap = '{"9731":[1,1768600800000]}';
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
expect(request.data.capCounts).to.equal('9731=1');
});
it('does not have capped ids if local storage variable is correctly formatted but no opt in', function () {
localStorage.ivvcap = '{"9731":[1,1768600800000]}';
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
expect(request.data.capCounts).to.equal('');
});
it('does not have capped ids if local storage variable is incorrectly formatted', function () {
localStorage.ivvcap = ':[1,1574334216992]}';
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
expect(request.data.capCounts).to.equal('');
});
it('does not have capped ids if local storage variable is expired', function () {
localStorage.ivvcap = '{"9731":[1,1574330064104]}';
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
expect(request.data.capCounts).to.equal('');
});
it('sends query string params from localstorage 1', function () {
localStorage.ivbs = JSON.stringify({bvci: 1});
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
expect(request.data.bvci).to.equal(1);
});
it('sends query string params from localstorage 2', function () {
localStorage.ivbs = JSON.stringify({invibbvlog: true});
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
expect(request.data.invibbvlog).to.equal(true);
});
it('does not send query string params from localstorage if unknwon', function () {
localStorage.ivbs = JSON.stringify({someparam: true});
const request = spec.buildRequests(bidRequests, {auctionStart: Date.now()});
expect(request.data.someparam).to.be.undefined;
});
it('sends all Placement Ids', function () {
const request = spec.buildRequests(bidRequests);
expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[0].params.placementId);
expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId);
});
it('sends undefined lid when no cookie', function () {
let request = spec.buildRequests(bidRequests);
expect(request.data.lId).to.be.undefined;
});
it('sends lid when comes on cookie', function () {
top.window.invibes.optIn = 1;
top.window.invibes.purposes = [true, false, false, false, false, false, false, false, false, false];
global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":' + Date.now() + ',"hc":0}';
let bidderRequest = {gdprConsent: {vendorData: {vendorConsents: {436: true}}}};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.lId).to.exist;
});
it('should send purpose 1', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: true}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.purposes.split(',')[0]).to.equal('true');
});
it('should send purpose 2 & 7', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: true}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.purposes.split(',')[1] && request.data.purposes.split(',')[6]).to.equal('true');
});
it('should send purpose 9', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: true}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.purposes.split(',')[9]).to.equal('true');
});
it('should send legitimateInterests 2 & 7', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: true}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
},
legitimateInterests: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.li.split(',')[1] && request.data.li.split(',')[6]).to.equal('true');
});
it('should send oi = 0 when vendorData is null', function () {
let bidderRequest = {
gdprConsent: {
vendorData: null
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(0);
});
it('should send oi = 2 when consent was approved on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: true}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 0 when vendor consents for invibes are false on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: false}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(0);
});
it('should send oi = 2 when vendor consent for invibes are false and vendor legitimate interest for invibes are true on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: false}, legitimateInterests: {436: true}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 0 when vendor consents and legitimate interests for invibes are false on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: false}, legitimateInterests: {436: false}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(0);
});
it('should send oi = 0 when purpose consents is null', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: false}},
purpose: {}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(0);
});
it('should send oi = 2 when purpose consents weren\'t approved on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: true}},
purpose: {
consents: {
1: true,
2: false,
3: false,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 2 when purpose consents are less then 10 on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: true}},
purpose: {
consents: {
1: true,
2: false,
3: false,
4: true,
5: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 4 when vendor consents are null on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: null},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(4);
});
it('should send oi = 4 when vendor consents for invibes is null on tcf v2', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendor: {consents: {436: null}},
purpose: {
consents: {
1: true,
2: true,
3: true,
4: true,
5: true,
6: true,
7: true,
8: true,
9: true,
10: true
}
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(4);
});
it('should send oi = 4 when vendor consents for invibes is null on tcf v1', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendorConsents: {436: null},
purposeConsents: {
1: true,
2: true,
3: true,
4: true,
5: true
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(4);
});
it('should send oi = 4 when vendor consents consents are null on tcf v1', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendorConsents: null,
purposeConsents: {
1: true,
2: true,
3: true,
4: true,
5: true
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(4);
});
it('should send oi = 2 when gdpr doesn\'t apply or has global consent', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: false,
hasGlobalConsent: true,
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 2 when consent was approved on tcf v1', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendorConsents: {436: true},
purposeConsents: {
1: true,
2: true,
3: true,
4: true,
5: true
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 2 when purpose consents weren\'t approved on tcf v1', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendorConsents: {436: true},
purposeConsents: {
1: false,
2: false,
3: true,
4: true,
5: true
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 2 when purpose consents are less then 5 on tcf v1', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendorConsents: {436: true},
purposeConsents: {
1: false,
2: false,
3: true
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(2);
});
it('should send oi = 0 when vendor consents for invibes are false on tcf v1', function () {
let bidderRequest = {
gdprConsent: {
vendorData: {
gdprApplies: true,
hasGlobalConsent: false,
vendorConsents: {436: false},
purposeConsents: {
1: true,
2: true,
3: true,
4: true,
5: true
}
}
}
};
let request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.oi).to.equal(0);
});
});
describe('interpretResponse', function () {
let response = {
Ads: [{
BidPrice: 0.5,
VideoExposedId: 123
}],
BidModel: {
BidVersion: 1,
PlacementId: '12345',
AuctionStartTime: Date.now(),
CreativeHtml: '<!-- Creative -->'
}
};
let expectedResponse = [{
requestId: bidRequests[0].bidId,
cpm: 0.5,
width: 400,
height: 300,
creativeId: 123,
currency: 'EUR',
netRevenue: true,
ttl: 300,
ad: `<html>
<head><script type='text/javascript'>inDapIF=true;</script></head>
<body style='margin : 0; padding: 0;'>
<!-- Creative -->
</body>
</html>`,
meta: {}
}];
let multiResponse = {
AdPlacements: [{
Ads: [{
BidPrice: 0.5,
VideoExposedId: 123
}],
BidModel: {
BidVersion: 1,
PlacementId: '12345',
AuctionStartTime: Date.now(),
CreativeHtml: '<!-- Creative -->'
}
}]
};
let invalidResponse = {
AdPlacements: [{
Ads: [{
BidPrice: 0.5,
VideoExposedId: 123
}]
}]
};
let responseWithMeta = {
Ads: [{
BidPrice: 0.5,
VideoExposedId: 123
}],
BidModel: {
BidVersion: 1,
PlacementId: '12345',
AuctionStartTime: Date.now(),
CreativeHtml: '<!-- Creative -->',
Meta: {
advertiserDomains: ['theadvertiser.com', 'theadvertiser_2.com'],
advertiserName: 'theadvertiser'
}
}
};
context('when the response is not valid', function () {
it('handles response with no bids requested', function () {
let emptyResult = spec.interpretResponse({body: response});
expect(emptyResult).to.be.empty;
});
it('handles empty response', function () {
let emptyResult = spec.interpretResponse(null, {bidRequests});
expect(emptyResult).to.be.empty;
});
it('handles response with bidding is not configured', function () {
let emptyResult = spec.interpretResponse({body: {Ads: [{BidPrice: 1}]}}, {bidRequests});
expect(emptyResult).to.be.empty;
});
it('handles response with no ads are received', function () {
let emptyResult = spec.interpretResponse({
body: {
BidModel: {PlacementId: '12345'},
AdReason: 'No ads'
}
}, {bidRequests});
expect(emptyResult).to.be.empty;
});
it('handles response with no ads are received - no ad reason', function () {
let emptyResult = spec.interpretResponse({body: {BidModel: {PlacementId: '12345'}}}, {bidRequests});
expect(emptyResult).to.be.empty;
});
it('handles response when no placement Id matches', function () {
let emptyResult = spec.interpretResponse({
body: {
BidModel: {PlacementId: '123456'},
Ads: [{BidPrice: 1}]
}
}, {bidRequests});
expect(emptyResult).to.be.empty;
});
it('handles response when placement Id is not present', function () {
let emptyResult = spec.interpretResponse({BidModel: {}, Ads: [{BidPrice: 1}]}, {bidRequests});
expect(emptyResult).to.be.empty;
});
it('handles response when bid model is missing', function () {
let emptyResult = spec.interpretResponse(invalidResponse);
expect(emptyResult).to.be.empty;
});
});
context('when the multiresponse is valid', function () {
it('responds with a valid multiresponse bid', function () {
let result = spec.interpretResponse({body: multiResponse}, {bidRequests});
expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
});
it('responds with a valid singleresponse bid', function () {
let result = spec.interpretResponse({body: response}, {bidRequests});
expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
});
it('does not make multiple bids', function () {
let result = spec.interpretResponse({body: response}, {bidRequests});
let secondResult = spec.interpretResponse({body: response}, {bidRequests});
expect(secondResult).to.be.empty;
});
});
context('when the response has meta', function () {
it('responds with a valid bid, with the meta info', function () {
let result = spec.interpretResponse({body: responseWithMeta}, {bidRequests});
expect(result[0].meta.advertiserName).to.equal('theadvertiser');
expect(result[0].meta.advertiserDomains).to.contain('theadvertiser.com');
expect(result[0].meta.advertiserDomains).to.contain('theadvertiser_2.com');
});
});
});
describe('getUserSyncs', function () {
it('returns an iframe if enabled', function () {
let response = spec.getUserSyncs({iframeEnabled: true});
expect(response.type).to.equal('iframe');
expect(response.url).to.include(SYNC_ENDPOINT);
});
it('returns an iframe with params if enabled', function () {
top.window.invibes.optIn = 1;
global.document.cookie = 'ivvbks=17639.0,1,2';
let response = spec.getUserSyncs({iframeEnabled: true});
expect(response.type).to.equal('iframe');
expect(response.url).to.include(SYNC_ENDPOINT);
expect(response.url).to.include('optIn');
expect(response.url).to.include('ivvbks');
});
it('returns an iframe with params including if enabled', function () {
top.window.invibes.optIn = 1;
global.document.cookie = 'ivvbks=17639.0,1,2;ivbsdid={"id":"dvdjkams6nkq","cr":' + Date.now() + ',"hc":0}';
let response = spec.getUserSyncs({iframeEnabled: true});
expect(response.type).to.equal('iframe');
expect(response.url).to.include(SYNC_ENDPOINT);
expect(response.url).to.include('optIn');
expect(response.url).to.include('ivvbks');
expect(response.url).to.include('ivbsdid');
});
it('returns undefined if iframe not enabled ', function () {
let response = spec.getUserSyncs({iframeEnabled: false});
expect(response).to.equal(undefined);
});
});
});