Skip to content

Commit

Permalink
Qwarry bid adapter (prebid#5662)
Browse files Browse the repository at this point in the history
* qwarry bid adapter

* formatting fixes

* fix tests for qwarry

* qwarry bid adapter

* add header for qwarry bid adapter

* bid requests fix

* fix tests

* response fix

* fix tests for Qwarry bid adapter

Co-authored-by: Artem Kostritsa <akostritsa@akostritsa.com>
Co-authored-by: Alexander Kascheev <akascheev@asteriosoft.com>
  • Loading branch information
3 people authored and stsepelin committed May 28, 2021
1 parent 128fed7 commit 9df4893
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 0 deletions.
75 changes: 75 additions & 0 deletions modules/qwarryBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { deepClone } from '../src/utils.js';
import { ajax } from '../src/ajax.js';
import { VIDEO } from '../src/mediaTypes.js';

const BIDDER_CODE = 'qwarry';
export const ENDPOINT = 'https://ui-bidder.kantics.co/bid/adtag?prebid=true'

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: ['banner', 'video'],

isBidRequestValid: function (bid) {
return !!(bid.params && bid.params.zoneToken);
},

buildRequests: function (validBidRequests, bidderRequest) {
let bids = [];
validBidRequests.forEach(bidRequest => {
bids.push({
bidId: bidRequest.bidId,
zoneToken: bidRequest.params.zoneToken
})
})

return {
method: 'POST',
url: ENDPOINT,
data: { requestId: bidderRequest.bidderRequestId, bids },
options: {
contentType: 'application/json',
customHeaders: {
'Rtb-Direct': true
}
}
};
},

interpretResponse: function (serverResponse, request) {
const serverBody = serverResponse.body;
if (!serverBody || typeof serverBody !== 'object') {
return [];
}

const { prebidResponse } = serverBody;
if (!prebidResponse || typeof prebidResponse !== 'object') {
return [];
}

let bids = [];
prebidResponse.forEach(bidResponse => {
let bid = deepClone(bidResponse);
bid.cpm = parseFloat(bidResponse.cpm);

// banner or video
if (VIDEO === bid.format) {
bid.vastXml = bid.ad;
}

bids.push(bid);
})

return bids;
},

onBidWon: function (bid) {
if (bid.winUrl) {
ajax(bid.winUrl, null);
return true;
}
return false;
}
}

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

```
Module Name: Qwarry Bidder Adapter
Module Type: Bidder Adapter
Maintainer: akascheev@asteriosoft.com
```

# Description

Connects to Qwarry Bidder for bids.
Qwarry bid adapter supports Banner and Video ads.

# Test Parameters
```
const adUnits = [
{
bids: [
{
bidder: 'qwarry',
params: {
zoneToken: '?????????????????????', // zoneToken provided by Qwarry
}
}
]
}
];
```
122 changes: 122 additions & 0 deletions test/spec/modules/qwarryBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { expect } from 'chai'
import { ENDPOINT, spec } from 'modules/qwarryBidAdapter.js'
import { newBidder } from 'src/adapters/bidderFactory.js'

const REQUEST = {
'bidId': '456',
'bidder': 'qwarry',
'params': {
zoneToken: 'e64782a4-8e68-4c38-965b-80ccf115d46f'
}
}

const BIDDER_BANNER_RESPONSE = {'prebidResponse': [{
'ad': '<div>test</div>',
'requestId': 'e64782a4-8e68-4c38-965b-80ccf115d46d',
'cpm': 900.5,
'currency': 'USD',
'width': 640,
'height': 480,
'ttl': 300,
'creativeId': 1,
'netRevenue': true,
'winUrl': 'http://test.com',
'format': 'banner'
}]}

const BIDDER_VIDEO_RESPONSE = {'prebidResponse': [{
'ad': '<xml>vast</xml>',
'requestId': 'e64782a4-8e68-4c38-965b-80ccf115d46z',
'cpm': 800.4,
'currency': 'USD',
'width': 1024,
'height': 768,
'ttl': 200,
'creativeId': 2,
'netRevenue': true,
'winUrl': 'http://test.com',
'format': 'video'
}]}

const BIDDER_NO_BID_RESPONSE = ''

describe('qwarryBidAdapter', 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 () {
it('should return true when required params found', function () {
expect(spec.isBidRequestValid(REQUEST)).to.equal(true)
})

it('should return false when required params are not passed', function () {
let bid = Object.assign({}, REQUEST)
delete bid.params.zoneToken
expect(spec.isBidRequestValid(bid)).to.equal(false)
delete bid.params
expect(spec.isBidRequestValid(bid)).to.equal(false)
})
})

describe('buildRequests', function () {
let bidRequests = [REQUEST]
const bidderRequest = spec.buildRequests(bidRequests, { bidderRequestId: '123' })

it('sends bid request to ENDPOINT via POST', function () {
expect(bidderRequest.method).to.equal('POST')
expect(bidderRequest.data.requestId).to.equal('123')
expect(bidderRequest.data.bids).to.deep.contains({ bidId: '456', zoneToken: 'e64782a4-8e68-4c38-965b-80ccf115d46f' })
expect(bidderRequest.options.customHeaders).to.deep.equal({ 'Rtb-Direct': true })
expect(bidderRequest.options.contentType).to.equal('application/json')
expect(bidderRequest.url).to.equal(ENDPOINT)
})
})

describe('interpretResponse', function () {
it('handles banner request : should get correct bid response', function () {
const result = spec.interpretResponse({ body: BIDDER_BANNER_RESPONSE }, {})

expect(result[0]).to.have.property('ad').equal('<div>test</div>')
expect(result[0]).to.have.property('requestId').equal('e64782a4-8e68-4c38-965b-80ccf115d46d')
expect(result[0]).to.have.property('cpm').equal(900.5)
expect(result[0]).to.have.property('currency').equal('USD')
expect(result[0]).to.have.property('width').equal(640)
expect(result[0]).to.have.property('height').equal(480)
expect(result[0]).to.have.property('ttl').equal(300)
expect(result[0]).to.have.property('creativeId').equal(1)
expect(result[0]).to.have.property('netRevenue').equal(true)
expect(result[0]).to.have.property('winUrl').equal('http://test.com')
expect(result[0]).to.have.property('format').equal('banner')
})

it('handles video request : should get correct bid response', function () {
const result = spec.interpretResponse({ body: BIDDER_VIDEO_RESPONSE }, {})

expect(result[0]).to.have.property('ad').equal('<xml>vast</xml>')
expect(result[0]).to.have.property('requestId').equal('e64782a4-8e68-4c38-965b-80ccf115d46z')
expect(result[0]).to.have.property('cpm').equal(800.4)
expect(result[0]).to.have.property('currency').equal('USD')
expect(result[0]).to.have.property('width').equal(1024)
expect(result[0]).to.have.property('height').equal(768)
expect(result[0]).to.have.property('ttl').equal(200)
expect(result[0]).to.have.property('creativeId').equal(2)
expect(result[0]).to.have.property('netRevenue').equal(true)
expect(result[0]).to.have.property('winUrl').equal('http://test.com')
expect(result[0]).to.have.property('format').equal('video')
expect(result[0]).to.have.property('vastXml').equal('<xml>vast</xml>')
})

it('handles no bid response : should get empty array', function () {
let result = spec.interpretResponse({ body: undefined }, {})
expect(result).to.deep.equal([])

result = spec.interpretResponse({ body: BIDDER_NO_BID_RESPONSE }, {})
expect(result).to.deep.equal([])
})
})
})

0 comments on commit 9df4893

Please sign in to comment.