mk9-prebid
Version:
Header Bidding Management Library
534 lines (496 loc) • 15.8 kB
JavaScript
import { expect } from 'chai';
import { OPENRTB, spec } from 'modules/rtbhouseBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
describe('RTBHouseAdapter', () => {
const adapter = newBidder(spec);
describe('inherited functions', function () {
it('exists and is a function', function () {
expect(adapter.callBids).to.exist.and.to.be.a('function');
});
});
describe('isBidRequestValid', function () {
let bid = {
'bidder': 'rtbhouse',
'params': {
'publisherId': 'PREBID_TEST',
'region': 'prebid-eu'
},
'adUnitCode': 'adunit-code',
'mediaTypes': {
'banner': {
'sizes': [[300, 250], [300, 600]],
}
},
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475'
};
it('should return true when required params found', function () {
expect(spec.isBidRequestValid(bid)).to.equal(true);
});
it('Checking backward compatibility. should return true', function () {
let bid2 = Object.assign({}, bid);
delete bid2.mediaTypes;
bid2.sizes = [[300, 250], [300, 600]];
expect(spec.isBidRequestValid(bid2)).to.equal(true);
});
it('should return false when required params are not passed', function () {
let bid = Object.assign({}, bid);
delete bid.params;
bid.params = {
'someIncorrectParam': 0
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
});
describe('buildRequests', function () {
let bidRequests;
const bidderRequest = {
'refererInfo': {
'numIframes': 0,
'reachedTop': true,
'referer': 'https://example.com',
'stack': ['https://example.com']
}
};
beforeEach(() => {
bidRequests = [
{
'bidder': 'rtbhouse',
'params': {
'publisherId': 'PREBID_TEST',
'region': 'prebid-eu',
'test': 1
},
'adUnitCode': 'adunit-code',
'mediaTypes': {
'banner': {
'sizes': [[300, 250], [300, 600]],
}
},
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
'transactionId': 'example-transaction-id',
'schain': {
'ver': '1.0',
'complete': 1,
'nodes': [
{
'asi': 'directseller.com',
'sid': '00001',
'rid': 'BidRequest1',
'hp': 1
}
]
}
}
];
});
it('should build test param into the request', () => {
let builtTestRequest = spec.buildRequests(bidRequests, bidderRequest).data;
expect(JSON.parse(builtTestRequest).test).to.equal(1);
});
it('should build valid OpenRTB banner object', () => {
const request = JSON.parse(spec.buildRequests(bidRequests, bidderRequest).data);
const imp = request.imp[0];
expect(imp.banner).to.deep.equal({
w: 300,
h: 250,
format: [{
w: 300,
h: 250
}, {
w: 300,
h: 600
}]
})
});
it('sends bid request to ENDPOINT via POST', function () {
let bidRequest = Object.assign([], bidRequests);
delete bidRequest[0].params.test;
const request = spec.buildRequests(bidRequest, bidderRequest);
expect(request.url).to.equal('https://prebid-eu.creativecdn.com/bidder/prebid/bids');
expect(request.method).to.equal('POST');
});
it('should not populate GDPR if for non-EEA users', function () {
let bidRequest = Object.assign([], bidRequests);
delete bidRequest[0].params.test;
const request = spec.buildRequests(bidRequest, bidderRequest);
let data = JSON.parse(request.data);
expect(data).to.not.have.property('regs');
expect(data).to.not.have.property('user');
});
it('should populate GDPR and consent string if available for EEA users', function () {
let bidRequest = Object.assign([], bidRequests);
delete bidRequest[0].params.test;
const request = spec.buildRequests(
bidRequest,
Object.assign({}, bidderRequest, {
gdprConsent: {
gdprApplies: true,
consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='
}
})
);
let data = JSON.parse(request.data);
expect(data.regs.ext.gdpr).to.equal(1);
expect(data.user.ext.consent).to.equal('BOJ8RZsOJ8RZsABAB8AAAAAZ-A');
});
it('should populate GDPR and empty consent string if available for EEA users without consent string but with consent', function () {
let bidRequest = Object.assign([], bidRequests);
delete bidRequest[0].params.test;
const request = spec.buildRequests(
bidRequest,
Object.assign({}, bidderRequest, {
gdprConsent: {
gdprApplies: true
}
})
);
let data = JSON.parse(request.data);
expect(data.regs.ext.gdpr).to.equal(1);
expect(data.user.ext.consent).to.equal('');
});
it('should include banner imp in request', () => {
const bidRequest = Object.assign([], bidRequests);
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.imp[0].banner).to.not.be.empty;
});
it('should include source.tid in request', () => {
const bidRequest = Object.assign([], bidRequests);
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.source.tid).to.equal('example-transaction-id');
});
it('should include bidfloor from floor module if avaiable', () => {
const bidRequest = Object.assign([], bidRequests);
bidRequest[0].getFloor = () => ({floor: 1.22});
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.imp[0].bidfloor).to.equal(1.22)
});
it('should use bidfloor from floor module if both floor module and bid floor avaiable', () => {
const bidRequest = Object.assign([], bidRequests);
bidRequest[0].getFloor = () => ({floor: 1.22});
bidRequest[0].params.bidfloor = 0.01;
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.imp[0].bidfloor).to.equal(1.22)
});
it('should include bidfloor in request if available', () => {
const bidRequest = Object.assign([], bidRequests);
bidRequest[0].params.bidfloor = 0.01;
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.imp[0].bidfloor).to.equal(0.01)
});
it('should include schain in request', () => {
const bidRequest = Object.assign([], bidRequests);
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.ext.schain).to.deep.equal({
'ver': '1.0',
'complete': 1,
'nodes': [
{
'asi': 'directseller.com',
'sid': '00001',
'rid': 'BidRequest1',
'hp': 1
}
]
});
});
it('should include source.tid in request', () => {
const bidRequest = Object.assign([], bidRequests);
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.source).to.have.deep.property('tid');
});
it('should not include invalid schain', () => {
const bidRequest = Object.assign([], bidRequests);
bidRequest[0].schain = {
'nodes': [{
'unknown_key': 1
}]
};
const request = spec.buildRequests(bidRequest, bidderRequest);
const data = JSON.parse(request.data);
expect(data.source).to.not.have.property('ext');
});
describe('native imp', () => {
function basicRequest(extension) {
return Object.assign({
bidder: 'bidder',
adUnitCode: 'adunit-code',
bidId: '1',
params: {
publisherId: 'PREBID_TEST',
region: 'prebid-eu',
test: 1
}
}, extension);
}
function buildImp(request) {
const resultRequest = spec.buildRequests([request], bidderRequest);
return JSON.parse(resultRequest.data).imp[0];
}
it('should extract native params when single mediaType', () => {
const imp = buildImp(basicRequest({
mediaType: 'native',
nativeParams: {
title: {
required: true,
len: 100
}
}
}));
expect(imp.native.request.assets[0]).to.deep.equal({
id: OPENRTB.NATIVE.ASSET_ID.TITLE,
required: 1,
title: {
len: 100
}
})
});
it('should extract native params when many mediaTypes', () => {
const imp = buildImp(basicRequest({
mediaTypes: {
native: {
title: {
len: 100
}
}
}
}));
expect(imp.native.request.assets[0]).to.deep.equal({
id: OPENRTB.NATIVE.ASSET_ID.TITLE,
required: 0,
title: {
len: 100
}
})
});
it('should not contain banner in imp', () => {
const imp = buildImp(basicRequest({
mediaTypes: {
native: {
title: {
required: true
}
}
}
}));
expect(imp.banner).to.be.undefined;
});
describe('image sizes', () => {
it('should parse single image size', () => {
const imp = buildImp(basicRequest({
mediaTypes: {
native: {
image: {
sizes: [300, 250]
}
}
}
}));
expect(imp.native.request.assets[0]).to.deep.equal({
id: OPENRTB.NATIVE.ASSET_ID.IMAGE,
required: 0,
img: {
w: 300,
h: 250,
type: OPENRTB.NATIVE.IMAGE_TYPE.MAIN,
}
})
});
it('should parse multiple image sizes', () => {
const imp = buildImp(basicRequest({
mediaTypes: {
native: {
image: {
sizes: [[300, 250], [100, 100]]
}
}
}
}));
expect(imp.native.request.assets[0]).to.deep.equal({
id: OPENRTB.NATIVE.ASSET_ID.IMAGE,
required: 0,
img: {
w: 300,
h: 250,
type: OPENRTB.NATIVE.IMAGE_TYPE.MAIN,
}
})
})
});
it('should parse aspect ratios with min_width', () => {
const imp = buildImp(basicRequest({
mediaTypes: {
native: {
icon: {
aspect_ratios: [{
min_width: 300,
ratio_width: 2,
ratio_height: 3,
}]
}
}
}
}));
expect(imp.native.request.assets[0]).to.deep.equal({
id: OPENRTB.NATIVE.ASSET_ID.ICON,
required: 0,
img: {
type: OPENRTB.NATIVE.IMAGE_TYPE.ICON,
wmin: 300,
hmin: 450,
}
})
});
it('should parse aspect ratios without min_width', () => {
const imp = buildImp(basicRequest({
mediaTypes: {
native: {
icon: {
aspect_ratios: [{
ratio_width: 2,
ratio_height: 3,
}]
}
}
}
}));
expect(imp.native.request.assets[0]).to.deep.equal({
id: OPENRTB.NATIVE.ASSET_ID.ICON,
required: 0,
img: {
type: OPENRTB.NATIVE.IMAGE_TYPE.ICON,
wmin: 100,
hmin: 150,
}
})
});
it('should handle all native assets', () => {
const imp = buildImp(basicRequest({
mediaTypes: {
native: {
title: {},
image: {},
icon: {},
sponsoredBy: {},
body: {},
cta: {},
}
}
}));
expect(imp.native.request.assets.length).to.equal(6);
imp.native.request.assets.forEach(asset => {
expect(asset.id).to.be.at.least(1)
})
});
});
});
describe('interpretResponse', function () {
let response = [{
'id': 'bidder_imp_identifier',
'impid': '552b8922e28f27',
'price': 0.5,
'adid': 'Ad_Identifier',
'adm': '<!-- test creative -->',
'adomain': ['rtbhouse.com'],
'cid': 'Ad_Identifier',
'w': 300,
'h': 250
}];
it('should get correct bid response', function () {
let expectedResponse = [
{
'requestId': '552b8922e28f27',
'cpm': 0.5,
'creativeId': 29681110,
'width': 300,
'height': 250,
'ad': '<!-- test creative -->',
'mediaType': 'banner',
'currency': 'USD',
'ttl': 300,
'meta': { advertiserDomains: ['rtbhouse.com'] },
'netRevenue': true
}
];
let bidderRequest;
let result = spec.interpretResponse({body: response}, {bidderRequest});
expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
});
it('handles nobid responses', function () {
let response = '';
let bidderRequest;
let result = spec.interpretResponse({body: response}, {bidderRequest});
expect(result.length).to.equal(0);
});
describe('native', () => {
const adm = {
native: {
ver: 1.1,
link: {
url: 'https://example.com'
},
imptrackers: [
'https://example.com/imptracker'
],
assets: [{
id: OPENRTB.NATIVE.ASSET_ID.TITLE,
required: 1,
title: {
text: 'Title text'
}
}, {
id: OPENRTB.NATIVE.ASSET_ID.IMAGE,
required: 1,
img: {
url: 'https://example.com/image.jpg',
w: 150,
h: 50
}
}, {
id: OPENRTB.NATIVE.ASSET_ID.BODY,
required: 0,
data: {
value: 'Body text'
}
}],
}
};
const response = [{
'id': 'id',
'impid': 'impid',
'price': 1,
'adid': 'adid',
'adm': JSON.stringify(adm),
'adomain': ['rtbhouse.com'],
'cid': 'cid',
'w': 1,
'h': 1
}];
it('should contain native assets in valid format', () => {
const bids = spec.interpretResponse({body: response}, {});
expect(bids[0].meta.advertiserDomains).to.deep.equal(['rtbhouse.com']);
expect(bids[0].native).to.deep.equal({
title: 'Title text',
clickUrl: encodeURIComponent('https://example.com'),
impressionTrackers: ['https://example.com/imptracker'],
image: {
url: encodeURIComponent('https://example.com/image.jpg'),
width: 150,
height: 50
},
body: 'Body text'
});
});
});
});
});