From 219f5f96093870bbc64b9269185e1f8d6c0c84c9 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 3 Oct 2017 15:27:26 -0400 Subject: [PATCH] Appnexus ast unittest updates (#1654) * Updated unit test to use bidderFactory * Updated unit test --- .../modules/appnexusAstBidAdapter_spec.js | 490 +++++++++--------- 1 file changed, 246 insertions(+), 244 deletions(-) diff --git a/test/spec/modules/appnexusAstBidAdapter_spec.js b/test/spec/modules/appnexusAstBidAdapter_spec.js index 61745697f3a..f8288819a55 100644 --- a/test/spec/modules/appnexusAstBidAdapter_spec.js +++ b/test/spec/modules/appnexusAstBidAdapter_spec.js @@ -1,202 +1,200 @@ import { expect } from 'chai'; import { spec } from 'modules/appnexusAstBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -import bidmanager from 'src/bidmanager'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; -const REQUEST = { - 'bidderCode': 'appnexusAst', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - 'bidderRequestId': '7101db09af0db2', - 'bids': [ - { - 'bidder': 'appnexusAst', - 'params': { - 'placementId': '4799418', - }, - 'placementCode': '/19968336/header-bid-tag1', - 'sizes': [ - [728, 90], - [970, 90] - ], - 'bidId': '84ab500420319d', - 'bidderRequestId': '7101db09af0db2', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6' - } - ], - 'start': 1469479810130 -}; - -const RESPONSE = { - 'version': '0.0.1', - 'tags': [{ - 'uuid': '84ab500420319d', - 'tag_id': 4799418, - 'auction_id': '2256922143947979797', - 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', - 'timeout_ms': 2500, - 'ads': [{ - 'content_source': 'rtb', - 'ad_type': 'banner', - 'buyer_member_id': 958, - 'creative_id': 33989846, - 'media_type_id': 1, - 'media_subtype_id': 1, - 'cpm': 0.500000, - 'cpm_publisher_currency': 0.500000, - 'publisher_currency_code': '$', - 'client_initiated_ad_counting': true, - 'rtb': { - 'banner': { - 'width': 728, - 'height': 90, - 'content': '' - }, - 'trackers': [{ - 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] - }] - } - }] - }] -}; - describe('AppNexusAdapter', () => { const adapter = newBidder(spec); - describe('request function', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => xhr.restore()); - + describe('inherited functions', () => { it('exists and is a function', () => { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); + }); - it('requires paramters to make request', () => { - adapter.callBids({}); - expect(requests).to.be.empty; + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'appnexusAst', + 'params': { + 'placementId': '10433394' + }, + '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('requires member && invCode', () => { - let backup = REQUEST.bids[0].params; - REQUEST.bids[0].params = {member: 1234}; - adapter.callBids(REQUEST); - expect(requests).to.be.empty; - REQUEST.bids[0].params = backup; + it('should return true when required params found', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'member': '1234', + 'invCode': 'ABCD' + }; + + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('attaches valid video params to the tag', () => { - REQUEST.bids[0].params.video = { - id: 123, - minduration: 100, - foobar: 'invalid' + it('should return false when required params are not passed', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); - adapter.callBids(REQUEST); + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'appnexusAst', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; - const request = JSON.parse(requests[0].requestBody).tags[0]; - expect(request.video).to.deep.equal({ - id: 123, - minduration: 100 + it('should add source and verison to the tag', () => { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.sdk).to.exist; + expect(payload.sdk).to.deep.equal({ + source: 'pbjs', + version: '$prebid.version$' }); - - delete REQUEST.bids[0].params.video; }); - it('attaches valid user params to the tag', () => { - REQUEST.bids[0].params.user = { - external_uid: '123', - foobar: 'invalid' - }; + it('sends bid request to ENDPOINT via POST', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + }); - adapter.callBids(REQUEST); + it('should attach valid video params to the tag', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + video: { + id: 123, + minduration: 100, + foobar: 'invalid' + } + } + } + ); - const request = JSON.parse(requests[0].requestBody); - expect(request.user).to.exist; - expect(request.user).to.deep.equal({ - external_uid: '123', + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.tags[0].video).to.deep.equal({ + id: 123, + minduration: 100 }); - - delete REQUEST.bids[0].params.user; }); - it('should add source and verison to the tag', () => { - adapter.callBids(REQUEST); + it('should attach valid user params to the tag', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + user: { + external_uid: '123', + foobar: 'invalid' + } + } + } + ); - const request = JSON.parse(requests[0].requestBody); - expect(request.sdk).to.exist; - expect(request.sdk).to.deep.equal({ - source: 'pbjs', - version: '$prebid.version$' + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.user).to.exist; + expect(payload.user).to.deep.equal({ + external_uid: '123', }); }); - it('attaches native params to the request', () => { - REQUEST.bids[0].mediaType = 'native'; - REQUEST.bids[0].nativeParams = { - title: {required: true}, - body: {required: true}, - image: {required: true, sizes: [{ width: 100, height: 100 }] }, - cta: {required: false}, - sponsoredBy: {required: true} - }; + it('should attache native params to the request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + title: {required: true}, + body: {required: true}, + image: {required: true, sizes: [{ width: 100, height: 100 }] }, + cta: {required: false}, + sponsoredBy: {required: true} + } + } + ); - adapter.callBids(REQUEST); + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); - const request = JSON.parse(requests[0].requestBody); - expect(request.tags[0].native.layouts[0]).to.deep.equal({ + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ title: {required: true}, description: {required: true}, main_image: {required: true, sizes: [{ width: 100, height: 100 }] }, ctatext: {required: false}, sponsored_by: {required: true} }); - - delete REQUEST.bids[0].mediaType; - delete REQUEST.bids[0].params.nativeParams; }); it('sets minimum native asset params when not provided on adunit', () => { - REQUEST.bids[0].mediaType = 'native'; - REQUEST.bids[0].nativeParams = { - image: {required: true}, - }; + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: {required: true}, + } + } + ); - adapter.callBids(REQUEST); + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); - const request = JSON.parse(requests[0].requestBody); - expect(request.tags[0].native.layouts[0]).to.deep.equal({ + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ main_image: {required: true, sizes: [{}] }, }); - - delete REQUEST.bids[0].mediaType; - delete REQUEST.bids[0].params.nativeParams; }); it('does not overwrite native ad unit params with mimimum params', () => { - REQUEST.bids[0].mediaType = 'native'; - REQUEST.bids[0].nativeParams = { - image: { - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - }, - }; + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: { + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + ); - adapter.callBids(REQUEST); + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); - const request = JSON.parse(requests[0].requestBody); - expect(request.tags[0].native.layouts[0]).to.deep.equal({ + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ main_image: { required: true, aspect_ratios: [{ @@ -206,31 +204,30 @@ describe('AppNexusAdapter', () => { }] }, }); - - delete REQUEST.bids[0].mediaType; - delete REQUEST.bids[0].params.nativeParams; - }); - - it('sends bid request to ENDPOINT via POST', () => { - adapter.callBids(REQUEST); - expect(requests[0].url).to.equal(ENDPOINT); - expect(requests[0].method).to.equal('POST'); }); - it('converts keyword params to proper form and attaches to request', () => { - REQUEST.bids[0].params.keywords = { - single: 'val', - singleArr: ['val'], - singleArrNum: [5], - multiValMixed: ['value1', 2, 'value3'], - singleValNum: 123, - badValue: {'foo': 'bar'} // should be dropped - }; + it('should convert keyword params to proper form and attaches to request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + badValue: {'foo': 'bar'} // should be dropped + } + } + } + ); - adapter.callBids(REQUEST); + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); - const request = JSON.parse(requests[0].requestBody).tags[0]; - expect(request.keywords).to.deep.equal([{ + expect(payload.tags[0].keywords).to.deep.equal([{ 'key': 'single', 'value': ['val'] }, { @@ -246,38 +243,74 @@ describe('AppNexusAdapter', () => { 'key': 'singleValNum', 'value': ['123'] }]); - - delete REQUEST.bids[0].params.keywords; }); - }); - - describe('response handler', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore() - bidmanager.addBidResponse.restore(); - }); - - it('registers bids', () => { - server.respondWith(JSON.stringify(RESPONSE)); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid available'); - expect(response).to.have.property('cpm', 0.5); + }) + + describe('interpretResponse', () => { + let response = { + 'version': '3.0.0', + 'tags': [ + { + 'uuid': '3db3773286ee59', + 'tag_id': 10433394, + 'auction_id': '4534722592064951574', + 'nobid': false, + 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', + 'timeout_ms': 10000, + 'ad_profile_id': 27079, + 'ads': [ + { + 'content_source': 'rtb', + 'ad_type': 'banner', + 'buyer_member_id': 958, + 'creative_id': 29681110, + 'media_type_id': 1, + 'media_subtype_id': 1, + 'cpm': 0.5, + 'cpm_publisher_currency': 0.5, + 'publisher_currency_code': '$', + 'client_initiated_ad_counting': true, + 'rtb': { + 'banner': { + 'content': '', + 'width': 300, + 'height': 250 + }, + 'trackers': [ + { + 'impression_urls': [ + 'http://lax1-ib.adnxs.com/impression' + ], + 'video_events': {} + } + ] + } + } + ] + } + ] + }; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creative_id': 29681110, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner' + } + ]; + + let result = spec.interpretResponse(response); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); it('handles nobid responses', () => { - server.respondWith(JSON.stringify({ + let response = { 'version': '0.0.1', 'tags': [{ 'uuid': '84ab500420319d', @@ -285,21 +318,14 @@ describe('AppNexusAdapter', () => { 'auction_id': '297492697822162468', 'nobid': true }] - })); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + }; - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); }); it('handles non-banner media responses', () => { - server.respondWith(JSON.stringify({ + let response = { 'tags': [{ 'uuid': '84ab500420319d', 'ads': [{ @@ -312,19 +338,18 @@ describe('AppNexusAdapter', () => { } }] }] - })); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + }; - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid available'); + let result = spec.interpretResponse(response); + expect(result[0]).to.have.property('vastUrl'); + expect(result[0]).to.have.property('descriptionUrl'); + expect(result[0]).to.have.property('mediaType', 'video'); }); it('handles native responses', () => { - RESPONSE.tags[0].ads[0].ad_type = 'native'; - RESPONSE.tags[0].ads[0].rtb.native = { + let response1 = Object.assign({}, response); + response1.tags[0].ads[0].ad_type = 'native'; + response1.tags[0].ads[0].rtb.native = { 'title': 'Native Creative', 'desc': 'Cool description great stuff', 'ctatext': 'Do it', @@ -347,34 +372,11 @@ describe('AppNexusAdapter', () => { 'impression_trackers': ['http://example.com'], }; - adapter.callBids(REQUEST); - server.respondWith(JSON.stringify(RESPONSE)); - server.respond(); - - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - - expect(response.native.title).to.equal('Native Creative'); - expect(response.native.body).to.equal('Cool description great stuff'); - expect(response.native.cta).to.equal('Do it'); - expect(response.native.image).to.equal('http://cdn.adnxs.com/img.png'); - - RESPONSE.tags[0].ads[0].ad_type = 'banner'; - }); - - it('handles JSON.parse errors', () => { - server.respondWith(''); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); + let result = spec.interpretResponse(response1); + expect(result[0].native.title).to.equal('Native Creative'); + expect(result[0].native.body).to.equal('Cool description great stuff'); + expect(result[0].native.cta).to.equal('Do it'); + expect(result[0].native.image).to.equal('http://cdn.adnxs.com/img.png'); }); }); });