From e848cab2ff7e3de7939a45954893c334296ad154 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Tue, 4 Dec 2018 14:12:36 -0500 Subject: [PATCH] initial version of ozone adapter for review (#3307) * initial version of ozone adapter for review * updates made per prebid.org feedback * Added a new line as failed prebid.org automated test * Unit Tests for Ozone Adaptor * updated URIs to include https protocol which failed tests --- modules/ozoneBidAdapter.js | 233 +++++++++++ modules/ozoneBidAdapter.md | 45 +++ test/spec/modules/ozoneBidAdapter_spec.js | 454 ++++++++++++++++++++++ 3 files changed, 732 insertions(+) create mode 100644 modules/ozoneBidAdapter.js create mode 100644 modules/ozoneBidAdapter.md create mode 100644 test/spec/modules/ozoneBidAdapter_spec.js diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js new file mode 100644 index 00000000000..1907b74ee02 --- /dev/null +++ b/modules/ozoneBidAdapter.js @@ -0,0 +1,233 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'ozone'; + +const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; +const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; + +export const spec = { + code: BIDDER_CODE, + + /** + * Basic check to see whether required parameters are in the request. + * @param bid + * @returns {boolean} + */ + isBidRequestValid(bid) { + if (!(bid.params.hasOwnProperty('placementId'))) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : missing placementId : siteId, placementId and publisherId are REQUIRED'); + return false; + } + if (!(bid.params.placementId).toString().match(/^[0-9]{10}$/)) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : placementId must be exactly 10 numeric characters'); + return false; + } + if (!(bid.params.hasOwnProperty('publisherId'))) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : missing publisherId : siteId, placementId and publisherId are REQUIRED'); + return false; + } + if (!(bid.params.publisherId).toString().match(/^[a-zA-Z0-9\-]{12}$/)) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : publisherId must be exactly 12 alphanumieric characters including hyphens'); + return false; + } + if (!(bid.params.hasOwnProperty('siteId'))) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : missing siteId : siteId, placementId and publisherId are REQUIRED'); + return false; + } + if (!(bid.params.siteId).toString().match(/^[0-9]{10}$/)) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : siteId must be exactly 10 numeric characters'); + return false; + } + if (bid.params.hasOwnProperty('customData')) { + if (typeof bid.params.customData !== 'object') { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : customData is not an object'); + return false; + } + } + if (bid.params.hasOwnProperty('customParams')) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : customParams should be renamed to customData'); + return false; + } + if (bid.params.hasOwnProperty('ozoneData')) { + if (typeof bid.params.ozoneData !== 'object') { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : ozoneData is not an object'); + return false; + } + } + if (bid.params.hasOwnProperty('lotameData')) { + if (typeof bid.params.lotameData !== 'object') { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : lotameData is not an object'); + return false; + } + } + return true; + }, + /** + * @param serverResponse + * @param request + * @returns {*} + */ + interpretResponse(serverResponse, request) { + serverResponse = serverResponse.body || {}; + if (serverResponse.seatbid) { + if (utils.isArray(serverResponse.seatbid)) { + const {seatbid: arrSeatbid} = serverResponse; + let winnerAds = arrSeatbid.reduce((bid, ads) => { + var _seat = ads.seat; + let ad = ads.bid.reduce(function(currentWinningBid, considerBid) { + if (currentWinningBid.price < considerBid.price) { + const bid = matchRequest(considerBid.impid, request); + const {width, height} = defaultSize(bid); + considerBid.cpm = considerBid.price; + considerBid.bidId = considerBid.impid; + considerBid.requestId = considerBid.impid; + considerBid.width = considerBid.w || width; + considerBid.height = considerBid.h || height; + considerBid.ad = considerBid.adm; + considerBid.netRevenue = true; + considerBid.creativeId = considerBid.crid; + considerBid.currency = 'USD'; + considerBid.ttl = 60; + considerBid.seat = _seat; + + return considerBid; + } else { + currentWinningBid.cpm = currentWinningBid.price; + return currentWinningBid; + } + }, {price: 0}); + if (ad.adm) { + bid.push(ad) + } + return bid; + }, []) + let winnersClean = winnerAds.filter(w => { + if (w.bidId) { + return true; + } + return false; + }); + utils.logInfo(['going to return winnersClean:', winnersClean]); + return winnersClean; + } else { + return []; + } + } else { + return []; + } + }, + buildRequests(validBidRequests, bidderRequest) { + let ozoneRequest = validBidRequests[0].params; + ozoneRequest['id'] = utils.generateUUID(); + ozoneRequest['auctionId'] = bidderRequest['auctionId']; + + if (bidderRequest.hasOwnProperty('placementId')) { + bidderRequest.placementId = (bidderRequest.placementId).toString(); + } + if (bidderRequest.hasOwnProperty('siteId')) { + bidderRequest.siteId = (bidderRequest.siteId).toString(); + } + if (bidderRequest.hasOwnProperty('publisherId')) { + bidderRequest.publisherId = (bidderRequest.publisherId).toString(); + } + + if (!ozoneRequest.test) { + delete ozoneRequest.test; + } + if (bidderRequest.gdprConsent) { + ozoneRequest.regs = {}; + ozoneRequest.regs.ext = {}; + ozoneRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; + if (ozoneRequest.regs.ext.gdpr) { + ozoneRequest.regs.ext.consent = bidderRequest.gdprConsent.consentString; + } + } + let tosendtags = validBidRequests.map(ozone => { + var obj = {}; + obj.id = ozone.bidId; + obj.tagid = String(ozone.params.ozoneid); + obj.secure = window.location.protocol === 'https:' ? 1 : 0; + obj.banner = { + topframe: 1, + w: ozone.sizes[0][0] || 0, + h: ozone.sizes[0][1] || 0, + format: ozone.sizes.map(s => { + return {w: s[0], h: s[1]}; + }) + }; + if (ozone.params.hasOwnProperty('customData')) { + obj.customData = ozone.params.customData; + } + if (ozone.params.hasOwnProperty('ozoneData')) { + obj.ozoneData = ozone.params.ozoneData; + } + if (ozone.params.hasOwnProperty('lotameData')) { + obj.lotameData = ozone.params.lotameData; + } + if (ozone.params.hasOwnProperty('publisherId')) { + obj.publisherId = (ozone.params.publisherId).toString(); + } + if (ozone.params.hasOwnProperty('siteId')) { + obj.siteId = (ozone.params.siteId).toString(); + } + obj.ext = {'prebid': {'storedrequest': {'id': (ozone.params.placementId).toString()}}}; + return obj; + }); + ozoneRequest.imp = tosendtags; + var ret = { + method: 'POST', + url: OZONEURI, + data: JSON.stringify(ozoneRequest), + bidderRequest: bidderRequest + }; + utils.logInfo(['buildRequests going to return', ret]); + return ret; + }, + getUserSyncs(optionsType, serverResponse) { + if (!serverResponse || serverResponse.length === 0) { + return []; + } + if (optionsType.iframeEnabled) { + return [{ + type: 'iframe', + url: OZONECOOKIESYNC + }]; + } + } +} + +/** + * Function matchRequest(id: string, BidRequest: object) + * @param id + * @type string + * @param bidRequest + * @type Object + * @returns Object + * + */ +export function matchRequest(id, bidRequest) { + const {bids} = bidRequest.bidderRequest; + const [returnValue] = bids.filter(bid => bid.bidId === id); + return returnValue; +} + +export function checkDeepArray(Arr) { + if (Array.isArray(Arr)) { + if (Array.isArray(Arr[0])) { + return Arr[0]; + } else { + return Arr; + } + } else { + return Arr; + } +} +export function defaultSize(thebidObj) { + const {sizes} = thebidObj; + const returnObject = {}; + returnObject.width = checkDeepArray(sizes)[0]; + returnObject.height = checkDeepArray(sizes)[1]; + return returnObject; +} +registerBidder(spec); diff --git a/modules/ozoneBidAdapter.md b/modules/ozoneBidAdapter.md new file mode 100644 index 00000000000..c013a4d558c --- /dev/null +++ b/modules/ozoneBidAdapter.md @@ -0,0 +1,45 @@ + +# Overview + +``` +Module Name: Ozone Project Bidder Adapter +Module Type: Bidder Adapter +Maintainer: engineering@ozoneproject.com + +``` + +# Description + +Module that connects to the Ozone Project's demand source(s). + +The Ozone Project bid adapter supports Banner mediaTypes ONLY. + +# Test Parameters + + +A test ad unit that will consistently return test creatives: + +``` + +//Banner adUnit + +adUnits = [{ + code: 'id-of-your-banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'ozone', + params: { + publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */ + siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ + placementId: '0420420421', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ + customData: {"key1": "value1", "key2": "value2}, /* optional JSON placeholder for passing publisher key-values for targeting. */ + ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ + lotameData: {"key1": "value1", "key2": "value2} /* optional JSON placeholder for passing Lotame DMP data */ + } + }] + }]; +``` diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js new file mode 100644 index 00000000000..0dcad2b0858 --- /dev/null +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -0,0 +1,454 @@ +import { expect } from 'chai'; +import { spec } from 'modules/ozoneBidAdapter'; + +const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; +const BIDDER_CODE = 'ozone'; +/* + +NOTE - use firefox console to deep copy the objects to use here + + */ +var validBidRequests = [ + { + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + sizes: [[300, 250], [300, 600]], + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + } +]; + +var validBidderRequest = { + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + auctionStart: 1536838908986, + bidderCode: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + bids: [{ + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + sizes: [[300, 250], [300, 600]], + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + }], + doneCbCallCount: 1, + start: 1536838908987, + timeout: 3000 +}; +// make sure the impid matches the request bidId +var validResponse = { + 'body': { + 'id': 'd6198807-7a53-4141-b2db-d2cb754d68ba', + 'seatbid': [ + { + 'bid': [ + { + 'id': '677903815252395017', + 'impid': '2899ec066a91ff8', + 'price': 0.5, + 'adm': '', + 'adid': '98493581', + 'adomain': [ + 'http://prebid.org' + ], + 'iurl': 'https://fra1-ib.adnxs.com/cr?id=98493581', + 'cid': '9325', + 'crid': '98493581', + 'cat': [ + 'IAB3-1' + ], + 'w': 300, + 'h': 600, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 555545, + 'auction_id': 6500448734132353000, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + } + ], + 'seat': 'appnexus' + } + ], + 'ext': { + 'responsetimemillis': { + 'appnexus': 47, + 'openx': 30 + } + }, + 'timing': { + 'start': 1536848078.089177, + 'end': 1536848078.142203, + 'TimeTaken': 0.05302619934082031 + } + }, + 'headers': {} +} + +describe('ozone Adapter', function () { + describe('isBidRequestValid', function () { + // A test ad unit that will consistently return test creatives + let validBidReq = { + bidder: BIDDER_CODE, + params: { + placementId: '1310000099', + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(validBidReq)).to.equal(true); + }); + + var validBidReq2 = { + + bidder: BIDDER_CODE, + params: { + placementId: '1310000099', + publisherId: '9876abcd12-3', + siteId: '1234567890' + }, + customData: {'gender': 'bart', 'age': 'low'}, + ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, + lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, + siteId: 1234567890 + } + + it('should return true when required params found and all optional params are valid', function () { + expect(spec.isBidRequestValid(validBidReq2)).to.equal(true); + }); + + var xEmptyPlacement = { + bidder: BIDDER_CODE, + params: { + placementId: '', + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate empty placementId', function () { + expect(spec.isBidRequestValid(xEmptyPlacement)).to.equal(false); + }); + + var xMissingPlacement = { + bidder: BIDDER_CODE, + params: { + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate missing placementId', function () { + expect(spec.isBidRequestValid(xMissingPlacement)).to.equal(false); + }); + + var xBadPlacement = { + bidder: BIDDER_CODE, + params: { + placementId: '123X45', + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate placementId with a non-numeric value', function () { + expect(spec.isBidRequestValid(xBadPlacement)).to.equal(false); + }); + + var xBadPlacementTooShort = { + bidder: BIDDER_CODE, + params: { + placementId: 123456789, /* should be exactly 10 chars */ + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate placementId with a numeric value of wrong length', function () { + expect(spec.isBidRequestValid(xBadPlacementTooShort)).to.equal(false); + }); + + var xBadPlacementTooLong = { + bidder: BIDDER_CODE, + params: { + placementId: 12345678901, /* should be exactly 10 chars */ + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate placementId with a numeric value of wrong length', function () { + expect(spec.isBidRequestValid(xBadPlacementTooLong)).to.equal(false); + }); + + var xMissingPublisher = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + siteId: '1234567890' + } + }; + + it('should not validate missing publisherId', function () { + expect(spec.isBidRequestValid(xMissingPublisher)).to.equal(false); + }); + + var xBadPublisherTooShort = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12a', + siteId: '1234567890' + } + }; + + it('should not validate publisherId being too short', function () { + expect(spec.isBidRequestValid(xBadPublisherTooShort)).to.equal(false); + }); + + var xBadPublisherTooLong = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12abc', + siteId: '1234567890' + } + }; + + it('should not validate publisherId being too long', function () { + expect(spec.isBidRequestValid(xBadPublisherTooLong)).to.equal(false); + }); + + var publisherNumericOk = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: 123456789012, + siteId: '1234567890' + } + }; + + it('should validate publisherId being 12 digits', function () { + expect(spec.isBidRequestValid(publisherNumericOk)).to.equal(true); + }); + + var xEmptyPublisher = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '', + siteId: '1234567890' + } + }; + + it('should not validate empty publisherId', function () { + expect(spec.isBidRequestValid(xEmptyPublisher)).to.equal(false); + }); + + var xBadSite = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12-3', + siteId: '12345Z' + } + }; + + it('should not validate bad siteId', function () { + expect(spec.isBidRequestValid(xBadSite)).to.equal(false); + }); + + var xBadSiteTooLong = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12-3', + siteId: '12345678901' + } + }; + + it('should not validate siteId too long', function () { + expect(spec.isBidRequestValid(xBadSite)).to.equal(false); + }); + + var xBadSiteTooShort = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12-3', + siteId: '123456789' + } + }; + + it('should not validate siteId too short', function () { + expect(spec.isBidRequestValid(xBadSite)).to.equal(false); + }); + + var allNonStrings = { + bidder: BIDDER_CODE, + params: { + placementId: 1234567890, + publisherId: '9876abcd12-3', + siteId: 1234567890 + } + }; + + it('should validate all numeric values being sent as non-string numbers', function () { + expect(spec.isBidRequestValid(allNonStrings)).to.equal(true); + }); + + var emptySiteId = { + bidder: BIDDER_CODE, + params: { + placementId: 1234567890, + publisherId: '9876abcd12-3', + siteId: '' + } + }; + + it('should not validate siteId being empty string (it is required now)', function () { + expect(spec.isBidRequestValid(emptySiteId)).to.equal(false); + }); + + var xBadCustomData = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'siteId': '1234567890', + 'customData': 'this aint gonna work' + } + }; + + it('should not validate customData not being an object', function () { + expect(spec.isBidRequestValid(xBadCustomData)).to.equal(false); + }); + + var xCustomParams = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'customParams': {'info': 'this is not allowed'}, + siteId: '1234567890' + } + }; + + it('should not validate customParams being sent', function () { + expect(spec.isBidRequestValid(xCustomParams)).to.equal(false); + }); + + var xBadOzoneData = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'ozoneData': 'this should be an object', + siteId: '1234567890' + } + }; + + it('should not validate ozoneData being sent', function () { + expect(spec.isBidRequestValid(xBadOzoneData)).to.equal(false); + }); + + var xBadCustomData = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'customData': 'this should be an object', + siteId: '1234567890' + } + }; + + it('should not validate ozoneData being sent', function () { + expect(spec.isBidRequestValid(xBadCustomData)).to.equal(false); + }); + var xBadLotame = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'lotameData': 'this should be an object', + siteId: '1234567890' + } + }; + + it('should not validate lotameData being sent', function () { + expect(spec.isBidRequestValid(xBadLotame)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + it('sends bid request to OZONEURI via POST', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.url).to.equal(OZONEURI); + expect(request.method).to.equal('POST'); + }); + + it('sends data as a string', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.data).to.be.a('string'); + }); + + it('sends all bid parameters', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); + }); + + it('has correct bidder', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.bidderRequest.bids[0].bidder).to.equal(BIDDER_CODE); + }); + }); + + describe('interpretResponse', function () { + it('should build bid array', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + console.log(['interpretResponse request = ', request]); + const result = spec.interpretResponse(validResponse, request); + console.log(['interpretResponse result = ', result]); + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + console.log(['Request: ', request]); + const result = spec.interpretResponse(validResponse, request); + console.log(['result[0]: ', result[0]]); + const bid = result[0]; + expect(bid.cpm).to.equal(validResponse.body.seatbid[0].bid[0].cpm); + expect(bid.width).to.equal(validResponse.body.seatbid[0].bid[0].width); + expect(bid.height).to.equal(validResponse.body.seatbid[0].bid[0].height); + }); + + it('should build bid array with gdpr', function () { + var validBidderRequestWithGdpr = validBidderRequest; + validBidderRequestWithGdpr.gdprConsent = {'gdprApplies': 1, 'consentString': 'This is the gdpr consent string'}; + const request = spec.buildRequests(validBidRequests, validBidderRequestWithGdpr); + console.log(['interpretResponse request = ', request]); + const result = spec.interpretResponse(validResponse, request); + console.log(['interpretResponse result = ', result]); + expect(result.length).to.equal(1); + }); + }); +});