mk9-prebid
Version:
Header Bidding Management Library
627 lines (585 loc) • 21.3 kB
JavaScript
import { expect } from 'chai';
import { spec } from 'modules/videobyteBidAdapter.js';
describe('VideoByteBidAdapter', function () {
let bidRequest;
let bidderRequest = {
'bidderCode': 'videobyte',
'auctionId': 'e158486f-8c7f-472f-94ce-b0cbfbb50ab4',
'bidderRequestId': '1e498b84fffc39',
'bids': bidRequest,
'auctionStart': 1520001292880,
'timeout': 3000,
'start': 1520001292884,
'doneCbCallCount': 0,
'refererInfo': {
'numIframes': 1,
'reachedTop': true,
'referer': 'test.com'
}
};
let mockConfig;
beforeEach(function () {
bidRequest = {
mediaTypes: {
video: {
context: 'instream',
playerSize: [[640, 480]],
}
},
bidder: 'videobyte',
sizes: [640, 480],
bidId: '30b3efwfwe1e',
adUnitCode: 'video1',
params: {
video: {
playerWidth: 640,
playerHeight: 480,
mimes: ['video/mp4', 'application/javascript'],
protocols: [2, 5],
api: [2],
position: 1,
delivery: [2],
sid: 134,
rewarded: 1,
placement: 1,
hp: 1,
inventoryid: 123
},
site: {
id: 1,
page: 'https://test.com',
referrer: 'http://test.com'
},
pubId: 'vb12345'
}
};
});
describe('spec.isBidRequestValid', function () {
it('should return false when mediaTypes is empty', function () {
bidRequest.mediaTypes = {};
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
it('should return true (skip validations) when e2etest = true', function () {
bidRequest.params.video = {
e2etest: true
};
expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
});
it('should return true when mediaTypes.video has all mandatory params', function () {
bidRequest.mediaTypes.video = {
context: 'instream',
playerSize: [[640, 480]],
mimes: ['video/mp4', 'application/javascript'],
}
bidRequest.params.video = {};
expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
});
it('should return true when params.video has all override params instead of mediaTypes.video', function () {
bidRequest.mediaTypes.video = {
context: 'instream'
};
bidRequest.params.video = {
playerSize: [[640, 480]],
mimes: ['video/mp4', 'application/javascript']
};
expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
});
it('should return true when mimes is passed in params.video', function () {
bidRequest.mediaTypes.video = {
context: 'instream',
playerSize: [[640, 480]]
};
bidRequest.video = {
mimes: ['video/mp4', 'application/javascript']
};
expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
});
it('should return false when both mediaTypes.video and params.video Objects are missing', function () {
bidRequest.mediaTypes = {};
bidRequest.params = {
pubId: 'brxd'
};
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
it('should return false when both mediaTypes.video and params.video are missing mimes and player size', function () {
bidRequest.mediaTypes = {
video: {
context: 'instream'
}
};
bidRequest.params = {
pubId: 'brxd'
};
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
it('should return false when the "pubId" param is missing', function () {
bidRequest.params = {
video: {
playerWidth: 480,
playerHeight: 640,
mimes: ['video/mp4', 'application/javascript'],
}
};
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
it('should return false when the "pubId" param is missing', function () {
bidRequest.params = {
video: {
playerWidth: 480,
playerHeight: 640,
mimes: ['video/mp4', 'application/javascript'],
}
};
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
it('should return false when no bid params are passed', function () {
bidRequest.params = {};
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
});
describe('spec.buildRequests', function () {
it('should create a POST request for every bid', function () {
const requests = spec.buildRequests([bidRequest], bidderRequest);
expect(requests[0].method).to.equal('POST');
expect(requests[0].url).to.equal(spec.ENDPOINT + bidRequest.params.pubId);
});
it('should attach request data', function () {
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
const [width, height] = bidRequest.sizes;
const VERSION = '1.0.0';
expect(data.imp[0].video.w).to.equal(width);
expect(data.imp[0].video.h).to.equal(height);
expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor);
expect(data.ext.prebidver).to.equal('$prebid.version$');
expect(data.ext.adapterver).to.equal(spec.VERSION);
});
it('should set pubId to e2etest when bid.params.video.e2etest = true', function () {
bidRequest.params.video.e2etest = true;
const requests = spec.buildRequests([bidRequest], bidderRequest);
expect(requests[0].method).to.equal('POST');
expect(requests[0].url).to.equal(spec.ENDPOINT + 'e2etest');
});
it('should attach End 2 End test data', function () {
bidRequest.params.video.e2etest = true;
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.imp[0].bidfloor).to.not.exist;
expect(data.imp[0].video.w).to.equal(640);
expect(data.imp[0].video.h).to.equal(480);
});
it('should send Global schain', function () {
bidRequest.params.video.sid = null;
const globalSchain = {
ver: '1.0',
complete: 1,
nodes: [{
asi: 'some-platform.com',
sid: '111111',
rid: bidRequest.id,
hp: 1
}]
};
bidRequest.schain = globalSchain;
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
const schain = data.source.ext.schain;
expect(schain.nodes.length).to.equal(1);
expect(schain).to.deep.equal(globalSchain);
});
describe('content object validations', function () {
it('should not accept content object if value is Undefined ', function () {
bidRequest.params.video.content = null;
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.undefined;
});
it('should not accept content object if value is is Array ', function () {
bidRequest.params.video.content = [];
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.undefined;
});
it('should not accept content object if value is Number ', function () {
bidRequest.params.video.content = 123456;
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.undefined;
});
it('should not accept content object if value is String ', function () {
bidRequest.params.video.content = 'keyValuePairs';
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.undefined;
});
it('should not accept content object if value is Boolean ', function () {
bidRequest.params.video.content = true;
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.undefined;
});
it('should accept content object if value is Object ', function () {
bidRequest.params.video.content = {};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.a('object');
});
it('should not append unsupported content object keys', function () {
bidRequest.params.video.content = {
fake: 'news',
unreal: 'param',
counterfit: 'data'
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.empty;
});
it('should not append content string parameters if value is not string ', function () {
bidRequest.params.video.content = {
id: 1234,
title: ['Title'],
series: ['Series'],
season: ['Season'],
genre: ['Genre'],
contentrating: {1: 'C-Rating'},
language: {1: 'EN'}
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.a('object');
expect(data.site.content).to.be.empty
});
it('should not append content Number parameters if value is not Number ', function () {
bidRequest.params.video.content = {
episode: '1',
context: 'context',
livestream: {0: 'stream'},
len: [360],
prodq: [1],
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.a('object');
expect(data.site.content).to.be.empty
});
it('should not append content Array parameters if value is not Array ', function () {
bidRequest.params.video.content = {
cat: 'categories',
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.a('object');
expect(data.site.content).to.be.empty
});
it('should not append content ext if value is not Object ', function () {
bidRequest.params.video.content = {
ext: 'content.ext',
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.be.a('object');
expect(data.site.content).to.be.empty
});
it('should append supported parameters if value match validations ', function () {
bidRequest.params.video.content = {
id: '1234',
title: 'Title',
series: 'Series',
season: 'Season',
cat: [
'IAB1'
],
genre: 'Genre',
contentrating: 'C-Rating',
language: 'EN',
episode: 1,
prodq: 1,
context: 1,
livestream: 0,
len: 360,
ext: {}
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.site.content).to.deep.equal(bidRequest.params.video.content);
});
});
});
describe('price floor module validations', function () {
beforeEach(function () {
bidRequest.getFloor = (floorObj) => {
return {
floor: bidRequest.floors.values[floorObj.mediaType + '|640x480'],
currency: floorObj.currency,
mediaType: floorObj.mediaType
}
}
});
it('should get bidfloor from getFloor method', function () {
bidRequest.params.cur = 'EUR';
bidRequest.floors = {
currency: 'EUR',
values: {
'video|640x480': 5.55
}
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.imp[0].bidfloor).is.a('number');
expect(data.imp[0].bidfloor).to.equal(5.55);
});
it('should get bidfloor from params method', function () {
bidRequest.params.bidfloor = 4.0;
bidRequest.params.currency = 'EUR';
bidRequest.getFloor = null;
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.imp[0].bidfloor).is.a('number');
expect(data.imp[0].bidfloor).to.equal(4.0);
expect(data.imp[0].bidfloorcur).to.equal('EUR');
});
it('should use adUnit/module currency & floor instead of bid.params.bidfloor', function () {
bidRequest.params.cur = 'EUR';
bidRequest.params.bidfloor = 3.33;
bidRequest.floors = {
currency: 'EUR',
values: {
'video|640x480': 5.55
}
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.imp[0].bidfloor).is.a('number');
expect(data.imp[0].bidfloor).to.equal(5.55);
});
it('should load video floor when multi-format adUnit is present', function () {
bidRequest.params.cur = 'EUR';
bidRequest.mediaTypes.banner = {
sizes: [
[640, 480]
]
};
bidRequest.floors = {
currency: 'EUR',
values: {
'banner|640x480': 2.22,
'video|640x480': 9.99
}
};
const requests = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(requests[0].data);
expect(data.imp[0].bidfloor).is.a('number');
expect(data.imp[0].bidfloor).to.equal(9.99);
})
})
describe('spec.interpretResponse', function () {
it('should return no bids if the response is not valid', function () {
const bidResponse = spec.interpretResponse({
body: null
}, {
bidRequest
});
expect(bidResponse.length).to.equal(0);
});
it('should return no bids if the response "nurl" and "adm" are missing', function () {
const serverResponse = {
seatbid: [{
bid: [{
price: 6.01
}]
}]
};
const bidResponse = spec.interpretResponse({
body: serverResponse
}, {
bidRequest
});
expect(bidResponse.length).to.equal(0);
});
it('should return no bids if the response "price" is missing', function () {
const serverResponse = {
seatbid: [{
bid: [{
adm: '<VAST></VAST>'
}]
}]
};
const bidResponse = spec.interpretResponse({
body: serverResponse
}, {
bidRequest
});
expect(bidResponse.length).to.equal(0);
});
it('should return a valid video bid response with just "adm"', function () {
const serverResponse = {
id: '123',
seatbid: [{
bid: [{
id: 1,
adid: 123,
crid: 2,
price: 6.01,
adm: '<VAST></VAST>',
adomain: [
'videobyte.com'
],
w: 640,
h: 480
}]
}],
cur: 'USD'
};
const bidResponse = spec.interpretResponse({
body: serverResponse
}, {
bidRequest
});
let o = {
requestId: serverResponse.id,
bidderCode: spec.code,
cpm: serverResponse.seatbid[0].bid[0].price,
creativeId: serverResponse.seatbid[0].bid[0].crid,
vastXml: serverResponse.seatbid[0].bid[0].adm,
width: 640,
height: 480,
mediaType: 'video',
currency: 'USD',
ttl: 300,
netRevenue: true,
meta: {
advertiserDomains: ['videobyte.com']
}
};
expect(bidResponse[0]).to.deep.equal(o);
});
it('should default ttl to 300', function () {
const serverResponse = {seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: '<VAST></VAST>'}]}], cur: 'USD'};
const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest });
expect(bidResponse[0].ttl).to.equal(300);
});
it('should not allow ttl above 3601, default to 300', function () {
bidRequest.params.video.ttl = 3601;
const serverResponse = {seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: '<VAST></VAST>'}]}], cur: 'USD'};
const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest });
expect(bidResponse[0].ttl).to.equal(300);
});
it('should not allow ttl below 1, default to 300', function () {
bidRequest.params.video.ttl = 0;
const serverResponse = {seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: '<VAST></VAST>'}]}], cur: 'USD'};
const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest });
expect(bidResponse[0].ttl).to.equal(300);
});
});
describe('when GDPR and uspConsent applies', function () {
beforeEach(function () {
bidderRequest = {
'gdprConsent': {
'consentString': 'test-gdpr-consent-string',
'gdprApplies': true
},
'uspConsent': '1YN-',
'bidderCode': 'videobyte',
'auctionId': 'e158486f-8c7f-472f-94ce-b0cbfbb50ab4',
'bidderRequestId': '1e498b84fffc39',
'bids': bidRequest,
'auctionStart': 1520001292880,
'timeout': 3000,
'start': 1520001292884,
'doneCbCallCount': 0,
'refererInfo': {
'numIframes': 1,
'reachedTop': true,
'referer': 'test.com'
}
};
mockConfig = {
consentManagement: {
gdpr: {
cmpApi: 'iab',
timeout: 3000,
allowAuctionWithoutConsent: 'cancel'
},
usp: {
cmpApi: 'iab',
timeout: 1000,
allowAuctionWithoutConsent: 'cancel'
}
}
};
});
it('should send a signal to specify that GDPR applies to this request', function () {
const request = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(request[0].data);
expect(data.regs.ext.gdpr).to.equal(1);
});
it('should send the consent string', function () {
const request = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(request[0].data);
expect(data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString);
});
it('should send the uspConsent string', function () {
const request = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(request[0].data);
expect(data.regs.ext.us_privacy).to.equal(bidderRequest.uspConsent);
});
it('should send the uspConsent and GDPR ', function () {
const request = spec.buildRequests([bidRequest], bidderRequest);
const data = JSON.parse(request[0].data);
expect(data.regs.ext.gdpr).to.equal(1);
expect(data.regs.ext.us_privacy).to.equal(bidderRequest.uspConsent);
});
});
describe('getUserSyncs', function () {
const ortbResponse = {
'body': {
'ext': {
'usersync': {
'sovrn': {
'status': 'none',
'syncs': [
{
'url': 'urlsovrn',
'type': 'iframe'
}
]
},
'appnexus': {
'status': 'none',
'syncs': [
{
'url': 'urlappnexus',
'type': 'pixel'
}
]
}
}
}
}
};
it('handles no parameters', function () {
let opts = spec.getUserSyncs({});
expect(opts).to.be.an('array').that.is.empty;
});
it('returns non if sync is not allowed', function () {
let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false});
expect(opts).to.be.an('array').that.is.empty;
});
it('iframe sync enabled should return results', function () {
let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [ortbResponse]);
expect(opts.length).to.equal(1);
expect(opts[0].type).to.equal('iframe');
expect(opts[0].url).to.equal(ortbResponse.body.ext.usersync['sovrn'].syncs[0].url);
});
it('pixel sync enabled should return results', function () {
let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [ortbResponse]);
expect(opts.length).to.equal(1);
expect(opts[0].type).to.equal('image');
expect(opts[0].url).to.equal(ortbResponse.body.ext.usersync['appnexus'].syncs[0].url);
});
it('all sync enabled should return only iframe result', function () {
let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [ortbResponse]);
expect(opts.length).to.equal(1);
});
});
});