diff --git a/modules/platformioBidAdapter.js b/modules/platformioBidAdapter.js index 93907c9bb1a..3c53022189f 100644 --- a/modules/platformioBidAdapter.js +++ b/modules/platformioBidAdapter.js @@ -1,220 +1,226 @@ - -import {logError, getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; - -const NATIVE_DEFAULTS = { - TITLE_LEN: 100, - DESCR_LEN: 200, - SPONSORED_BY_LEN: 50, - IMG_MIN: 150, - ICON_MIN: 50, -}; - -export const spec = { - - code: 'platformio', - supportedMediaTypes: ['native'], - - isBidRequestValid: bid => ( - !!(bid && bid.params && bid.params.pubId && bid.params.siteId) - ), - buildRequests: bidRequests => { - const request = { - id: bidRequests[0].bidderRequestId, - at: 2, - imp: bidRequests.map(slot => impression(slot)), - site: site(bidRequests), - device: device(), - }; - return { - method: 'POST', - url: '//piohbdisp.hb.adx1.com/', - data: JSON.stringify(request), - }; - }, - interpretResponse: (response, request) => ( - bidResponseAvailable(request, response.body) - ), -}; - -function bidResponseAvailable(bidRequest, bidResponse) { - const idToImpMap = {}; - const idToBidMap = {}; - const ortbRequest = parse(bidRequest.data); - ortbRequest.imp.forEach(imp => { - idToImpMap[imp.id] = imp; - }); - if (bidResponse) { - bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { - idToBidMap[bid.impid] = bid; - })); - } - const bids = []; - Object.keys(idToImpMap).forEach(id => { - if (idToBidMap[id]) { - const bid = {}; - bid.requestId = id; - bid.adId = id; - bid.creativeId = id; - bid.cpm = idToBidMap[id].price; - bid.currency = bidResponse.cur; - bid.ttl = 360; - bid.netRevenue = true; - if (idToImpMap[id]['native']) { - bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); - let nurl = idToBidMap[id].nurl; - nurl = nurl.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); - nurl = nurl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); - nurl = nurl.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); - nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); - bid['native']['impressionTrackers'] = [nurl]; - bid.mediaType = 'native'; - } else { - bid.ad = idToBidMap[id].adm; - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); - bid.width = idToImpMap[id].banner.w; - bid.height = idToImpMap[id].banner.h; - } - bids.push(bid); - } - }); - return bids; -} -function impression(slot) { - return { - id: slot.bidId, - banner: banner(slot), - 'native': nativeImpression(slot), - bidfloor: slot.params.bidFloor || '0.000001', - tagid: slot.params.placementId.toString(), - }; -} -function banner(slot) { - if (!slot.nativeParams) { - const size = slot.params.size.toUpperCase().split('X'); - const width = parseInt(size[0]); - const height = parseInt(size[1]); - return { - w: width, - h: height, - }; - }; -} - -function nativeImpression(slot) { - if (slot.nativeParams) { - const assets = []; - addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); - addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); - addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); - addAsset(assets, imageAsset(4, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); - addAsset(assets, imageAsset(5, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); - return { - request: JSON.stringify({ assets }), - ver: '1.1', - }; - } - return null; -} - -function addAsset(assets, asset) { - if (asset) { - assets.push(asset); - } -} - -function titleAsset(id, params, defaultLen) { - if (params) { - return { - id, - required: params.required ? 1 : 0, - title: { - len: params.len || defaultLen, - }, - }; - } - return null; -} - -function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { - return params ? { - id, - required: params.required ? 1 : 0, - img: { - type, - wmin: params.wmin || defaultMinWidth, - hmin: params.hmin || defaultMinHeight, - } - } : null; -} - -function dataAsset(id, params, type, defaultLen) { - return params ? { - id, - required: params.required ? 1 : 0, - data: { - type, - len: params.len || defaultLen, - } - } : null; -} - -function site(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; - const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; - return { - publisher: { - id: pubId.toString(), - domain: getTopWindowLocation().hostname, - }, - id: siteId.toString(), - ref: getTopWindowReferrer(), - page: getTopWindowLocation().href, - } -} - -function device() { - return { - ua: navigator.userAgent, - language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), - w: (window.screen.width || window.innerWidth), - h: (window.screen.height || window.innerHeigh), - }; -} -function parse(rawResponse) { - try { - if (rawResponse) { - return JSON.parse(rawResponse); - } - } catch (ex) { - logError('platformio.parse', 'ERROR', ex); - } - return null; -} - -function nativeResponse(imp, bid) { - if (imp['native']) { - const nativeAd = parse(bid.adm); - const keys = {}; - if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { - nativeAd['native'].assets.forEach(asset => { - keys.title = asset.title ? asset.title.text : keys.title; - keys.body = asset.data && asset.id === 2 ? asset.data.value : keys.body; - keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; - keys.icon = asset.img && asset.id === 4 ? asset.img.url : keys.icon; - keys.image = asset.img && asset.id === 5 ? asset.img.url : keys.image; - }); - if (nativeAd['native'].link) { - keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); - } - return keys; - } - } - return null; -} - -registerBidder(spec); + +import {logError, getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const NATIVE_DEFAULTS = { + TITLE_LEN: 100, + DESCR_LEN: 200, + SPONSORED_BY_LEN: 50, + IMG_MIN: 150, + ICON_MIN: 50, +}; + +export const spec = { + + code: 'platformio', + supportedMediaTypes: ['banner', 'native'], + + isBidRequestValid: bid => ( + !!(bid && bid.params && bid.params.pubId && bid.params.siteId) + ), + buildRequests: bidRequests => { + const request = { + id: bidRequests[0].bidderRequestId, + at: 2, + imp: bidRequests.map(slot => impression(slot)), + site: site(bidRequests), + device: device(), + }; + return { + method: 'POST', + url: '//piohbdisp.hb.adx1.com/', + data: JSON.stringify(request), + }; + }, + interpretResponse: (response, request) => ( + bidResponseAvailable(request, response.body) + ), +}; + +function bidResponseAvailable(bidRequest, bidResponse) { + const idToImpMap = {}; + const idToBidMap = {}; + const ortbRequest = parse(bidRequest.data); + ortbRequest.imp.forEach(imp => { + idToImpMap[imp.id] = imp; + }); + if (bidResponse) { + bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { + idToBidMap[bid.impid] = bid; + })); + } + const bids = []; + Object.keys(idToImpMap).forEach(id => { + if (idToBidMap[id]) { + const bid = {}; + bid.requestId = id; + bid.adId = id; + bid.creativeId = id; + bid.cpm = idToBidMap[id].price; + bid.currency = bidResponse.cur; + bid.ttl = 360; + bid.netRevenue = true; + if (idToImpMap[id]['native']) { + bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); + let nurl = idToBidMap[id].nurl; + nurl = nurl.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid['native']['impressionTrackers'] = [nurl]; + bid.mediaType = 'native'; + } else { + bid.ad = idToBidMap[id].adm; + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid.width = idToImpMap[id].banner.w; + bid.height = idToImpMap[id].banner.h; + } + bids.push(bid); + } + }); + return bids; +} +function impression(slot) { + return { + id: slot.bidId, + banner: banner(slot), + 'native': nativeImpression(slot), + bidfloor: slot.params.bidFloor || '0.000001', + tagid: slot.params.placementId.toString(), + }; +} +function banner(slot) { + if (!slot.nativeParams) { + const size = slot.params.size.toUpperCase().split('X'); + const width = parseInt(size[0]); + const height = parseInt(size[1]); + return { + w: width, + h: height, + }; + }; +} + +function nativeImpression(slot) { + if (slot.nativeParams) { + const assets = []; + addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); + addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); + addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); + addAsset(assets, imageAsset(4, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); + addAsset(assets, imageAsset(5, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); + return { + request: JSON.stringify({ assets }), + ver: '1.1', + }; + } + return null; +} + +function addAsset(assets, asset) { + if (asset) { + assets.push(asset); + } +} + +function titleAsset(id, params, defaultLen) { + if (params) { + return { + id, + required: params.required ? 1 : 0, + title: { + len: params.len || defaultLen, + }, + }; + } + return null; +} + +function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { + return params ? { + id, + required: params.required ? 1 : 0, + img: { + type, + wmin: params.wmin || defaultMinWidth, + hmin: params.hmin || defaultMinHeight, + } + } : null; +} + +function dataAsset(id, params, type, defaultLen) { + return params ? { + id, + required: params.required ? 1 : 0, + data: { + type, + len: params.len || defaultLen, + } + } : null; +} + +function site(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; + const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; + return { + publisher: { + id: pubId.toString(), + domain: getTopWindowLocation().hostname, + }, + id: siteId.toString(), + ref: getTopWindowReferrer(), + page: getTopWindowLocation().href, + } +} + +function device() { + return { + ua: navigator.userAgent, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), + w: (window.screen.width || window.innerWidth), + h: (window.screen.height || window.innerHeigh), + }; +} +function parse(rawResponse) { + try { + if (rawResponse) { + return JSON.parse(rawResponse); + } + } catch (ex) { + logError('platformio.parse', 'ERROR', ex); + } + return null; +} + +function nativeResponse(imp, bid) { + if (imp['native']) { + const nativeAd = parse(bid.adm); + const keys = {}; + keys.image = {}; + keys.icon = {}; + if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { + nativeAd['native'].assets.forEach(asset => { + keys.title = asset.title ? asset.title.text : keys.title; + keys.body = asset.data && asset.id === 2 ? asset.data.value : keys.body; + keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; + keys.icon.url = asset.img && asset.id === 4 ? asset.img.url : keys.icon.url; + keys.icon.width = asset.img && asset.id === 4 ? asset.img.w : keys.icon.width; + keys.icon.height = asset.img && asset.id === 4 ? asset.img.h : keys.icon.height; + keys.image.url = asset.img && asset.id === 5 ? asset.img.url : keys.image.url; + keys.image.width = asset.img && asset.id === 5 ? asset.img.w : keys.image.width; + keys.image.height = asset.img && asset.id === 5 ? asset.img.h : keys.image.height; + }); + if (nativeAd['native'].link) { + keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); + } + return keys; + } + } + return null; +} + +registerBidder(spec); diff --git a/modules/platformioBidAdapter.md b/modules/platformioBidAdapter.md index 81ac81380b0..4ef0aa755bf 100644 --- a/modules/platformioBidAdapter.md +++ b/modules/platformioBidAdapter.md @@ -21,7 +21,7 @@ Please use ```platformio``` as the bidder code. pubId: '29521', // required siteId: '26047', // required size: '250X250', // required - placementId: '123', + placementId: '123', // required bidFloor: '0.001' } }] @@ -40,7 +40,7 @@ Please use ```platformio``` as the bidder code. params: { pubId: '29521', // required siteId: '26047', // required - placementId: '123', + placementId: '123', // required bidFloor: '0.001' } }] diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index 7caca2e0d17..c69a31f1ec5 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -1,205 +1,211 @@ -import {expect} from 'chai'; -import {spec} from 'modules/platformioBidAdapter'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('Platform.io Adapter Tests', () => { - const slotConfigs = [{ - placementCode: '/DfpAccount1/slot1', - bidId: 'bid12345', - params: { - pubId: '29521', - siteId: '26047', - placementId: '123', - size: '300x250', - bidFloor: '0.001' - } - }, { - placementCode: '/DfpAccount2/slot2', - bidId: 'bid23456', - params: { - pubId: '29521', - siteId: '26047', - placementId: '1234', - size: '728x90', - bidFloor: '0.000001' - } - }]; - const nativeSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - nativeParams: { - title: { required: true, len: 200 }, - body: {}, - image: { wmin: 100 }, - sponsoredBy: { }, - icon: { } - }, - params: { - pubId: '29521', - placementId: '123', - siteId: '26047' - } - }]; - - it('Verify build request', () => { - const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.not.equal(null); - expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('29521'); - expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); - expect(ortbRequest.imp).to.have.lengthOf(2); - // device object - expect(ortbRequest.device).to.not.equal(null); - expect(ortbRequest.device.ua).to.equal(navigator.userAgent); - // slot 1 - expect(ortbRequest.imp[0].tagid).to.equal('123'); - expect(ortbRequest.imp[0].banner).to.not.equal(null); - expect(ortbRequest.imp[0].banner.w).to.equal(300); - expect(ortbRequest.imp[0].banner.h).to.equal(250); - expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); - // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('1234'); - expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(728); - expect(ortbRequest.imp[1].banner.h).to.equal(90); - expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); - }); - - it('Verify parse response', () => { - const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: 'This is an Ad' - }] - }], - cur: 'USD' - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.ad).to.equal('This is an Ad'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.adId).to.equal('bid12345'); - expect(bid.creativeId).to.equal('bid12345'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(360); - }); - - it('Verify full passback', () => { - const request = spec.buildRequests(slotConfigs); - const bids = spec.interpretResponse({ body: null }, request) - expect(bids).to.have.lengthOf(0); - }); - - it('Verify Native request', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // // native impression - expect(ortbRequest.imp[0].tagid).to.equal('123'); - const nativePart = ortbRequest.imp[0]['native']; - expect(nativePart).to.not.equal(null); - expect(nativePart.ver).to.equal('1.1'); - expect(nativePart.request).to.not.equal(null); - // native request assets - const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); - expect(nativeRequest).to.not.equal(null); - expect(nativeRequest.assets).to.have.lengthOf(5); - expect(nativeRequest.assets[0].id).to.equal(1); - expect(nativeRequest.assets[1].id).to.equal(2); - expect(nativeRequest.assets[2].id).to.equal(3); - expect(nativeRequest.assets[3].id).to.equal(4); - expect(nativeRequest.assets[4].id).to.equal(5); - expect(nativeRequest.assets[0].required).to.equal(1); - expect(nativeRequest.assets[0].title).to.not.equal(null); - expect(nativeRequest.assets[0].title.len).to.equal(200); - expect(nativeRequest.assets[1].title).to.be.undefined; - expect(nativeRequest.assets[1].data).to.not.equal(null); - expect(nativeRequest.assets[1].data.type).to.equal(2); - expect(nativeRequest.assets[1].data.len).to.equal(200); - expect(nativeRequest.assets[2].required).to.equal(0); - expect(nativeRequest.assets[3].img).to.not.equal(null); - expect(nativeRequest.assets[3].img.wmin).to.equal(50); - expect(nativeRequest.assets[3].img.hmin).to.equal(50); - expect(nativeRequest.assets[3].img.type).to.equal(1); - expect(nativeRequest.assets[4].img).to.not.equal(null); - expect(nativeRequest.assets[4].img.wmin).to.equal(100); - expect(nativeRequest.assets[4].img.hmin).to.equal(150); - expect(nativeRequest.assets[4].img.type).to.equal(3); - }); - - it('Verify Native response', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - const nativeResponse = { - 'native': { - assets: [ - { id: 1, title: { text: 'Ad Title' } }, - { id: 2, data: { value: 'Test description' } }, - { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png' } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png' } } - ], - link: { url: 'http://brand.com/' } - } - }; - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - nurl: 'http://rtb.adx1.com/log', - adm: JSON.stringify(nativeResponse) - }] - }], - cur: 'USD', - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - // verify bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.adId).to.equal('bid12345'); - expect(bid.ad).to.be.undefined; - expect(bid.mediaType).to.equal('native'); - const nativeBid = bid['native']; - expect(nativeBid).to.not.equal(null); - expect(nativeBid.title).to.equal('Ad Title'); - expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); - expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); - expect(nativeBid.impressionTrackers).to.have.lengthOf(1); - expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); - }); - - it('Verifies bidder code', () => { - expect(spec.code).to.equal('platformio'); - }); - - it('Verifies supported media types', () => { - expect(spec.supportedMediaTypes).to.have.lengthOf(1); - expect(spec.supportedMediaTypes[0]).to.equal('native'); - }); - - it('Verifies if bid request valid', () => { - expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); - }); -}); + +import {expect} from 'chai'; +import {spec} from 'modules/platformioBidAdapter'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; + +describe('Platform.io Adapter Tests', () => { + const slotConfigs = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + pubId: '29521', + siteId: '26047', + placementId: '123', + size: '300x250', + bidFloor: '0.001' + } + }, { + placementCode: '/DfpAccount2/slot2', + bidId: 'bid23456', + params: { + pubId: '29521', + siteId: '26047', + placementId: '1234', + size: '728x90', + bidFloor: '0.000001' + } + }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + nativeParams: { + title: { required: true, len: 200 }, + body: {}, + image: { wmin: 100 }, + sponsoredBy: { }, + icon: { } + }, + params: { + pubId: '29521', + placementId: '123', + siteId: '26047' + } + }]; + + it('Verify build request', () => { + const request = spec.buildRequests(slotConfigs); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.publisher).to.not.equal(null); + expect(ortbRequest.site.publisher.id).to.equal('29521'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); + expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.imp).to.have.lengthOf(2); + // device object + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(ortbRequest.imp[0].tagid).to.equal('123'); + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); + // slot 2 + expect(ortbRequest.imp[1].tagid).to.equal('1234'); + expect(ortbRequest.imp[1].banner).to.not.equal(null); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); + expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); + }); + + it('Verify parse response', () => { + const request = spec.buildRequests(slotConfigs); + const ortbRequest = JSON.parse(request.data); + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'This is an Ad' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('This is an Ad'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + + it('Verify full passback', () => { + const request = spec.buildRequests(slotConfigs); + const bids = spec.interpretResponse({ body: null }, request) + expect(bids).to.have.lengthOf(0); + }); + + it('Verify Native request', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // // native impression + expect(ortbRequest.imp[0].tagid).to.equal('123'); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(5); + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[3].id).to.equal(4); + expect(nativeRequest.assets[4].id).to.equal(5); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(2); + expect(nativeRequest.assets[1].data.len).to.equal(200); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[3].img).to.not.equal(null); + expect(nativeRequest.assets[3].img.wmin).to.equal(50); + expect(nativeRequest.assets[3].img.hmin).to.equal(50); + expect(nativeRequest.assets[3].img.type).to.equal(1); + expect(nativeRequest.assets[4].img).to.not.equal(null); + expect(nativeRequest.assets[4].img.wmin).to.equal(100); + expect(nativeRequest.assets[4].img.hmin).to.equal(150); + expect(nativeRequest.assets[4].img.type).to.equal(3); + }); + + it('Verify Native response', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { id: 1, title: { text: 'Ad Title' } }, + { id: 2, data: { value: 'Test description' } }, + { id: 3, data: { value: 'Brand' } }, + { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + ], + link: { url: 'http://brand.com/' } + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + nurl: 'http://rtb.adx1.com/log', + adm: JSON.stringify(nativeResponse) + }] + }], + cur: 'USD', + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Brand'); + expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.image.width).to.equal(300); + expect(nativeBid.image.height).to.equal(300); + expect(nativeBid.icon.width).to.equal(100); + expect(nativeBid.icon.height).to.equal(100); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(1); + expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); + }); + + it('Verifies bidder code', () => { + expect(spec.code).to.equal('platformio'); + }); + + it('Verifies supported media types', () => { + expect(spec.supportedMediaTypes).to.have.lengthOf(2); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); + expect(spec.supportedMediaTypes[1]).to.equal('native'); + }); + + it('Verifies if bid request valid', () => { + expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + }); +});