From 212b51802f8741cd59c9b7f0144c62b2e12ed9f3 Mon Sep 17 00:00:00 2001 From: bretg Date: Thu, 30 Sep 2021 07:37:05 -0400 Subject: [PATCH] Slimcut Bid Adapter: porting from 4.x with adomain (#7514) * slimcut adapter: porting from 4.x with adomain * fix utils imports * fix linting Co-authored-by: Chris Huie --- modules/slimcutBidAdapter.js | 121 ++++++++++++ test/spec/modules/slimcutBidAdapter_spec.js | 200 ++++++++++++++++++++ 2 files changed, 321 insertions(+) create mode 100644 modules/slimcutBidAdapter.js create mode 100644 test/spec/modules/slimcutBidAdapter_spec.js diff --git a/modules/slimcutBidAdapter.js b/modules/slimcutBidAdapter.js new file mode 100644 index 00000000000..c2592137fd8 --- /dev/null +++ b/modules/slimcutBidAdapter.js @@ -0,0 +1,121 @@ +import { getValue, parseSizesInput, getBidIdParameter } from '../src/utils.js'; +import { + registerBidder +} from '../src/adapters/bidderFactory.js'; +import { + ajax +} from '../src/ajax.js'; +const BIDDER_CODE = 'slimcut'; +const ENDPOINT_URL = 'https://sb.freeskreen.com/pbr'; +export const spec = { + code: BIDDER_CODE, + aliases: ['scm'], + supportedMediaTypes: ['video', 'banner'], + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + let isValid = false; + if (typeof bid.params !== 'undefined' && !isNaN(parseInt(getValue(bid.params, 'placementId'))) && parseInt(getValue(bid.params, 'placementId')) > 0) { + isValid = true; + } + return isValid; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + const bids = validBidRequests.map(buildRequestObject); + const payload = { + referrer: getReferrerInfo(bidderRequest), + data: bids, + deviceWidth: screen.width + }; + let gdpr = bidderRequest.gdprConsent; + if (bidderRequest && gdpr) { + let isCmp = (typeof gdpr.gdprApplies === 'boolean') + let isConsentString = (typeof gdpr.consentString === 'string') + payload.gdpr_iab = { + consent: isConsentString ? gdpr.consentString : '', + status: isCmp ? gdpr.gdprApplies : -1 + }; + } + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, request) { + const bidResponses = []; + serverResponse = serverResponse.body; + if (serverResponse.responses) { + serverResponse.responses.forEach(function(bid) { + const bidResponse = { + cpm: bid.cpm, + width: bid.width, + height: bid.height, + currency: bid.currency, + netRevenue: bid.netRevenue, + ttl: bid.ttl, + ad: bid.ad, + requestId: bid.requestId, + creativeId: bid.creativeId, + transactionId: bid.tranactionId, + winUrl: bid.winUrl, + meta: { + advertiserDomains: bid.adomain || [] + } + }; + bidResponses.push(bidResponse); + }); + } + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: 'https://sb.freeskreen.com/async_usersync.html' + }]; + } + return []; + }, + onBidWon: function(bid) { + ajax(bid.winUrl + bid.cpm, null); + } +} +function buildRequestObject(bid) { + const reqObj = {}; + let placementId = getValue(bid.params, 'placementId'); + reqObj.sizes = parseSizesInput(bid.sizes); + reqObj.bidId = getBidIdParameter('bidId', bid); + reqObj.bidderRequestId = getBidIdParameter('bidderRequestId', bid); + reqObj.placementId = parseInt(placementId); + reqObj.adUnitCode = getBidIdParameter('adUnitCode', bid); + reqObj.auctionId = getBidIdParameter('auctionId', bid); + reqObj.transactionId = getBidIdParameter('transactionId', bid); + return reqObj; +} +function getReferrerInfo(bidderRequest) { + let ref = window.location.href; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + ref = bidderRequest.refererInfo.referer; + } + return ref; +} + +registerBidder(spec); diff --git a/test/spec/modules/slimcutBidAdapter_spec.js b/test/spec/modules/slimcutBidAdapter_spec.js new file mode 100644 index 00000000000..300791c9658 --- /dev/null +++ b/test/spec/modules/slimcutBidAdapter_spec.js @@ -0,0 +1,200 @@ +import { + expect +} from 'chai'; +import { + spec +} from 'modules/slimcutBidAdapter.js'; +import { + newBidder +} from 'src/adapters/bidderFactory.js'; +const ENDPOINT = 'https://sb.freeskreen.com/pbr'; +const AD_SCRIPT = '"'; +describe('slimcutBidAdapter', function() { + 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': 'slimcut', + 'params': { + 'placementId': 83 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '3c871ffa8ef14c', + 'bidderRequestId': 'b41642f1aee381', + 'auctionId': '4e156668c977d7' + }; + it('should return true when required params found', function() { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when placementId is not valid (letters)', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 'ABCD' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + it('should return false when placementId < 0', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': -1 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + it('should return false when required params are not passed', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + describe('buildRequests', function() { + let bidRequests = [{ + 'bidder': 'teads', + 'params': { + 'placementId': 10433394 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '3c871ffa8ef14c', + 'bidderRequestId': 'b41642f1aee381', + 'auctionId': '4e156668c977d7', + 'deviceWidth': 1680 + }]; + let bidderResquestDefault = { + 'auctionId': '4e156668c977d7', + 'bidderRequestId': 'b41642f1aee381', + 'timeout': 3000 + }; + it('sends bid request to ENDPOINT via POST', function() { + const request = spec.buildRequests(bidRequests, bidderResquestDefault); + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + }); + it('should send GDPR to endpoint', function() { + let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; + let bidderRequest = { + 'auctionId': '4e156668c977d7', + 'bidderRequestId': 'b41642f1aee381', + 'timeout': 3000, + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true, + 'vendorData': { + 'hasGlobalConsent': false + } + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.gdpr_iab).to.exist; + expect(payload.gdpr_iab.consent).to.equal(consentString); + }); + it('should add referer info to payload', function() { + const bidRequest = Object.assign({}, bidRequests[0]) + const bidderRequest = { + refererInfo: { + referer: 'https://example.com/page.html', + reachedTop: true, + numIframes: 2 + } + } + const request = spec.buildRequests([bidRequest], bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.referrer).to.exist; + expect(payload.referrer).to.deep.equal('https://example.com/page.html') + }); + }); + describe('getUserSyncs', () => { + let bids = { + 'body': { + 'responses': [{ + 'ad': AD_SCRIPT, + 'cpm': 0.5, + 'currency': 'USD', + 'height': 250, + 'netRevenue': true, + 'requestId': '3ede2a3fa0db94', + 'ttl': 360, + 'width': 300, + 'creativeId': 'er2ee', + 'transactionId': 'deadb33f', + 'winUrl': 'https://sb.freeskreen.com/win' + }] + } + }; + it('should get the correct number of sync urls', () => { + let urls = spec.getUserSyncs({ + iframeEnabled: true + }, bids); + expect(urls.length).to.equal(1); + expect(urls[0].url).to.equal('https://sb.freeskreen.com/async_usersync.html'); + }); + it('should return no url if not iframe enabled', () => { + let urls = spec.getUserSyncs({ + iframeEnabled: false + }, bids); + expect(urls.length).to.equal(0); + }); + }); + describe('interpretResponse', function() { + let bids = { + 'body': { + 'responses': [{ + 'ad': AD_SCRIPT, + 'cpm': 0.5, + 'currency': 'USD', + 'height': 250, + 'netRevenue': true, + 'requestId': '3ede2a3fa0db94', + 'ttl': 360, + 'width': 300, + 'creativeId': 'er2ee', + 'transactionId': 'deadb33f', + 'winUrl': 'https://sb.freeskreen.com/win' + }] + } + }; + it('should get correct bid response', function() { + let expectedResponse = [{ + 'cpm': 0.5, + 'width': 300, + 'height': 250, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + 'ad': AD_SCRIPT, + 'requestId': '3ede2a3fa0db94', + 'creativeId': 'er2ee', + 'transactionId': 'deadb33f', + 'winUrl': 'https://sb.freeskreen.com/win', + 'meta': { + 'advertiserDomains': [] + } + }]; + let result = spec.interpretResponse(bids); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + it('handles nobid responses', function() { + let bids = { + 'body': { + 'responses': [] + } + }; + let result = spec.interpretResponse(bids); + expect(result.length).to.equal(0); + }); + }); +});