From ef00f9b681b7b2f4d507fd6e359d01a726facbbc Mon Sep 17 00:00:00 2001 From: prebidtappx <77485538+prebidtappx@users.noreply.github.com> Date: Fri, 16 Apr 2021 22:27:47 +0200 Subject: [PATCH] tappx Bid Adapter: add video instream support and update testing (#6580) * tappxBidAdapter : update tests adding video * tappxBidAdapter : add video instream * tappxBidAdapter : update tappx md doc * tappxBidAdapter: Fix Newline required eol-last * tappxBidAdapter: update tests User sync and video reqs * tappxBidAdapter: Extra space after fix Co-authored-by: marc_tappx --- modules/tappxBidAdapter.js | 81 +++++++++++++---- modules/tappxBidAdapter.md | 33 +++++++ test/spec/modules/tappxBidAdapter_spec.js | 102 ++++++++++++++++++++-- 3 files changed, 195 insertions(+), 21 deletions(-) diff --git a/modules/tappxBidAdapter.js b/modules/tappxBidAdapter.js index 3677c3ce4c9..1228fbafaad 100644 --- a/modules/tappxBidAdapter.js +++ b/modules/tappxBidAdapter.js @@ -2,20 +2,22 @@ import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; const BIDDER_CODE = 'tappx'; const TTL = 360; const CUR = 'USD'; -const TAPPX_BIDDER_VERSION = '0.1.10329'; +const TAPPX_BIDDER_VERSION = '0.1.10413'; const TYPE_CNN = 'prebidjs'; +const VIDEO_SUPPORT = ['instream']; + var HOST; var hostDomain; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER], + supportedMediaTypes: [BANNER, VIDEO], /** * Determines whether or not the given bid request is valid. @@ -24,11 +26,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function(bid) { - if ((bid.params == null) || (bid.params.endpoint == null) || (bid.params.tappxkey == null)) { - utils.logWarn(`[TAPPX]: Please review the mandatory Tappx parameters. ${JSON.stringify(bid)}`); - return false; - } - return true; + return validBasic(bid) && validMediaType(bid) }, /** @@ -63,7 +61,7 @@ export const spec = { const bids = []; responseBody.seatbid.forEach(serverSeatBid => { serverSeatBid.bid.forEach(serverBid => { - bids.push(interpretBannerBid(serverBid, originalRequest)); + bids.push(interpretBid(serverBid, originalRequest)); }); }); @@ -106,25 +104,66 @@ export const spec = { } } +function validBasic(bid) { + if ( + (bid.params == null) || + (bid.params.endpoint == null) || + (bid.params.tappxkey == null)) { + utils.logWarn(`[TAPPX]: Please review the mandatory Tappx parameters.`); + return false; + } + return true; +} + +function validMediaType(bid) { + const video = utils.deepAccess(bid, 'mediaTypes.video'); + + // Video validations + if (typeof video != 'undefined') { + if (VIDEO_SUPPORT.indexOf(video.context) === -1) { + utils.logWarn(`[TAPPX]: Please review the mandatory Tappx parameters for Video. Only "instream" is suported.`); + return false; + } + } + + return true; +} + /** * Parse the response and generate one bid object. * * @param {object} serverBid Bid by OpenRTB 2.5 * @returns {object} Prebid banner bidObject */ -function interpretBannerBid(serverBid, request) { - return { +function interpretBid(serverBid, request) { + let bidReturned = { requestId: request.bids.bidId, cpm: serverBid.price, currency: serverBid.cur ? serverBid.cur : CUR, width: serverBid.w, height: serverBid.h, - ad: serverBid.adm, ttl: TTL, creativeId: serverBid.crid, netRevenue: true, - mediaType: BANNER, } + + if (typeof serverBid.dealId != 'undefined') { bidReturned.dealId = serverBid.dealId } + + if (typeof request.bids.mediaTypes != 'undefined' && typeof request.bids.mediaTypes.video != 'undefined') { + bidReturned.vastXml = serverBid.adm; + bidReturned.vastUrl = serverBid.lurl; + bidReturned.ad = serverBid.adm; + bidReturned.mediaType = VIDEO; + } else { + bidReturned.ad = serverBid.adm; + bidReturned.mediaType = BANNER; + } + + if (typeof bidReturned.adomain != 'undefined' || bidReturned.adomain != null) { + bidReturned.meta = { advertiserDomains: request.bids.adomain }; + } + + return bidReturned; } /** @@ -136,14 +175,14 @@ function interpretBannerBid(serverBid, request) { */ function buildOneRequest(validBidRequests, bidderRequest) { HOST = utils.deepAccess(validBidRequests, 'params.host'); - let hostInfo = getHostInfo(HOST) - // hostDomain = HOST.split('/', 1)[0]; + let hostInfo = getHostInfo(HOST); hostDomain = hostInfo.domain; const ENDPOINT = utils.deepAccess(validBidRequests, 'params.endpoint'); const TAPPXKEY = utils.deepAccess(validBidRequests, 'params.tappxkey'); const BIDFLOOR = utils.deepAccess(validBidRequests, 'params.bidfloor'); const bannerMediaType = utils.deepAccess(validBidRequests, 'mediaTypes.banner'); + const videoMediaType = utils.deepAccess(validBidRequests, 'mediaTypes.video'); const { refererInfo } = bidderRequest; // let requests = []; @@ -205,6 +244,18 @@ function buildOneRequest(validBidRequests, bidderRequest) { imp.banner = banner; } + if (videoMediaType) { + let video = {}; + w = videoMediaType.playerSize[0][0]; + h = videoMediaType.playerSize[0][1]; + video.w = w; + video.h = h; + + video.mimes = videoMediaType.mimes; + + imp.video = video; + } + imp.id = validBidRequests.bidId; imp.tagid = tagid; imp.secure = 1; diff --git a/modules/tappxBidAdapter.md b/modules/tappxBidAdapter.md index d9ffd98b6c5..e6581a67d06 100644 --- a/modules/tappxBidAdapter.md +++ b/modules/tappxBidAdapter.md @@ -7,6 +7,7 @@ Maintainer: prebid@tappx.com # Description Module that connects to :tappx demand sources. +Suppots Banner and Instream Video. Please use ```tappx``` as the bidder code. Ads sizes available: [320,50], [300,250], [320,480], [1024,768], [728,90] @@ -35,3 +36,35 @@ Ads sizes available: [320,50], [300,250], [320,480], [1024,768], [728,90] } ]; ``` + + +# Video Test Parameters +``` + var adUnits = [ + { + code: 'video-ad-div', + renderer: { + options: { + text: "Tappx instream Video" + } + }, + mediaTypes: { + video: { + context: "instream", + mimes : [ "video/mp4", "application/javascript" ], + playerSize: [320, 250] + } + }, + bids: [{ + bidder: 'tappx', + params: { + host: "testing.ssp.tappx.com/rtb/v2/", + tappxkey: "pub-1234-desktop-1234", + endpoint: "VZ12TESTCTV", + bidfloor: 0.005, + test: true + } + }] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/tappxBidAdapter_spec.js b/test/spec/modules/tappxBidAdapter_spec.js index 1d3f9676d09..378b391a4eb 100644 --- a/test/spec/modules/tappxBidAdapter_spec.js +++ b/test/spec/modules/tappxBidAdapter_spec.js @@ -53,7 +53,7 @@ const c_BIDREQUEST = { } ] }; -const c_SERVERRESPONSE = { +const c_SERVERRESPONSE_B = { body: { id: '1c54b4f1-645f-44e6-b8ae-5d43c923ef1c', bidid: 'bid3811165568213389257', @@ -82,10 +82,40 @@ const c_SERVERRESPONSE = { }, headers: {} }; + +const c_SERVERRESPONSE_V = { + body: { + id: '1c54b4f1-645f-44e6-b8ae-5d43c923ef1c', + bidid: 'bid3811165568213389257', + seatbid: [ + { + seat: '1', + group: 0, + bid: [ + { + id: '3811165568213389257', + impid: 1, + price: 0.05, + adm: "Tappx<\/AdSystem>Tappx<\/AdTitle><\/Impression><\/Error>00:00:22<\/Duration><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/Tracking><\/TrackingEvents><\/ClickThrough><\/ClickTracking><\/VideoClicks><\/MediaFile><\/MediaFiles><\/Linear><\/Creative><\/Creatives><\/InLine><\/Ad><\/VAST>", + 'lurl': 'https:\/\/ssp.api.tappx.com\/rtb\/RTBv2Loss?id=5001829913749291152&ep=VZ12TESTCTV&au=test&bu=localhost&sz=6x6&pu=0.005&pt=0.01&cid=&crid=&adv=&aid=${AUCTION_ID}&bidid=${AUCTION_BID_ID}&impid=${AUCTION_IMP_ID}&sid=${AUCTION_SEAT_ID}&adid=${AUCTION_AD_ID}&ap=${AUCTION_PRICE}&cur=${AUCTION_CURRENCY}&mbr=${AUCTION_MBR}&l=${AUCTION_LOSS}', + cid: '01744fbb521e9fb10ffea926190effea', + crid: 'a13cf884e66e7c660afec059c89d98b6', + adomain: [ + ], + }, + ], + }, + ], + cur: 'USD', + }, + headers: {} +}; + const c_CONSENTSTRING = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; const c_VALIDBIDREQUESTS = [{'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com\/rtb\/v2\/', 'tappxkey': 'pub-1234-android-1234', 'endpoint': 'ZZ1234PBJS', 'bidfloor': 0.005, 'test': 1}, 'userId': {'haloId': '0000x179MZAzMqUWsFonu7Drm3eDDBMYtj5SPoWQnl89Upk3WTlCvEnKI9SshX0p6eFJ7otPYix179MZAzMqUWsFonu7Drm3eDDBMYtj5SPoWQnl89Upk3WTlCvEnKI9SshX0p6e', 'id5id': {'uid': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_rEXbz6UYtYEJelYrDaZOLkh8WcF9J0ZHmEHFKZEBlLXsgP6xqXU3BCj4Ay0Z6fw_jSOaHxMHwd-voRHqFA4Q9NwAxFcVLyPWnNGZ9VbcSAPos1wupq7Xu3MIm-Bw_0vxjhZdWNy4chM9x3i', 'ext': {'linkType': 0}}, 'intentIqId': 'GIF89a\u0000\u0000\u0000\u0000�\u0000\u0000���\u0000\u0000\u0000?�\u0000\u0000\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000A\u0000\u0000;', 'lotamePanoramaId': 'xTtLUY7GwqX2MMqSHo9RQ2YUOIBFhlASOR43I9KjvgtcrxIys3RxME96M02LTjWR', 'parrableId': {'eid': '02.YoqC9lWZh8.C8QTSiJTNgI6Pp0KCM5zZgEgwVMSsVP5W51X8cmiUHQESq9WRKB4nreqZJwsWIcNKlORhG4u25Wm6lmDOBmQ0B8hv0KP6uVQ97aouuH52zaz2ctVQTORUKkErPRPcaCJ7dKFcrNoF2i6WOR0S5Nk'}, 'pubcid': 'b1254-152f-12F5-5698-dI1eljK6C7WA', 'pubProvidedId': [{'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}]}, 'userIdAsEids': [{'source': 'audigent.com', 'uids': [{'id': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'atype': 1}]}, {'source': 'id5-sync.com', 'uids': [{'id': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'atype': 1, 'ext': {'linkType': 0}}]}], 'ortb2Imp': {'ext': {'data': {'adserver': {'name': 'gam', 'adslot': '/19968336/header-bid-tag-0'}, 'pbadslot': '/19968336/header-bid-tag-0'}}}, 'mediaTypes': {'banner': {'sizes': [[320, 480], [320, 50]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '71c0d86b-4b47-4aff-a6da-1af0b1712439', 'sizes': [[320, 480], [320, 50]], 'bidId': '264d7969b125a5', 'bidderRequestId': '1c674c14a3889c', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}]; const c_VALIDBIDAPPREQUESTS = [{'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com\/rtb\/v2\/', 'tappxkey': 'pub-1234-android-1234', 'endpoint': 'ZZ1234PBJS', 'bidfloor': 0.005, 'test': 1, 'app': {'name': 'Tappx Test', 'bundle': 'com.test.tappx', 'domain': 'tappx.com', 'publisher': { 'name': 'Tappx', 'domain': 'tappx.com' }}}, 'userId': {'haloId': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'id5id': {'uid': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'ext': {'linkType': 0}}, 'intentIqId': 'GIF89a\u0001\u0000\u0001\u0000�\u0000\u0000���\u0000\u0000\u0000!�\u0004\u0001\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;', 'lotamePanoramaId': '8003916b61a95b185690ec103bdf4945a70213e01818a5e5d8690b542730755a', 'parrableId': {'eid': '01.1617088921.7faa68d9570a50ea8e4f359e9b99ca4b7509e948a6175b3e5b0b8cbaf5b62424104ccfb0191ca79366de8368ed267b89a68e236df5f41f96f238e4301659e9023fec05e46399fb1ad0a0'}, 'pubcid': 'b7143795-852f-42f0-8864-5ecbea1ade4e', 'pubProvidedId': [{'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}]}, 'userIdAsEids': [{'source': 'audigent.com', 'uids': [{'id': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'atype': 1}]}, {'source': 'id5-sync.com', 'uids': [{'id': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'atype': 1, 'ext': {'linkType': 0}}]}, {'source': 'intentiq.com', 'uids': [{'id': 'GIF89a\u0001\u0000\u0001\u0000�\u0000\u0000���\u0000\u0000\u0000!�\u0004\u0001\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;', 'atype': 1}]}, {'source': 'crwdcntrl.net', 'uids': [{'id': '8003916b61a95b185690ec103bdf4945a70213e01818a5e5d8690b542730755a', 'atype': 1}]}, {'source': 'parrable.com', 'uids': [{'id': '01.1617088921.7faa68d9570a50ea8e4f359e9b99ca4b7509e948a6175b3e5b0b8cbaf5b62424104ccfb0191ca79366de8368ed267b89a68e236df5f41f96f238e4301659e9023fec05e46399fb1ad0a0', 'atype': 1}]}, {'source': 'pubcid.org', 'uids': [{'id': 'b7143795-852f-42f0-8864-5ecbea1ade4e', 'atype': 1}]}, {'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}], 'ortb2Imp': {'ext': {'data': {'adserver': {'name': 'gam', 'adslot': '/19968336/header-bid-tag-0'}, 'pbadslot': '/19968336/header-bid-tag-0'}}}, 'mediaTypes': {'banner': {'sizes': [[320, 480], [320, 50]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '71c0d86b-4b47-4aff-a6da-1af0b1712439', 'sizes': [[320, 480], [320, 50]], 'bidId': '264d7969b125a5', 'bidderRequestId': '1c674c14a3889c', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}]; -const c_BIDDERREQUEST = {'bidderCode': 'tappx', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'bidderRequestId': '1c674c14a3889c', 'bids': [{'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com\/rtb\/v2\/', 'tappxkey': 'pub-1234-android-1234', 'endpoint': 'ZZ1234PBJS', 'bidfloor': 0.005, 'test': 1}, 'userId': {'haloId': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'id5id': {'uid': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'ext': {'linkType': 0}}, 'intentIqId': 'GIF89a\u0000\u0000\u0000\u0000�\u0000\u0000���\u0000\u0000\u0000?�\u0000\u0000\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000A\u0000\u0000;', 'lotamePanoramaId': '8003916b61a95b185690ec103bdf4945a70213e01818a5e5d8690b542730755a', 'parrableId': {'eid': '01.1617088921.7faa68d9570a50ea8e4f359e9b99ca4b7509e948a6175b3e5b0b8cbaf5b62424104ccfb0191ca79366de8368ed267b89a68e236df5f41f96f238e4301659e9023fec05e46399fb1ad0a0'}, 'pubcid': 'b7143795-852f-42f0-8864-5ecbea1ade4e', 'pubProvidedId': [{'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}]}, 'userIdAsEids': [{'source': 'audigent.com', 'uids': [{'id': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'atype': 1}]}, {'source': 'id5-sync.com', 'uids': [{'id': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'atype': 1, 'ext': {'linkType': 0}}]}], 'ortb2Imp': {'ext': {'data': {'adserver': {'name': 'gam', 'adslot': '/19968336/header-bid-tag-0'}, 'pbadslot': '/19968336/header-bid-tag-0'}}}, 'mediaTypes': {'banner': {'sizes': [[320, 480], [320, 50]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '71c0d86b-4b47-4aff-a6da-1af0b1712439', 'sizes': [[320, 480], [320, 50]], 'bidId': '264d7969b125a5', 'bidderRequestId': '1c674c14a3889c', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}], 'auctionStart': 1617088922120, 'timeout': 700, 'refererInfo': {'referer': 'http://localhost:9999/integrationExamples/gpt/gdpr_hello_world.html?pbjs_debug=true', 'reachedTop': true, 'isAmp': false, 'numIframes': 0, 'stack': ['http://localhost:9999/integrationExamples/gpt/gdpr_hello_world.html?pbjs_debug=true'], 'canonicalUrl': null}, 'gdprConsent': {'consentString': c_CONSENTSTRING, 'vendorData': {'metadata': 'BO-JeiTPABAOkAAABAENABA', 'gdprApplies': true, 'hasGlobalScope': false, 'cookieVersion': 1, 'created': '2020-12-09T09:22:09.900Z', 'lastUpdated': '2021-01-14T15:44:03.600Z', 'cmpId': 0, 'cmpVersion': 1, 'consentScreen': 0, 'consentLanguage': 'EN', 'vendorListVersion': 1, 'maxVendorId': 0, 'purposeConsents': {}, 'vendorConsents': {}}, 'gdprApplies': true, 'apiVersion': 1}, 'uspConsent': '1YCC', 'start': 1611308859099}; +const c_BIDDERREQUEST_B = {'bidderCode': 'tappx', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'bidderRequestId': '1c674c14a3889c', 'bids': [{'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com\/rtb\/v2\/', 'tappxkey': 'pub-1234-android-1234', 'endpoint': 'ZZ1234PBJS', 'bidfloor': 0.005, 'test': 1}, 'userId': {'haloId': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'id5id': {'uid': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'ext': {'linkType': 0}}, 'intentIqId': 'GIF89a\u0000\u0000\u0000\u0000�\u0000\u0000���\u0000\u0000\u0000?�\u0000\u0000\u0000\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000A\u0000\u0000;', 'lotamePanoramaId': '8003916b61a95b185690ec103bdf4945a70213e01818a5e5d8690b542730755a', 'parrableId': {'eid': '01.1617088921.7faa68d9570a50ea8e4f359e9b99ca4b7509e948a6175b3e5b0b8cbaf5b62424104ccfb0191ca79366de8368ed267b89a68e236df5f41f96f238e4301659e9023fec05e46399fb1ad0a0'}, 'pubcid': 'b7143795-852f-42f0-8864-5ecbea1ade4e', 'pubProvidedId': [{'source': 'domain.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 1, 'ext': {'stype': 'ppuid'}}]}, {'source': '3rdpartyprovided.com', 'uids': [{'id': 'value read from cookie or local storage', 'atype': 3, 'ext': {'stype': 'sha256email'}}]}]}, 'userIdAsEids': [{'source': 'audigent.com', 'uids': [{'id': '0000fgclxw05ycn0608xiyi90bwpa0c0evvlif0hv1x0i0ku88il0ntek0o0qskvir0trr70u0wqxiix0zq3u1012pa5j315ogh1618nmsj91bmt41c1elzfjf1hl5r1i1kkc2jl', 'atype': 1}]}, {'source': 'id5-sync.com', 'uids': [{'id': 'ID5@iu-PJX_OQ0d6FJjKS8kYfUpHriD_qpoXJUngedfpNva812If1fHEqHHkamLC89txVxk1i9WGqeQrTX97HFCgv9QDa1M_bkHUBsAWFm-D5r1rYrsfMFFiyqwCAEzqNbvsUZXOYCAQSjPcLxR4of22w-U9_JDRThCGRDV3Fmvc38E', 'atype': 1, 'ext': {'linkType': 0}}]}], 'ortb2Imp': {'ext': {'data': {'adserver': {'name': 'gam', 'adslot': '/19968336/header-bid-tag-0'}, 'pbadslot': '/19968336/header-bid-tag-0'}}}, 'mediaTypes': {'banner': {'sizes': [[320, 480], [320, 50]]}}, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '71c0d86b-4b47-4aff-a6da-1af0b1712439', 'sizes': [[320, 480], [320, 50]], 'bidId': '264d7969b125a5', 'bidderRequestId': '1c674c14a3889c', 'auctionId': '13a8a3a9-ed3a-4101-9435-4699ee77bb62', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}], 'auctionStart': 1617088922120, 'timeout': 700, 'refererInfo': {'referer': 'http://localhost:9999/integrationExamples/gpt/gdpr_hello_world.html?pbjs_debug=true', 'reachedTop': true, 'isAmp': false, 'numIframes': 0, 'stack': ['http://localhost:9999/integrationExamples/gpt/gdpr_hello_world.html?pbjs_debug=true'], 'canonicalUrl': null}, 'gdprConsent': {'consentString': c_CONSENTSTRING, 'vendorData': {'metadata': 'BO-JeiTPABAOkAAABAENABA', 'gdprApplies': true, 'hasGlobalScope': false, 'cookieVersion': 1, 'created': '2020-12-09T09:22:09.900Z', 'lastUpdated': '2021-01-14T15:44:03.600Z', 'cmpId': 0, 'cmpVersion': 1, 'consentScreen': 0, 'consentLanguage': 'EN', 'vendorListVersion': 1, 'maxVendorId': 0, 'purposeConsents': {}, 'vendorConsents': {}}, 'gdprApplies': true, 'apiVersion': 1}, 'uspConsent': '1YCC', 'start': 1611308859099}; +const c_BIDDERREQUEST_V = {'method': 'POST', 'url': 'https://testing.ssp.tappx.com/rtb/v2//VZ12TESTCTV?type_cnn=prebidjs&v=0.1.10329', 'data': '{"site":{"name":"localhost","bundle":"localhost","domain":"localhost"},"user":{"ext":{}},"id":"e807363f-3095-43a8-a4a6-f44196cb7318","test":1,"at":1,"tmax":1000,"bidder":"tappx","imp":[{"video":{"w":320,"h":250,"mimes":["video/mp4","application/javascript"]},"id":"28f49c71b13f2f","tagid":"localhost_typeAdBanVid_windows","secure":1,"bidfloor":0.005,"ext":{"bidder":{"tappxkey":"pub-1234-desktop-1234","endpoint":"VZ12TESTCTV","host":"testing.ssp.tappx.com/rtb/v2/"}}}],"device":{"os":"windows","ip":"peer","ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","h":864,"w":1536,"dnt":0,"language":"en","make":"Google Inc."},"params":{"host":"tappx.com","bidfloor":0.005},"regs":{"gdpr":0,"ext":{}}}', 'bids': {'bidder': 'tappx', 'params': {'host': 'testing.ssp.tappx.com/rtb/v2/', 'tappxkey': 'pub-1234-desktop-1234', 'endpoint': 'VZ12TESTCTV', 'bidfloor': 0.005, 'test': true}, 'crumbs': {'pubcid': 'dccfe922-3823-4676-b7b2-e5ed8743154e'}, 'ortb2Imp': {'ext': {'data': {'pbadslot': 'video-ad-div'}}}, 'renderer': {'options': {'text': 'Tappx Outstream Video'}}, 'mediaTypes': {'video': {'context': 'instream', 'mimes': ['video/mp4', 'application/javascript'], 'playerSize': [[320, 250]]}}, 'adUnitCode': 'video-ad-div', 'transactionId': 'ed41c805-d14c-49c3-954d-26b98b2aa2c2', 'sizes': [[320, 250]], 'bidId': '28f49c71b13f2f', 'bidderRequestId': '1401710496dc7', 'auctionId': 'e807363f-3095-43a8-a4a6-f44196cb7318', 'src': 'client', 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0}} describe('Tappx bid adapter', function () { /** @@ -102,6 +132,16 @@ describe('Tappx bid adapter', function () { delete badBidRequest.bids[0].params.endpoint; assert.isFalse(spec.isBidRequestValid(badBidRequest.bids[0])); }); + + it('should return false for not instream requests', function () { + let badBidRequest_v = c_BIDDERREQUEST_V; + delete badBidRequest_v.bids.mediaTypes.banner; + badBidRequest_v.bids.mediaTypes.video = {}; + badBidRequest_v.bids.mediaTypes.video.context = 'outstream'; + badBidRequest_v.bids.mediaTypes.video.mimes = [ 'video/mp4', 'application/javascript' ]; + badBidRequest_v.bids.mediaTypes.video.playerSize = [320, 250]; + assert.isFalse(spec.isBidRequestValid(badBidRequest_v.bids)); + }); }); /** @@ -110,10 +150,12 @@ describe('Tappx bid adapter', function () { describe('buildRequest', function () { // Web Test let validBidRequests = c_VALIDBIDREQUESTS; + let validBidRequests_V = c_VALIDBIDREQUESTS; // App Test let validAppBidRequests = c_VALIDBIDAPPREQUESTS; - let bidderRequest = c_BIDDERREQUEST; + let bidderRequest = c_BIDDERREQUEST_B; + let bidderRequest_V = c_BIDDERREQUEST_V; it('should add gdpr/usp consent information to the request', function () { const request = spec.buildRequests(validBidRequests, bidderRequest); @@ -138,6 +180,20 @@ describe('Tappx bid adapter', function () { expect(data.imp[0].banner.h).to.be.oneOf([320, 50, 250, 480]); }); + it('should properly build a video request', function () { + const request = spec.buildRequests(validBidRequests_V, bidderRequest_V); + expect(request[0].url).to.match(/^(http|https):\/\/(.*)\.tappx\.com\/.+/); + expect(request[0].method).to.equal('POST'); + + const data = JSON.parse(request[0].data); + expect(data.site).to.not.equal(null); + expect(data.imp).to.have.lengthOf(1); + expect(data.imp[0].bidfloor, data).to.not.be.null; + expect(data.imp[0].banner).to.not.equal(null); + expect(data.imp[0].banner.w).to.be.oneOf([320, 50, 250, 480]); + expect(data.imp[0].banner.h).to.be.oneOf([320, 50, 250, 480]); + }); + it('should set user eids array', function () { const request = spec.buildRequests(validBidRequests, bidderRequest); @@ -165,17 +221,51 @@ describe('Tappx bid adapter', function () { * INTERPRET RESPONSE TESTS */ describe('interpretResponse', function () { - it('receive reponse with single placement', function () { - const bids = spec.interpretResponse(c_SERVERRESPONSE, c_BIDREQUEST); + it('receive banner reponse with single placement', function () { + const bids = spec.interpretResponse(c_SERVERRESPONSE_B, c_BIDDERREQUEST_B); const bid = bids[0]; expect(bid.cpm).to.exist; expect(bid.ad).to.match(/^