mk9-prebid
Version:
Header Bidding Management Library
559 lines (473 loc) • 15 kB
JavaScript
import { expect } from 'chai';
import { spec } from 'modules/pubgeniusBidAdapter.js';
import { config } from 'src/config.js';
import { VIDEO } from 'src/mediaTypes.js';
import { deepClone, parseQueryStringParameters } from 'src/utils.js';
import { server } from 'test/mocks/xhr.js';
const {
code,
supportedMediaTypes,
isBidRequestValid,
buildRequests,
interpretResponse,
getUserSyncs,
onTimeout,
} = spec;
describe('pubGENIUS adapter', () => {
describe('code', () => {
it('should be pubgenius', () => {
expect(code).to.equal('pubgenius');
});
});
describe('supportedMediaTypes', () => {
it('should contain banner and video', () => {
expect(supportedMediaTypes).to.deep.equal(['banner', 'video']);
});
});
describe('isBidRequestValid', () => {
let bid = null;
beforeEach(() => {
bid = {
mediaTypes: {
banner: {
sizes: [[300, 600], [300, 250]],
},
},
params: {
adUnitId: 1112,
},
};
});
it('should return true with numeric adUnitId ', () => {
expect(isBidRequestValid(bid)).to.be.true;
});
it('should return true with string adUnitId ', () => {
bid.params.adUnitId = '1112';
expect(isBidRequestValid(bid)).to.be.true;
});
it('should return false without adUnitId', () => {
delete bid.params.adUnitId;
expect(isBidRequestValid(bid)).to.be.false;
});
it('should return false with adUnitId of invalid type', () => {
bid.params.adUnitId = [1112];
expect(isBidRequestValid(bid)).to.be.false;
});
it('should return false with empty sizes', () => {
bid.mediaTypes.banner.sizes = [];
expect(isBidRequestValid(bid)).to.be.false;
});
it('should return false with invalid size', () => {
bid.mediaTypes.banner.sizes = [[300, 600, 250]];
expect(isBidRequestValid(bid)).to.be.false;
});
it('should return false without banner or video', () => {
bid.mediaTypes = {};
expect(isBidRequestValid(bid)).to.be.false;
});
it('should return true with valid video media type', () => {
bid.mediaTypes = {
video: {
context: 'instream',
playerSize: [[100, 100]],
mimes: ['video/mp4'],
protocols: [1],
},
};
expect(isBidRequestValid(bid)).to.be.true;
});
it('should return true with valid video params', () => {
bid.params.video = {
placement: 1,
w: 200,
h: 200,
mimes: ['video/mp4'],
protocols: [1],
};
expect(isBidRequestValid(bid)).to.be.true;
});
it('should return false without video protocols', () => {
bid.mediaTypes = {
video: {
context: 'instream',
playerSize: [[100, 100]],
},
};
bid.params.video = {
mimes: ['video/mp4'],
};
expect(isBidRequestValid(bid)).to.be.false;
});
});
describe('buildRequests', () => {
const origBidderTimeout = config.getConfig('bidderTimeout');
const origPageUrl = config.getConfig('pageUrl');
const origCoppa = config.getConfig('coppa');
after(() => {
config.setConfig({
bidderTimeout: origBidderTimeout,
pageUrl: origPageUrl,
coppa: origCoppa,
});
});
let bidRequest = null;
let bidderRequest = null;
let expectedRequest = null;
beforeEach(() => {
bidRequest = {
adUnitCode: 'test-div',
auctionId: 'fake-auction-id',
bidId: 'fakebidid',
bidder: 'pubgenius',
bidderRequestId: 'fakebidderrequestid',
bidRequestsCount: 1,
bidderRequestsCount: 1,
bidderWinsCount: 0,
mediaTypes: {
banner: {
sizes: [[300, 600], [300, 250]],
},
},
params: {
adUnitId: 1112,
},
transactionId: 'fake-transaction-id',
};
bidderRequest = {
auctionId: 'fake-auction-id',
bidderCode: 'pubgenius',
bidderRequestId: 'fakebidderrequestid',
refererInfo: {},
timeout: 1200,
};
expectedRequest = {
method: 'POST',
url: 'https://ortb.adpearl.io/prebid/auction',
data: {
id: 'fake-auction-id',
imp: [
{
id: 'fakebidid',
banner: {
format: [{ w: 300, h: 600 }, { w: 300, h: 250 }],
topframe: 0,
},
tagid: '1112',
},
],
tmax: 1200,
ext: {
pbadapter: {
version: '1.1.0',
},
},
},
};
config.setConfig({
bidderTimeout: 1000,
pageUrl: undefined,
coppa: undefined,
});
});
it('should build basic requests correctly', () => {
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should build requests with multiple ad units', () => {
const bidRequest1 = deepClone(bidRequest);
bidRequest1.adUnitCode = 'test-div-1';
bidRequest1.bidId = 'fakebidid1';
bidRequest1.mediaTypes.banner.sizes = [[728, 90]];
bidRequest1.params.adUnitId = '1111';
expectedRequest.data.imp.push({
id: 'fakebidid1',
banner: {
format: [{ w: 728, h: 90 }],
topframe: 0,
},
tagid: '1111',
});
expect(buildRequests([bidRequest, bidRequest1], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take bid floor from getFloor interface', () => {
bidRequest.getFloor = () => ({ floor: 0.5, currency: 'USD' });
expectedRequest.data.imp[0].bidfloor = 0.5;
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take position in bidder params', () => {
bidRequest.params.position = 3;
expectedRequest.data.imp[0].banner.pos = 3;
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take pageUrl in config over referer in refererInfo', () => {
config.setConfig({ pageUrl: 'http://pageurl.org' });
bidderRequest.refererInfo.referer = 'http://referer.org';
expectedRequest.data.site = { page: 'http://pageurl.org' };
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should use canonical URL over referer in refererInfo', () => {
bidderRequest.refererInfo.canonicalUrl = 'http://pageurl.org';
bidderRequest.refererInfo.referer = 'http://referer.org';
expectedRequest.data.site = { page: 'http://pageurl.org' };
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take gdprConsent when GDPR does not apply', () => {
bidderRequest.gdprConsent = {
gdprApplies: false,
consentString: 'fakeconsent',
};
expectedRequest.data.regs = {
ext: { gdpr: 0 },
};
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take gdprConsent when GDPR applies', () => {
bidderRequest.gdprConsent = {
gdprApplies: true,
consentString: 'fakeconsent',
};
expectedRequest.data.regs = {
ext: { gdpr: 1 },
};
expectedRequest.data.user = {
ext: { consent: 'fakeconsent' },
};
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take uspConsent', () => {
bidderRequest.uspConsent = '1---';
expectedRequest.data.regs = {
ext: { us_privacy: '1---' },
};
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take schain', () => {
const schain = {
ver: '1.0',
complete: 1,
nodes: [
{
asi: 'indirectseller.com',
sid: '0001',
hp: 1
}
]
};
bidRequest.schain = deepClone(schain);
expectedRequest.data.source = {
ext: { schain: deepClone(schain) },
};
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take coppa', () => {
config.setConfig({ coppa: true });
expectedRequest.data.regs = { coppa: 1 };
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should take user IDs', () => {
const eid = {
source: 'adserver.org',
uids: [
{
id: 'fake-user-id',
atype: 1,
ext: { rtiPartner: 'TDID' },
},
],
};
bidRequest.userIdAsEids = [deepClone(eid)];
expectedRequest.data.user = {
ext: {
eids: [deepClone(eid)],
},
};
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should not take unsupported user IDs', () => {
bidRequest.userIdAsEids = [
{
source: 'pubcid.org',
uids: [
{
id: 'fake-user-id',
atype: 1,
},
],
},
];
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should not take empty user IDs', () => {
bidRequest.userIdAsEids = [];
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
it('should build video imp', () => {
bidRequest.mediaTypes = {
video: {
context: 'instream',
playerSize: [[200, 100]],
mimes: ['video/mp4'],
protocols: [2, 3],
api: [1, 2],
playbackmethod: [3, 4],
maxduration: 10,
linearity: 1,
},
};
bidRequest.params.video = {
minduration: 5,
maxduration: 100,
skip: 1,
skipafter: 1,
startdelay: -1,
};
delete expectedRequest.data.imp[0].banner;
expectedRequest.data.imp[0].video = {
mimes: ['video/mp4'],
minduration: 5,
maxduration: 100,
protocols: [2, 3],
w: 200,
h: 100,
startdelay: -1,
placement: 1,
skip: 1,
skipafter: 1,
playbackmethod: [3, 4],
api: [1, 2],
linearity: 1,
};
expect(buildRequests([bidRequest], bidderRequest)).to.deep.equal(expectedRequest);
});
});
describe('interpretResponse', () => {
let serverResponse = null;
let expectedBidResponse = null;
beforeEach(() => {
serverResponse = {
body: {
seatbid: [
{
seat: 'pubgenius',
bid: [
{
impid: 'fakebidid',
price: 0.3,
w: 300,
h: 250,
adm: 'fake_creative',
exp: 60,
crid: 'fakecreativeid',
},
],
},
],
},
};
expectedBidResponse = {
requestId: 'fakebidid',
cpm: 0.3,
currency: 'USD',
width: 300,
height: 250,
ad: 'fake_creative',
ttl: 60,
creativeId: 'fakecreativeid',
netRevenue: true,
};
});
it('should interpret response correctly', () => {
expect(interpretResponse(serverResponse)).to.deep.equal([expectedBidResponse]);
});
it('should interpret response with adomain', () => {
serverResponse.body.seatbid[0].bid[0].adomain = ['fakeaddomain'];
expectedBidResponse.meta = {
advertiserDomains: ['fakeaddomain'],
};
expect(interpretResponse(serverResponse)).to.deep.equal([expectedBidResponse]);
});
it('should interpret no bids', () => {
expect(interpretResponse({ body: {} })).to.deep.equal([]);
});
it('should interpret video response', () => {
serverResponse.body.seatbid[0].bid[0] = {
...serverResponse.body.seatbid[0].bid[0],
nurl: 'http://vasturl/cache?id=x',
ext: {
pbadapter: {
mediaType: 'video',
cacheKey: 'x',
},
},
};
delete expectedBidResponse.ad;
expectedBidResponse = {
...expectedBidResponse,
vastUrl: 'http://vasturl/cache?id=x',
vastXml: 'fake_creative',
mediaType: VIDEO,
};
expect(interpretResponse(serverResponse)).to.deep.equal([expectedBidResponse]);
});
});
describe('getUserSyncs', () => {
let syncOptions = null;
let expectedSync = null;
beforeEach(() => {
syncOptions = {
iframeEnabled: true,
pixelEnabled: true,
};
expectedSync = {
type: 'iframe',
url: 'https://ortb.adpearl.io/usersync/pixels.html?',
};
});
it('should return iframe pixels', () => {
expect(getUserSyncs(syncOptions)).to.deep.equal([expectedSync]);
});
it('should return empty when iframe is not enabled', () => {
syncOptions.iframeEnabled = false;
expect(getUserSyncs(syncOptions)).to.deep.equal([]);
});
it('should return sync when GDPR applies', () => {
const gdprConsent = {
gdprApplies: true,
consentString: 'fake-gdpr-consent',
};
expectedSync.url = expectedSync.url + parseQueryStringParameters({
gdpr: 1,
consent: 'fake-gdpr-consent',
});
expect(getUserSyncs(syncOptions, [], gdprConsent)).to.deep.equal([expectedSync]);
});
it('should return sync when GDPR does not apply', () => {
const gdprConsent = {
gdprApplies: false,
};
expectedSync.url = expectedSync.url + parseQueryStringParameters({ gdpr: 0 });
expect(getUserSyncs(syncOptions, [], gdprConsent)).to.deep.equal([expectedSync]);
});
it('should return sync with US privacy', () => {
expectedSync.url = expectedSync.url + parseQueryStringParameters({ us_privacy: '1---' });
expect(getUserSyncs(syncOptions, [], undefined, '1---')).to.deep.equal([expectedSync]);
});
});
describe('onTimeout', () => {
it('should send timeout data', () => {
const timeoutData = {
bidder: 'pubgenius',
bidId: 'fakebidid',
params: {
adUnitId: 1234,
},
adUnitCode: 'fake-ad-unit-code',
timeout: 3000,
auctionId: 'fake-auction-id',
};
onTimeout(timeoutData);
expect(server.requests[0].method).to.equal('POST');
expect(server.requests[0].url).to.equal('https://ortb.adpearl.io/prebid/events?type=timeout');
expect(JSON.parse(server.requests[0].requestBody)).to.deep.equal(timeoutData);
});
});
});