Skip to content

Commit

Permalink
Add Bridgewell adapter (#1825)
Browse files Browse the repository at this point in the history
* Add a new bid adapter and test specs for bridgewell

* remove getUserSyncs(optional)

* change var to let or const

* fix a bug in adapter test spec, and add a test for required parameters in bid responses

* add semicolons to match styling
  • Loading branch information
kuchunchou authored and matthewlane committed Nov 20, 2017
1 parent 049af72 commit 4ee64ac
Show file tree
Hide file tree
Showing 3 changed files with 325 additions and 0 deletions.
101 changes: 101 additions & 0 deletions modules/bridgewellBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as utils from 'src/utils';
import {registerBidder} from 'src/adapters/bidderFactory';

const BIDDER_CODE = 'bridgewell';
const REQUEST_ENDPOINT = '//rec.scupio.com/recweb/prebid.aspx';

export const spec = {
code: BIDDER_CODE,

/**
* 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) {
return bid && bid.params && !!bid.params.ChannelID;
},

/**
* Make a server request from the list of BidRequests.
*
* @param {BidRequest[]} validBidRequests - an array of bids
* @return ServerRequest Info describing the request to the server.
*/
buildRequests: function(validBidRequests) {
const channelIDs = [];

utils._each(validBidRequests, function(bid) {
channelIDs.push(bid.params.ChannelID);
});

return {
method: 'GET',
url: REQUEST_ENDPOINT,
data: {
'ChannelID': channelIDs.join(',')
},
validBidRequests: validBidRequests
};
},

/**
* Unpack the response from the server into a list of bids.
*
* @param {*} serverResponse A successful response from the server.
* @param {*} bidRequest
* @return {Bid[]} An array of bids which were nested inside the server.
*/
interpretResponse: function(serverResponse, bidRequest) {
const bidResponses = [];

// map responses to requests
utils._each(bidRequest.validBidRequests, function(req) {
const bidResponse = {};

if (!serverResponse.body) {
return;
}

let matchedResponse = serverResponse.body.find(function(res) {
return !!res && !res.consumed && req.sizes.find(function(size) {
return res.width === size[0] && res.height === size[1];
});
});

if (matchedResponse) {
matchedResponse.consumed = true;

// check required parameters
if (typeof matchedResponse.cpm !== 'number') {
return;
} else if (typeof matchedResponse.width !== 'number' || typeof matchedResponse.height !== 'number') {
return;
} else if (typeof matchedResponse.ad !== 'string') {
return;
} else if (typeof matchedResponse.net_revenue === 'undefined') {
return;
} else if (typeof matchedResponse.currency !== 'string') {
return;
}

bidResponse.requestId = req.bidId;
bidResponse.cpm = matchedResponse.cpm;
bidResponse.width = matchedResponse.width;
bidResponse.height = matchedResponse.height;
bidResponse.ad = matchedResponse.ad;
bidResponse.ttl = matchedResponse.ttl;
bidResponse.creativeId = matchedResponse.id;
bidResponse.netRevenue = matchedResponse.net_revenue === 'true';
bidResponse.currency = matchedResponse.currency;

bidResponses.push(bidResponse);
}
});

return bidResponses;
}
};

registerBidder(spec);
38 changes: 38 additions & 0 deletions modules/bridgewellBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Overview

Module Name: Bridgewell Bidder Adapter
Module Type: Bidder Adapter
Maintainer: kuchunchou@bridgewell.com

# Description

Module that connects to Bridgewell demand source to fetch bids.

# Test Parameters
```
var adUnits = [
{
code: 'test-div',
sizes: [[300, 250]],
bids: [
{
bidder: 'bridgewell',
params: {
ChannelID: 'CgUxMjMzOBIBNiIFcGVubnkqCQisAhD6ARoBOQ',
}
}
]
},{
code: 'test-div',
sizes: [[728, 90]],
bids: [
{
bidder: 'bridgewell',
params: {
ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ',
}
}
]
}
];
```
186 changes: 186 additions & 0 deletions test/spec/modules/bridgewellBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { expect } from 'chai';
import { spec } from 'modules/bridgewellBidAdapter';
import { newBidder } from 'src/adapters/bidderFactory';
import * as utils from 'src/utils';

describe('bridgewellBidAdapter', function () {
let bidRequests = [
{
'bidder': 'bridgewell',
'params': {
'ChannelID': 'CLJgEAYYvxUiBXBlbm55KgkIrAIQ-gEaATk'
},
'adUnitCode': 'adunit-code-1',
'sizes': [[300, 250], [300, 600]],
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
},
{
'bidder': 'bridgewell',
'params': {
'ChannelID': 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ'
},
'adUnitCode': 'adunit-code-2',
'sizes': [[728, 90]],
'bidId': '3150ccb55da321',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
},
{
'bidder': 'bridgewell',
'params': {
'ChannelID': 'CgUxMjMzOBIBNiIFcGVubnkqCQisAhD6ARoBOQ'
},
'adUnitCode': 'adunit-code-1',
'sizes': [[300, 250]],
'bidId': '42dbe3a7168a6a',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
}
];
const adapter = newBidder(spec);

describe('inherited functions', () => {
it('exists and is a function', () => {
expect(adapter.callBids).to.exist.and.to.be.a('function');
});
});

describe('isBidRequestValid', () => {
let bid = {
'bidder': 'bridgewell',
'params': {
'ChannelID': 'CLJgEAYYvxUiBXBlbm55KgkIrAIQ-gEaATk'
},
'adUnitCode': 'adunit-code',
'sizes': [[300, 250], [300, 600]],
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
};

it('should return true when required params found', () => {
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

it('should return false when required params are not passed', () => {
let bid = Object.assign({}, bid);
delete bid.params;
bid.params = {
'ChannelID': 0
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
});

describe('buildRequests', () => {
it('should attach valid params to the tag', () => {
const request = spec.buildRequests([bidRequests[0]]);
const payload = request.data;
expect(payload).to.be.an('object');
expect(payload).to.have.property('ChannelID').that.is.a('string');
});

it('should attach validBidRequests to the tag', () => {
const request = spec.buildRequests(bidRequests);
const validBidRequests = request.validBidRequests;
expect(validBidRequests).to.deep.equal(bidRequests);
});

it('should attach valid params to the tag if multiple ChannelIDs are presented', () => {
const request = spec.buildRequests(bidRequests);
const payload = request.data;
expect(payload).to.be.an('object');
expect(payload).to.have.property('ChannelID').that.is.a('string');
expect(payload.ChannelID.split(',')).to.have.lengthOf(bidRequests.length);
});
});

describe('interpretResponse', () => {
const request = spec.buildRequests(bidRequests);
const serverResponses = [{
'id': 'e5b10774-32bf-4931-85ee-05095e8cff21',
'bidder_code': 'bridgewell',
'cpm': 5.0,
'width': 300,
'height': 250,
'ad': '<div>test 300x250</div>',
'ttl': 360,
'net_revenue': 'true',
'currency': 'NTD'
}, {
'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d',
'bidder_code': 'bridgewell',
'cpm': 5.0,
'width': 728,
'height': 90,
'ad': '<div>test 728x90</div>',
'ttl': 360,
'net_revenue': 'true',
'currency': 'NTD'
}, {
'id': '8f12c646-3b87-4326-a837-c2a76999f168',
'bidder_code': 'bridgewell',
'cpm': 5.0,
'width': 300,
'height': 250,
'ad': '<div>test 300x250</div>',
'ttl': 360,
'net_revenue': 'true',
'currency': 'NTD'
}];

it('should return all required parameters', () => {
const result = spec.interpretResponse({'body': serverResponses}, request);
result.every(res => expect(res.cpm).to.be.a('number'));
result.every(res => expect(res.width).to.be.a('number'));
result.every(res => expect(res.height).to.be.a('number'));
result.every(res => expect(res.ttl).to.be.a('number'));
result.every(res => expect(res.netRevenue).to.be.a('boolean'));
result.every(res => expect(res.currency).to.be.a('string'));
result.every(res => expect(res.ad).to.be.a('string'));
});

it('should give up bid if server response is undefiend', () => {
const result = spec.interpretResponse({'body': undefined}, request);
expect(result).to.deep.equal([]);
});

it('should give up bid if cpm is missing', () => {
let target = Object.assign({}, serverResponses[0]);
delete target.cpm;
const result = spec.interpretResponse({'body': [target]}, request);
expect(result).to.deep.equal([]);
});

it('should give up bid if width or height is missing', () => {
let target = Object.assign({}, serverResponses[0]);
delete target.height;
delete target.width;
const result = spec.interpretResponse({'body': [target]}, request);
expect(result).to.deep.equal([]);
});

it('should give up bid if ad is missing', () => {
let target = Object.assign({}, serverResponses[0]);
delete target.ad;
const result = spec.interpretResponse({'body': [target]}, request);
expect(result).to.deep.equal([]);
});

it('should give up bid if revenue mode is missing', () => {
let target = Object.assign({}, serverResponses[0]);
delete target.net_revenue;
const result = spec.interpretResponse({'body': [target]}, request);
expect(result).to.deep.equal([]);
});

it('should give up bid if currency is missing', () => {
let target = Object.assign({}, serverResponses[0]);
delete target.currency;
const result = spec.interpretResponse({'body': [target]}, request);
expect(result).to.deep.equal([]);
});
});
});

0 comments on commit 4ee64ac

Please sign in to comment.