From 889e5f0fc814d88c223c204592435170f7056f2d Mon Sep 17 00:00:00 2001 From: Melody Li Date: Fri, 9 Feb 2018 09:39:45 -0500 Subject: [PATCH 01/49] update maintainer email --- modules/yieldmoBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index b93f72594bc..8c60202d7ea 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Yieldmo Bid Adapter Module Type: Bidder Adapter -Maintainer: melody@yieldmo.com +Maintainer: opensource@yieldmo.com Note: Our ads will only render in mobile ``` From 4fd8634f12133945ac44e9b550237321e71fc549 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:05:08 -0400 Subject: [PATCH 02/49] add stringified schain --- modules/yieldmoBidAdapter.js | 5 + test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++---------- test/spec/modules/yieldmoBidAdapter_spec.js | 7 + 3 files changed, 133 insertions(+), 121 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index fd09cbaa4ea..eaa053456d0 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -27,6 +27,8 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(bidRequests) { + console.log('bid requests'); + console.log(bidRequests); let serverRequest = { p: [], page_url: utils.getTopWindowUrl(), @@ -55,6 +57,9 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } + if (request.schain) { + serverRequest.schain = JSON.stringify(request.schain); + } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 59138b03e61..c211cf15c6b 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; - - beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); - }); - - afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); - }); - - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; - - adapter.track({ eventType, args }); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); - }); - - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); - }); + let xhr; + let requests; + let adapter; - describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); }); afterEach(function () { - events.getEvents.restore(); + xhr.restore(); + adapter.disableAnalytics(); }); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; - adapter.enableAnalytics(); - events.emit(eventType, args); + adapter.track({ eventType, args }); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; - adapter.enableAnalytics(); events.emit(eventType, args); + adapter.enableAnalytics(); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + describe(`WHEN an event occurs after enable analytics\n`, function () { + beforeEach(function () { + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + afterEach(function () { + events.getEvents.restore(); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); - }); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); - }); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - expect(requests.length).to.equal(1); - }); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); - afterEach(function () { - Math.random.restore(); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); events.emit(eventType, args); expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; + + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); + }); + + afterEach(function () { + Math.random.restore(); + }); + + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - events.emit(eventType, args); - expect(requests.length).to.equal(0); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(0); + }); }); }); }); -}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 60fe25db95e..803e4b012ed 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -149,6 +149,13 @@ describe('YieldmoAdapter', function () { const data = spec.buildRequests([unifiedIdBid]).data; expect(data.tdid).to.deep.equal(tdid); }); + + it('should add schain if it is in the bidRequest', () => { + const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; + bidArray[0].schain = schain; + const request = spec.buildRequests([bidArray[0]]); + expect(request.data.schain).equal(JSON.stringify(schain)); + }) }); describe('interpretResponse', function () { From 75d3036788ef029f0e85c183f2ea5b85c7a08370 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:08:46 -0400 Subject: [PATCH 03/49] Revert "add stringified schain" This reverts commit 4fd8634f12133945ac44e9b550237321e71fc549. --- modules/yieldmoBidAdapter.js | 5 - test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++---------- test/spec/modules/yieldmoBidAdapter_spec.js | 7 - 3 files changed, 121 insertions(+), 133 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index eaa053456d0..fd09cbaa4ea 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -27,8 +27,6 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(bidRequests) { - console.log('bid requests'); - console.log(bidRequests); let serverRequest = { p: [], page_url: utils.getTopWindowUrl(), @@ -57,9 +55,6 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } - if (request.schain) { - serverRequest.schain = JSON.stringify(request.schain); - } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index c211cf15c6b..59138b03e61 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; + let xhr; + let requests; + let adapter; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); + }); + + afterEach(function () { + xhr.restore(); + adapter.disableAnalytics(); + }); + + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; + + adapter.track({ eventType, args }); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + }); + + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + }); + describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); + events.getEvents.restore(); }); - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - adapter.track({ eventType, args }); + adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - events.emit(eventType, args); adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); - describe(`WHEN an event occurs after enable analytics\n`, function () { - beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - afterEach(function () { - events.getEvents.restore(); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + events.emit(eventType, args); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + expect(requests.length).to.equal(1); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); }); - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - adapter.enableAnalytics(); - events.emit(eventType, args); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + afterEach(function () { + Math.random.restore(); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); events.emit(eventType, args); expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; - - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); - }); - - afterEach(function () { - Math.random.restore(); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } }); + events.emit(eventType, args); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); - - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(0); - }); + expect(requests.length).to.equal(0); }); }); }); +}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 803e4b012ed..60fe25db95e 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -149,13 +149,6 @@ describe('YieldmoAdapter', function () { const data = spec.buildRequests([unifiedIdBid]).data; expect(data.tdid).to.deep.equal(tdid); }); - - it('should add schain if it is in the bidRequest', () => { - const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; - bidArray[0].schain = schain; - const request = spec.buildRequests([bidArray[0]]); - expect(request.data.schain).equal(JSON.stringify(schain)); - }) }); describe('interpretResponse', function () { From 4efef2a7ba797fb9aaf28a2d779d2ea8dd92fc9b Mon Sep 17 00:00:00 2001 From: Melody Li Date: Wed, 16 Oct 2019 15:01:18 -0400 Subject: [PATCH 04/49] pass along gdpr consent string and gdpr applies through get --- modules/yieldmoBidAdapter.js | 9 ++++- test/spec/modules/yieldmoBidAdapter_spec.js | 41 ++++++++++++++++----- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index fd09cbaa4ea..1226ce32392 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -26,7 +26,7 @@ export const spec = { * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(bidRequests) { + buildRequests: function(bidRequests, bidderRequest) { let serverRequest = { p: [], page_url: utils.getTopWindowUrl(), @@ -38,7 +38,12 @@ export const spec = { description: getPageDescription(), title: localWindow.document.title || '', w: localWindow.innerWidth, - h: localWindow.innerHeight + h: localWindow.innerHeight, + user: JSON.stringify({ + // case of undefined, stringify will remove param + gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, + consentString: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined + }) }; bidRequests.forEach((request) => { diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 60fe25db95e..c148684323a 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -27,6 +27,16 @@ describe('YieldmoAdapter', function () { } }; let bidArray = [bid]; + let bidderRequest = { + 'bidderCode': 'yieldmo', + 'auctionId': 'e3a336ad-2761-4a1c-b421-ecc7c5294a34', + 'bidderRequestId': '14c4ede8c693f', + 'bids': bidArray, + 'auctionStart': 1520001292880, + 'timeout': 3000, + 'start': 1520001292884, + 'doneCbCallCount': 0 + } describe('isBidRequestValid', function () { it('should return true when necessary information is found', function () { @@ -52,7 +62,7 @@ describe('YieldmoAdapter', function () { describe('buildRequests', function () { it('should attempt to send bid requests to the endpoint via GET', function () { - const request = spec.buildRequests(bidArray); + const request = spec.buildRequests(bidArray, bidderRequest); expect(request.method).to.equal('GET'); expect(request.url).to.be.equal(ENDPOINT); }); @@ -61,11 +71,11 @@ describe('YieldmoAdapter', function () { let bidArray = [ { ...bid, crumbs: undefined } ] - expect(function () { spec.buildRequests(bidArray) }).not.to.throw() + expect(function () { spec.buildRequests(bidArray, bidderRequest) }).not.to.throw() }) it('should place bid information into the p parameter of data', function () { - let placementInfo = spec.buildRequests(bidArray).data.p; + let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); bidArray.push({ @@ -85,24 +95,24 @@ describe('YieldmoAdapter', function () { }); // multiple placements - placementInfo = spec.buildRequests(bidArray).data.p; + placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); }); it('should add placement id if given', function () { bidArray[0].params.placementId = 'ym_1293871298'; - let placementInfo = spec.buildRequests(bidArray).data.p; + let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"'); bidArray[1].params.placementId = 'ym_0987654321'; - placementInfo = spec.buildRequests(bidArray).data.p; + placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"'); }); it('should add additional information to data parameter of request', function () { - const data = spec.buildRequests(bidArray).data; + const data = spec.buildRequests(bidArray, bidderRequest).data; expect(data.hasOwnProperty('page_url')).to.be.true; expect(data.hasOwnProperty('bust')).to.be.true; expect(data.hasOwnProperty('pr')).to.be.true; @@ -129,7 +139,7 @@ describe('YieldmoAdapter', function () { pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' } }; - const data = spec.buildRequests([pubcidBid]).data; + const data = spec.buildRequests([pubcidBid], bidderRequest).data; expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); }); @@ -146,9 +156,22 @@ describe('YieldmoAdapter', function () { tdid, } }; - const data = spec.buildRequests([unifiedIdBid]).data; + const data = spec.buildRequests([unifiedIdBid], bidderRequest).data; expect(data.tdid).to.deep.equal(tdid); }); + + it('should add gdpr information to request if available', () => { + bidderRequest.gdprConsent = { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'vendorData': {'blerp': 1}, + 'gdprApplies': true + } + const data = spec.buildRequests(bidArray, bidderRequest).data; + expect(data.user).equal(JSON.stringify({ + 'gdprApplies': true, + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' + })); + }); }); describe('interpretResponse', function () { From 05dbe645be7029dcead3538b62f98d48d863f785 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Thu, 17 Oct 2019 11:24:26 -0400 Subject: [PATCH 05/49] use paramter gdprConsent --- modules/yieldmoBidAdapter.js | 2 +- test/spec/modules/yieldmoBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 1226ce32392..725a361789b 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -39,7 +39,7 @@ export const spec = { title: localWindow.document.title || '', w: localWindow.innerWidth, h: localWindow.innerHeight, - user: JSON.stringify({ + gdprConsent: JSON.stringify({ // case of undefined, stringify will remove param gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, consentString: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index c148684323a..78cddf44e38 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -167,7 +167,7 @@ describe('YieldmoAdapter', function () { 'gdprApplies': true } const data = spec.buildRequests(bidArray, bidderRequest).data; - expect(data.user).equal(JSON.stringify({ + expect(data.gdprConsent).equal(JSON.stringify({ 'gdprApplies': true, 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' })); From 49de31ff0e00ef01d55e0813b3ada3be41ce38a4 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:05:08 -0400 Subject: [PATCH 06/49] add stringified schain --- modules/yieldmoBidAdapter.js | 3 + test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++---------- test/spec/modules/yieldmoBidAdapter_spec.js | 6 + 3 files changed, 130 insertions(+), 121 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 725a361789b..22b20511daf 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -60,6 +60,9 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } + if (request.schain) { + serverRequest.schain = JSON.stringify(request.schain); + } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 59138b03e61..c211cf15c6b 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; - - beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); - }); - - afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); - }); - - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; - - adapter.track({ eventType, args }); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); - }); - - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); - }); + let xhr; + let requests; + let adapter; - describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); }); afterEach(function () { - events.getEvents.restore(); + xhr.restore(); + adapter.disableAnalytics(); }); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; - adapter.enableAnalytics(); - events.emit(eventType, args); + adapter.track({ eventType, args }); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; - adapter.enableAnalytics(); events.emit(eventType, args); + adapter.enableAnalytics(); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + describe(`WHEN an event occurs after enable analytics\n`, function () { + beforeEach(function () { + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + afterEach(function () { + events.getEvents.restore(); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); - }); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); - }); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - expect(requests.length).to.equal(1); - }); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); - afterEach(function () { - Math.random.restore(); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); events.emit(eventType, args); expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; + + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); + }); + + afterEach(function () { + Math.random.restore(); + }); + + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - events.emit(eventType, args); - expect(requests.length).to.equal(0); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(0); + }); }); }); }); -}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 78cddf44e38..f143caa8c1e 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -172,6 +172,12 @@ describe('YieldmoAdapter', function () { 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' })); }); + it('should add schain if it is in the bidRequest', () => { + const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; + bidArray[0].schain = schain; + const request = spec.buildRequests([bidArray[0]]); + expect(request.data.schain).equal(JSON.stringify(schain)); + }) }); describe('interpretResponse', function () { From 3e384c9037c0e0d78504e609a11efbb8a612a41f Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 17:33:15 -0400 Subject: [PATCH 07/49] don't change other files --- test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++++++--------------- 1 file changed, 121 insertions(+), 121 deletions(-) diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index c211cf15c6b..59138b03e61 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; + let xhr; + let requests; + let adapter; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); + }); + + afterEach(function () { + xhr.restore(); + adapter.disableAnalytics(); + }); + + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; + + adapter.track({ eventType, args }); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + }); + + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + }); + describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); + events.getEvents.restore(); }); - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - adapter.track({ eventType, args }); + adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - events.emit(eventType, args); adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); - describe(`WHEN an event occurs after enable analytics\n`, function () { - beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - afterEach(function () { - events.getEvents.restore(); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + events.emit(eventType, args); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + expect(requests.length).to.equal(1); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); }); - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - adapter.enableAnalytics(); - events.emit(eventType, args); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + afterEach(function () { + Math.random.restore(); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); events.emit(eventType, args); expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; - - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); - }); - - afterEach(function () { - Math.random.restore(); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } }); + events.emit(eventType, args); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); - - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(0); - }); + expect(requests.length).to.equal(0); }); }); }); +}); From 17108a40dd8cb8a44d70f483231d535c6c116bcd Mon Sep 17 00:00:00 2001 From: Melody Li Date: Mon, 21 Oct 2019 17:37:12 -0400 Subject: [PATCH 08/49] change parameter namves --- modules/yieldmoBidAdapter.js | 6 +++--- test/spec/modules/yieldmoBidAdapter_spec.js | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 22b20511daf..a3623941ddc 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -39,10 +39,10 @@ export const spec = { title: localWindow.document.title || '', w: localWindow.innerWidth, h: localWindow.innerHeight, - gdprConsent: JSON.stringify({ + userConsent: JSON.stringify({ // case of undefined, stringify will remove param - gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, - consentString: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined + gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, + cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined }) }; diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index f143caa8c1e..139997ec2ee 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -167,11 +167,12 @@ describe('YieldmoAdapter', function () { 'gdprApplies': true } const data = spec.buildRequests(bidArray, bidderRequest).data; - expect(data.gdprConsent).equal(JSON.stringify({ + expect(data.userConsent).equal(JSON.stringify({ 'gdprApplies': true, - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' + 'cmp': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' })); }); + it('should add schain if it is in the bidRequest', () => { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; From 217eb0c8c50ae283746c0252dc576e103f764364 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 25 Oct 2019 11:20:43 -0400 Subject: [PATCH 09/49] updates bidder module to be 3.0 compliant, and tests --- modules/yieldmoBidAdapter.js | 2 +- test/spec/modules/yieldmoBidAdapter_spec.js | 28 ++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index a3623941ddc..c0a40616b79 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -114,7 +114,7 @@ function addPlacement(request) { const placementInfo = { placement_id: request.adUnitCode, callback_id: request.bidId, - sizes: request.sizes + sizes: request.mediaTypes.banner.sizes } if (request.params) { if (request.params.placementId) { diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 139997ec2ee..81c0108ab0d 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -15,7 +15,11 @@ describe('YieldmoAdapter', function () { bidFloor: 0.1 }, adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -76,7 +80,7 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.1}]'); bidArray.push({ bidder: 'yieldmo', @@ -84,7 +88,11 @@ describe('YieldmoAdapter', function () { bidFloor: 0.2 }, adUnitCode: 'adunit-code-1', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '123456789', bidderRequestId: '987654321', auctionId: '0246810', @@ -96,7 +104,7 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{sizes":[[300,250],[300,600]]}},"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.2}]'); }); it('should add placement id if given', function () { @@ -131,7 +139,11 @@ describe('YieldmoAdapter', function () { bidder: 'yieldmo', params: {}, adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -148,7 +160,11 @@ describe('YieldmoAdapter', function () { bidder: 'yieldmo', params: {}, adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', From 58546868c94320c461a87eaf67b9fbe4b0ad01a5 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 1 Nov 2019 13:15:14 -0400 Subject: [PATCH 10/49] deletes openxoutstream adapter --- modules/openxoutstreamBidAdapter.js | 213 --------------- modules/openxoutstreamBidAdapter.md | 43 ---- .../modules/openxoutstreamBidAdapter_spec.js | 243 ------------------ 3 files changed, 499 deletions(-) delete mode 100644 modules/openxoutstreamBidAdapter.js delete mode 100644 modules/openxoutstreamBidAdapter.md delete mode 100644 test/spec/modules/openxoutstreamBidAdapter_spec.js diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js deleted file mode 100644 index 9011a949e7b..00000000000 --- a/modules/openxoutstreamBidAdapter.js +++ /dev/null @@ -1,213 +0,0 @@ -import { config } from '../src/config'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import * as utils from '../src/utils'; -import { BANNER } from '../src/mediaTypes'; - -const SUPPORTED_AD_TYPES = [BANNER]; -const BIDDER_CODE = 'openxoutstream'; -const BIDDER_CONFIG = 'hb_pb_ym'; -const BIDDER_VERSION = '1.0.0'; -const CURRENCY = 'USD'; -const NET_REVENUE = true; -const TIME_TO_LIVE = 300; -const YM_SCRIPT = `!function(e,t){if(void 0===t._ym){var a=Math.round(5*Math.random()/3)+'';t._ym='';var m=e.createElement('script');m.type='text/javascript',m.async=!0,m.src='//static.yieldmo.com/ym.'+a+'.js',(e.getElementsByTagName('head')[0]||e.getElementsByTagName('body')[0]).appendChild(m)}else t._ym instanceof String||void 0===t._ym.chkPls||t._ym.chkPls()}(document,window);`; -const PLACEMENT_ID = '1986307928000988495'; -const PUBLISHER_ID = '1986307525700126029'; -const CR_ID = '2052941939925262540'; -const AD_ID = '1991358644725162800'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: SUPPORTED_AD_TYPES, - isBidRequestValid: function(bidRequest) { - return !!(bidRequest.params.delDomain && bidRequest.params.unit) - }, - buildRequests: function(bidRequests, bidderRequest) { - if (bidRequests.length === 0) { - return []; - } - let requests = []; - bidRequests.forEach(bid => { - requests.push(buildOXBannerRequest(bid, bidderRequest)); - }) - return requests; - }, - interpretResponse: function(bid, serverResponse) { - return handleVastResponse(bid, serverResponse.payload) - }, -}; - -function getViewportDimensions(isIfr) { - let width; - let height; - let tWin = window; - let body; - - if (isIfr) { - let tDoc; - try { - tWin = window.top; - tDoc = window.top.document; - } catch (e) { - return; - } - body = tDoc.body; - - width = tWin.innerWidth || docEl.clientWidth || body.clientWidth; - height = tWin.innerHeight || docEl.clientHeight || body.clientHeight; - } else { - width = tWin.innerWidth || docEl.clientWidth; - height = tWin.innerHeight || docEl.clientHeight; - } - - return `${width}x${height}`; -} - -function buildCommonQueryParamsFromBids(bid, bidderRequest) { - const isInIframe = utils.inIframe(); - let defaultParams; - const height = '184'; - const width = '414'; - const aus = '304x184%7C412x184%7C375x184%7C414x184'; - defaultParams = { - ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), - jr: utils.getTopWindowReferrer(), - ch: document.charSet || document.characterSet, - res: `${screen.width}x${screen.height}x${screen.colorDepth}`, - ifr: isInIframe, - tz: new Date().getTimezoneOffset(), - tws: getViewportDimensions(isInIframe), - be: 1, - bc: bid.params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, - auid: bid.params.unit, - dddid: bid.transactionId, - openrtb: '%7B%22mimes%22%3A%5B%22video%2Fmp4%22%5D%7D', - nocache: new Date().getTime(), - vht: height, - vwd: width, - aus: aus - }; - - if (utils.deepAccess(bidderRequest, 'gdprConsent')) { - let gdprConsentConfig = bidderRequest.gdprConsent; - - if (gdprConsentConfig.consentString !== undefined) { - defaultParams.gdpr_consent = gdprConsentConfig.consentString; - } - - if (gdprConsentConfig.gdprApplies !== undefined) { - defaultParams.gdpr = gdprConsentConfig.gdprApplies ? 1 : 0; - } - - if (config.getConfig('consentManagement.cmpApi') === 'iab') { - defaultParams.x_gdpr_f = 1; - } - } - - return defaultParams; -} - -function buildOXBannerRequest(bid, bidderRequest) { - let queryParams = buildCommonQueryParamsFromBids(bid, bidderRequest); - - if (bid.params.doNotTrack) { - queryParams.ns = 1; - } - - if (config.getConfig('coppa') === true || bid.params.coppa) { - queryParams.tfcd = 1; - } - - let url = `https://${bid.params.delDomain}/v/1.0/avjp` - return { - method: 'GET', - url: url, - data: queryParams, - payload: {'bid': bid} - }; -} - -function handleVastResponse(response, serverResponse) { - const body = response.body - let bidResponses = []; - if (response !== undefined && body.vastUrl !== '' && body.pub_rev && body.pub_rev > 0) { - const openHtmlTag = ''; - const closeHtmlTag = ''; - const sdkScript = createSdkScript().outerHTML; - const placementDiv = createPlacementDiv(); - placementDiv.dataset.pId = PUBLISHER_ID; - const placementDivString = placementDiv.outerHTML; - const adResponse = getTemplateAdResponse(body.vastUrl); - const adResponseString = JSON.stringify(adResponse); - const ymAdsScript = ''; - - let bidResponse = {}; - bidResponse.requestId = serverResponse.bid.bidId; - bidResponse.bidderCode = BIDDER_CODE; - bidResponse.netRevenue = NET_REVENUE; - bidResponse.currency = CURRENCY; - bidResponse.cpm = Number(body.pub_rev) / 1000; - bidResponse.creativeId = body.adid; - bidResponse.height = body.height; - bidResponse.width = body.width; - bidResponse.vastUrl = body.vastUrl; - bidResponse.ttl = TIME_TO_LIVE; - bidResponse.mediaType = BANNER; - bidResponse.ad = openHtmlTag + placementDivString + ymAdsScript + sdkScript + closeHtmlTag; - - bidResponses.push(bidResponse); - } - return bidResponses; -} -registerBidder(spec); - -// HELPER FUNCTIONS -function createSdkScript() { - const script = document.createElement('script'); - script.innerHTML = YM_SCRIPT; - return script; -} -function createPlacementDiv() { - const div = document.createElement('div'); - div.id = `ym_${PLACEMENT_ID}`; - div.classList.add('ym'); - div.dataset.lfId = CR_ID; - return div -} - -/** - * Create a nativeplay template with the placement id and vastURL. - * @param vastUrl - */ -const getTemplateAdResponse = (vastUrl) => { - return { - loader: 'openxoutstream', - availability_zone: '', - data: [ - { - ads: [ - { - actions: {}, - adv_id: AD_ID, - configurables: { - cta_button_copy: 'Learn More', - vast_click_tracking: 'true', - vast_url: vastUrl, - }, - cr_id: CR_ID, - } - ], - column_count: 1, - configs: { - allowable_height: '248', - header_copy: 'You May Like', - ping: 'true', - }, - creative_format_id: 40, - css: '', - placement_id: PLACEMENT_ID, - } - ], - nc: 0, - }; -}; diff --git a/modules/openxoutstreamBidAdapter.md b/modules/openxoutstreamBidAdapter.md deleted file mode 100644 index 0eebb28463b..00000000000 --- a/modules/openxoutstreamBidAdapter.md +++ /dev/null @@ -1,43 +0,0 @@ -# Overview - -``` -Module Name: OpenX Outstream Bidder Adapter -Module Type: Bidder Adapter -Maintainer: opensource@yieldmo.com, jimmy.tu@openx.com -Note: Ads will only render in mobile -``` - -# Description - -Module that connects to OpenX's demand sources for outstream to Yieldmo. - -This bid adapter supports Banner. - -Note that the only supported size for demand is currently 400 x 300. - -# Example -```javascript -var adUnits = [ - { - code: 'test-div', - mediaTypes: { - 'banner': { - sizes: [[400, 300], // a display size - } - }, - bids: [ - { - bidder: 'openxoutstream', - params: { - unit: '540141567', - delDomain: 'se-demo-d.openx.net', - } - } - ] - } -]; -``` - -# Additional Details -[Banner Ads](https://docs.openx.com/Content/developers/containers/prebid-adapter.html) - diff --git a/test/spec/modules/openxoutstreamBidAdapter_spec.js b/test/spec/modules/openxoutstreamBidAdapter_spec.js deleted file mode 100644 index 634df1c8c6a..00000000000 --- a/test/spec/modules/openxoutstreamBidAdapter_spec.js +++ /dev/null @@ -1,243 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/openxoutstreamBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('OpenXOutstreamAdapter', function () { - const adapter = newBidder(spec); - const URLBASE = '/v/1.0/avjp'; - const BIDDER = 'openxoutstream'; - const div = document.createElement('div'); - const PLACEMENT_ID = '1986307928000988495'; - const YM_SCRIPT = `!function(e,t){if(void 0===t._ym){var a=Math.round(5*Math.random()/3)+'';t._ym='';var m=e.createElement('script');m.type='text/javascript',m.async=!0,m.src='//static.yieldmo.com/ym.'+a+'.js',(e.getElementsByTagName('head')[0]||e.getElementsByTagName('body')[0]).appendChild(m)}else t._ym instanceof String||void 0===t._ym.chkPls||t._ym.chkPls()}(document,window);`; - const PUBLISHER_ID = '1986307525700126029'; - const CR_ID = '2052941939925262540'; - const AD_ID = '1991358644725162800'; - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', function () { - describe('when request is for a banner ad', function () { - let bannerBid; - beforeEach(function () { - bannerBid = { - bidder: BIDDER, - params: {}, - adUnitCode: 'adunit-code', - mediaTypes: {banner: {}}, - sizes: [[300, 250], [300, 600]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; - }); - it('should return false when there is no delivery domain', function () { - bannerBid.params = {'unit': '12345678'}; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - - describe('when there is a delivery domain', function () { - beforeEach(function () { - bannerBid.params = {delDomain: 'test-delivery-domain'} - }); - - it('should return false if there is no adunit id and sizes are defined', function () { - bannerBid.mediaTypes.banner.sizes = [720, 90]; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - - it('should return true if there is delivery domain and unit', function () { - bannerBid.params.unit = '12345678'; - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); - }); - it('should return false if there is unit but no delivery domain', function () { - bannerBid.params = {unit: '12345678'}; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - it('shoud return false if there is no delivery domain and no unit', function () { - bannerBid.params = {}; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }) - }); - }); - }); - - describe('buildRequests for banner ads', function () { - const bidRequestsWithMediaType = [{ - 'bidder': BIDDER, - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'mediaType': 'banner', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' - }]; - - it('should send bid request to openx url via GET, with mediaType specified as banner', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); - const params = bidRequestsWithMediaType[0].params; - expect(request[0].url).to.equal(`https://` + params.delDomain + URLBASE); - expect(request[0].method).to.equal('GET'); - }); - - it('should send ad unit ids, height, and width when any are defined', function () { - const bidRequestsWithUnitIds = [{ - 'bidder': BIDDER, - 'params': { - 'unit': '540141567', - 'height': '200', - 'width': '250', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - sizes: [300, 250], - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - 'bidId': 'test-bid-id-2', - 'bidderRequestId': 'test-bid-request-2', - 'auctionId': 'test-auction-2' - }, { - 'bidder': BIDDER, - 'params': { - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [300, 250], - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - 'bidId': 'test-bid-id-1', - 'bidderRequestId': 'test-bid-request-1', - 'auctionId': 'test-auction-1' - }]; - const request = spec.buildRequests(bidRequestsWithUnitIds); - expect(request[0].data.auid).to.equal(`${bidRequestsWithUnitIds[0].params.unit}`); - expect(request[0].data.vht).to.not.equal(`${bidRequestsWithUnitIds[0].params.height}`); - expect(request[0].data.vwd).to.not.equal(`${bidRequestsWithUnitIds[0].params.width}`); - expect(request[0].data.vht).to.equal('184'); - expect(request[0].data.vwd).to.equal('414'); - expect(request[0].data.aus).to.equal('304x184%7C412x184%7C375x184%7C414x184'); - }); - - describe('interpretResponse', function () { - let serverResponse; - let serverRequest; - - beforeEach(function () { - serverResponse = { - body: { - width: 300, - height: 250, - pub_rev: 3000, - bidderCode: 'openxoutstream', - vastUrl: 'test.vast.url', - mediaType: 'banner', - adid: '9874652394875' - }, - header: 'header?', - }; - serverRequest = { - payload: { - bid: { - bidId: '2d36ac90d654af', - }, - } - }; - }); - - it('should correctly reorder the server response', function () { - const newResponse = spec.interpretResponse(serverResponse, serverRequest); - const openHtmlTag = ''; - const closeHtmlTag = ''; - const sdkScript = createSdkScript().outerHTML; - const placementDiv = createPlacementDiv(); - placementDiv.dataset.pId = PUBLISHER_ID; - const placementDivString = placementDiv.outerHTML; - const adResponse = getTemplateAdResponse(serverResponse.body.vastUrl, PLACEMENT_ID); - const adResponseString = JSON.stringify(adResponse); - const ymAdsScript = ''; - expect(newResponse.length).to.be.equal(1); - expect(newResponse[0]).to.deep.equal({ - requestId: '2d36ac90d654af', - bidderCode: 'openxoutstream', - vastUrl: 'test.vast.url', - mediaType: 'banner', - cpm: 3, - width: 300, - height: 250, - creativeId: '9874652394875', - currency: 'USD', - netRevenue: true, - ttl: 300, - ad: openHtmlTag + placementDivString + ymAdsScript + sdkScript + closeHtmlTag - }); - }); - - it('should not add responses if the cpm is 0 or null', function () { - serverResponse.body.pub_rev = 0; - let response = spec.interpretResponse(serverResponse, serverRequest); - expect(response).to.deep.equal([]); - - serverResponse.body.pub_rev = null; - response = spec.interpretResponse(serverResponse, serverRequest); - expect(response).to.deep.equal([]) - }); - }); - }) - - function createSdkScript() { - const script = document.createElement('script'); - script.innerHTML = YM_SCRIPT; - return script; - } - function createPlacementDiv() { - div.id = `ym_${PLACEMENT_ID}`; - div.classList.add('ym'); - div.dataset.lfId = CR_ID; - return div - } - const getTemplateAdResponse = (vastUrl) => { - return { - loader: 'openxoutstream', - availability_zone: '', - data: [ - { - ads: [ - { - actions: {}, - adv_id: AD_ID, - configurables: { - cta_button_copy: 'Learn More', - vast_click_tracking: 'true', - vast_url: vastUrl, - }, - cr_id: CR_ID, - } - ], - column_count: 1, - configs: { - allowable_height: '248', - header_copy: 'You May Like', - ping: 'true', - }, - creative_format_id: 40, - css: '', - placement_id: PLACEMENT_ID, - } - ], - nc: 0, - }; - }; -}); From 6b16a1fc8900fed438d87235ed84c5021c6af2c0 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 1 Nov 2019 13:51:18 -0400 Subject: [PATCH 11/49] fix broken yieldmo test --- test/spec/modules/yieldmoBidAdapter_spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 81c0108ab0d..007bc034e8c 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -80,8 +80,8 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.1}]'); - + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); + // console.log('placementInfo! ', placementInfo); bidArray.push({ bidder: 'yieldmo', params: { @@ -104,7 +104,7 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{sizes":[[300,250],[300,600]]}},"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.2}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); }); it('should add placement id if given', function () { From 8f3f98a295c454a1170236ce7fe29244452d7f8a Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 1 Nov 2019 13:55:08 -0400 Subject: [PATCH 12/49] remove log --- test/spec/modules/yieldmoBidAdapter_spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 007bc034e8c..2594f61f9b4 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -81,7 +81,6 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); - // console.log('placementInfo! ', placementInfo); bidArray.push({ bidder: 'yieldmo', params: { From c0cab3e7f72b36a4d1b850f7f2b20ffcc44704e4 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 22 Nov 2019 10:58:56 -0500 Subject: [PATCH 13/49] remove utils functions that will be depricated in 3.0 and use new referer object in bidderRequest --- modules/yieldmoBidAdapter.js | 4 ++-- test/spec/modules/yieldmoBidAdapter_spec.js | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index c0a40616b79..f101521c2e5 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -29,9 +29,9 @@ export const spec = { buildRequests: function(bidRequests, bidderRequest) { let serverRequest = { p: [], - page_url: utils.getTopWindowUrl(), + page_url: bidderRequest.refererInfo.referer, bust: new Date().getTime().toString(), - pr: utils.getTopWindowReferrer(), + pr: bidderRequest.refererInfo.referer, scrd: localWindow.devicePixelRatio || 0, dnt: getDNT(), e: getEnvironment(), diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 2594f61f9b4..b24447e8468 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -39,7 +39,12 @@ describe('YieldmoAdapter', function () { 'auctionStart': 1520001292880, 'timeout': 3000, 'start': 1520001292884, - 'doneCbCallCount': 0 + 'doneCbCallCount': 0, + 'refererInfo': { + 'numIframes': 1, + 'reachedTop': true, + 'referer': 'yieldmo.com' + } } describe('isBidRequestValid', function () { @@ -191,7 +196,7 @@ describe('YieldmoAdapter', function () { it('should add schain if it is in the bidRequest', () => { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; - const request = spec.buildRequests([bidArray[0]]); + const request = spec.buildRequests([bidArray[0]], bidderRequest); expect(request.data.schain).equal(JSON.stringify(schain)); }) }); From 32bef9d4568c6ff26ba6a357563ad17249645e5d Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Tue, 26 Nov 2019 11:00:42 -0500 Subject: [PATCH 14/49] use prebids gettopwindow util functions. update markdown with 3.0 compliant ad units object --- modules/yieldmoBidAdapter.js | 10 +--------- modules/yieldmoBidAdapter.md | 6 +++++- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index f101521c2e5..6a0bd9654b7 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -7,7 +7,7 @@ const TIME_TO_LIVE = 300; const NET_REVENUE = true; const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; -const localWindow = getTopWindow(); +const localWindow = utils.getWindowTop(); export const spec = { code: BIDDER_CODE, @@ -180,14 +180,6 @@ function getPageDescription() { } } -function getTopWindow() { - try { - return window.top; - } catch (e) { - return window; - } -} - /*************************************** * Detect Environment Helper Functions ***************************************/ diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index d1e34a41ecb..ef5f07a4eb9 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -18,7 +18,11 @@ var adUnits = [ // Banner adUnit { code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300,600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + } bids: [{ bidder: 'yieldmo', params: { From e5af53a4dff8f296d24f751193d49f0b52218978 Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Tue, 26 Nov 2019 16:48:57 -0500 Subject: [PATCH 15/49] Pass along us_privacy string --- modules/yieldmoBidAdapter.js | 4 ++-- test/spec/modules/yieldmoBidAdapter_spec.js | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 6a0bd9654b7..ccf565df5da 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -43,7 +43,8 @@ export const spec = { // case of undefined, stringify will remove param gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined - }) + }), + us_privacy: bidderRequest && bidderRequest.us_privacy, }; bidRequests.forEach((request) => { @@ -74,7 +75,6 @@ export const spec = { /** * Makes Yieldmo Ad Server response compatible to Prebid specs * @param serverResponse successful response from Ad Server - * @param bidderRequest original bidRequest * @return {Bid[]} an array of bids */ interpretResponse: function(serverResponse) { diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index b24447e8468..6a4a142975f 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -193,6 +193,13 @@ describe('YieldmoAdapter', function () { })); }); + it('should add ccpa information to request if available', () => { + const privacy = '1YNY'; + bidderRequest.us_privacy = privacy; + const data = spec.buildRequests(bidArray, bidderRequest).data; + expect(data.us_privacy).equal(privacy); + }); + it('should add schain if it is in the bidRequest', () => { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; From c3fdba6c2e91fe170e7bc41aaa6c22dcf0dbf7b5 Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Wed, 27 Nov 2019 10:09:32 -0500 Subject: [PATCH 16/49] remove blank.min --- modules/yieldmoBidAdapter.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index ccf565df5da..b360681b017 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -89,15 +89,8 @@ export const spec = { } return bids; }, - getUserSync: function(syncOptions) { - if (trackingEnabled(syncOptions)) { - return [{ - type: 'iframe', - url: SYNC_ENDPOINT + utils.getOrigin() - }]; - } else { - return []; - } + getUserSyncs: function(syncOptions) { + return []; } } registerBidder(spec); From 8f93b8fb52bddda584dcd567acb5d70e454b1130 Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Wed, 27 Nov 2019 10:18:17 -0500 Subject: [PATCH 17/49] Fix unit tests and remove unused variables and methods --- modules/yieldmoBidAdapter.js | 17 --------------- test/spec/modules/yieldmoBidAdapter_spec.js | 23 ++------------------- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index b360681b017..c8347cceae0 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -5,7 +5,6 @@ const BIDDER_CODE = 'yieldmo'; const CURRENCY = 'USD'; const TIME_TO_LIVE = 300; const NET_REVENUE = true; -const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; const localWindow = utils.getWindowTop(); @@ -138,22 +137,6 @@ function createNewBid(response) { }; } -/** - * Detects if tracking is allowed - * @returns false if dnt or if not iframe/pixel enabled - */ -function trackingEnabled(options) { - return (isIOS() && !getDNT() && options.iframeEnabled); -} - -/** - * Detects whether we're in iOS - * @returns true if in iOS - */ -function isIOS() { - return /iPhone|iPad|iPod/i.test(window.navigator.userAgent); -} - /** * Detects whether dnt is true * @returns true if user enabled dnt diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 6a4a142975f..7c5159add6c 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -252,26 +252,7 @@ describe('YieldmoAdapter', function () { }); }); - describe('getUserSync', function () { - const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; - let options = { - iframeEnabled: true, - pixelEnabled: true - }; - - it('should return a tracker with type and url as parameters', function () { - if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) { - expect(spec.getUserSync(options)).to.deep.equal([{ - type: 'iframe', - url: SYNC_ENDPOINT + utils.getOrigin() - }]); - - options.iframeEnabled = false; - expect(spec.getUserSync(options)).to.deep.equal([]); - } else { - // not ios, so tracker will fail - expect(spec.getUserSync(options)).to.deep.equal([]); - } - }); + describe('getUserSyncs', function () { + expect(spec.getUserSyncs({})).to.deep.equal([]); }); }); From 6dc4d82b0ef085135dc1b8ab38553173dfe1ec7d Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:05:08 -0400 Subject: [PATCH 18/49] add stringified schain --- modules/yieldmoBidAdapter.js | 341 ++++++++++++++++++++ test/spec/AnalyticsAdapter_spec.js | 242 +++++++------- test/spec/modules/yieldmoBidAdapter_spec.js | 227 +++++++++++++ 3 files changed, 689 insertions(+), 121 deletions(-) create mode 100644 modules/yieldmoBidAdapter.js create mode 100644 test/spec/modules/yieldmoBidAdapter_spec.js diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js new file mode 100644 index 00000000000..eaa053456d0 --- /dev/null +++ b/modules/yieldmoBidAdapter.js @@ -0,0 +1,341 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; + +const BIDDER_CODE = 'yieldmo'; +const CURRENCY = 'USD'; +const TIME_TO_LIVE = 300; +const NET_REVENUE = true; +const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; +const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; +const localWindow = getTopWindow(); + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['banner'], + /** + * Determines whether or not the given bid request is valid. + * @param {object} bid, bid to validate + * @return boolean, true if valid, otherwise false + */ + isBidRequestValid: function(bid) { + return !!(bid && bid.adUnitCode && bid.bidId); + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(bidRequests) { + console.log('bid requests'); + console.log(bidRequests); + let serverRequest = { + p: [], + page_url: utils.getTopWindowUrl(), + bust: new Date().getTime().toString(), + pr: utils.getTopWindowReferrer(), + scrd: localWindow.devicePixelRatio || 0, + dnt: getDNT(), + e: getEnvironment(), + description: getPageDescription(), + title: localWindow.document.title || '', + w: localWindow.innerWidth, + h: localWindow.innerHeight + }; + + bidRequests.forEach((request) => { + serverRequest.p.push(addPlacement(request)); + const pubcid = getId(request, 'pubcid'); + if (pubcid) { + serverRequest.pubcid = pubcid; + } else if (request.crumbs) { + if (request.crumbs.pubcid) { + serverRequest.pubcid = request.crumbs.pubcid; + } + } + const tdid = getId(request, 'tdid'); + if (tdid) { + serverRequest.tdid = tdid; + } + if (request.schain) { + serverRequest.schain = JSON.stringify(request.schain); + } + }); + serverRequest.p = '[' + serverRequest.p.toString() + ']'; + return { + method: 'GET', + url: SERVER_ENDPOINT, + data: serverRequest + } + }, + /** + * Makes Yieldmo Ad Server response compatible to Prebid specs + * @param serverResponse successful response from Ad Server + * @param bidderRequest original bidRequest + * @return {Bid[]} an array of bids + */ + interpretResponse: function(serverResponse) { + let bids = []; + let data = serverResponse.body; + if (data.length > 0) { + data.forEach((response) => { + if (response.cpm && response.cpm > 0) { + bids.push(createNewBid(response)); + } + }); + } + return bids; + }, + getUserSync: function(syncOptions) { + if (trackingEnabled(syncOptions)) { + return [{ + type: 'iframe', + url: SYNC_ENDPOINT + utils.getOrigin() + }]; + } else { + return []; + } + } +} +registerBidder(spec); + +/*************************************** + * Helper Functions + ***************************************/ + +/** + * Adds placement information to array + * @param request bid request + */ +function addPlacement(request) { + const placementInfo = { + placement_id: request.adUnitCode, + callback_id: request.bidId, + sizes: request.sizes + } + if (request.params) { + if (request.params.placementId) { + placementInfo.ym_placement_id = request.params.placementId; + } + if (request.params.bidFloor) { + placementInfo.bidFloor = request.params.bidFloor; + } + } + return JSON.stringify(placementInfo); +} + +/** + * creates a new bid with response information + * @param response server response + */ +function createNewBid(response) { + return { + requestId: response['callback_id'], + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creative_id, + currency: CURRENCY, + netRevenue: NET_REVENUE, + ttl: TIME_TO_LIVE, + ad: response.ad + }; +} + +/** + * Detects if tracking is allowed + * @returns false if dnt or if not iframe/pixel enabled + */ +function trackingEnabled(options) { + return (isIOS() && !getDNT() && options.iframeEnabled); +} + +/** + * Detects whether we're in iOS + * @returns true if in iOS + */ +function isIOS() { + return /iPhone|iPad|iPod/i.test(window.navigator.userAgent); +} + +/** + * Detects whether dnt is true + * @returns true if user enabled dnt + */ +function getDNT() { + return window.doNotTrack === '1' || window.navigator.doNotTrack === '1' || false; +} + +/** + * get page description + */ +function getPageDescription() { + if (document.querySelector('meta[name="description"]')) { + return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. + } else { + return ''; + } +} + +function getTopWindow() { + try { + return window.top; + } catch (e) { + return window; + } +} + +/*************************************** + * Detect Environment Helper Functions + ***************************************/ + +/** + * Represents a method for loading Yieldmo ads. Environments affect + * which formats can be loaded into the page + * Environments: + * CodeOnPage: 0, // div directly on publisher's page + * Amp: 1, // google Accelerate Mobile Pages ampproject.org + * Mraid = 2, // native loaded through the MRAID spec, without Yieldmo's SDK https://www.iab.net/media/file/IAB_MRAID_v2_FINAL.pdf + * Dfp: 4, // google doubleclick for publishers https://www.doubleclickbygoogle.com/ + * DfpInAmp: 5, // AMP page containing a DFP iframe + * SafeFrame: 10, + * DfpSafeFrame: 11,Sandboxed: 16, // An iframe that can't get to the top window. + * SuperSandboxed: 89, // An iframe without allow-same-origin + * Unknown: 90, // A default sandboxed implementation delivered by EnvironmentDispatch when all positive environment checks fail + */ + +/** + * Detects what environment we're in + * @returns Environment kind + */ +function getEnvironment() { + if (isSuperSandboxedIframe()) { + return 89; + } else if (isDfpInAmp()) { + return 5; + } else if (isDfp()) { + return 4; + } else if (isAmp()) { + return 1; + } else if (isDFPSafeFrame()) { + return 11; + } else if (isSafeFrame()) { + return 10; + } else if (isMraid()) { + return 2; + } else if (isCodeOnPage()) { + return 0; + } else if (isSandboxedIframe()) { + return 16; + } else { + return 90; + } +} + +/** + * @returns true if we are running on the top window at dispatch time + */ +function isCodeOnPage() { + return window === window.parent; +} + +/** + * @returns true if the environment is both DFP and AMP + */ +function isDfpInAmp() { + return isDfp() && isAmp(); +} + +/** + * @returns true if the window is in an iframe whose id and parent element id match DFP + */ +function isDfp() { + try { + const frameElement = window.frameElement; + const parentElement = window.frameElement.parentNode; + if (frameElement && parentElement) { + return frameElement.id.indexOf('google_ads_iframe') > -1 && parentElement.id.indexOf('google_ads_iframe') > -1; + } + return false; + } catch (e) { + return false; + } +} + +/** +* @returns true if there is an AMP context object +*/ +function isAmp() { + try { + const ampContext = window.context || window.parent.context; + if (ampContext && ampContext.pageViewId) { + return ampContext; + } + return false; + } catch (e) { + return false; + } +} + +/** + * @returns true if the environment is a SafeFrame. + */ +function isSafeFrame() { + return window.$sf && window.$sf.ext; +} + +/** + * @returns true if the environment is a dfp safe frame. + */ +function isDFPSafeFrame() { + if (window.location && window.location.href) { + const href = window.location.href; + return isSafeFrame() && href.indexOf('google') !== -1 && href.indexOf('safeframe') !== -1; + } + return false; +} + +/** + * Return true if we are in an iframe and can't access the top window. + */ +function isSandboxedIframe() { + return window.top !== window && !window.frameElement; +} + +/** + * Return true if we cannot document.write to a child iframe (this implies no allow-same-origin) + */ +function isSuperSandboxedIframe() { + const sacrificialIframe = window.document.createElement('iframe'); + try { + sacrificialIframe.setAttribute('style', 'display:none'); + window.document.body.appendChild(sacrificialIframe); + sacrificialIframe.contentWindow._testVar = true; + window.document.body.removeChild(sacrificialIframe); + return false; + } catch (e) { + window.document.body.removeChild(sacrificialIframe); + return true; + } +} + +/** + * @returns true if the window has the attribute identifying MRAID + */ +function isMraid() { + return !!(window.mraid); +} + +/** + * Gets an id from the userId object if it exists + * @param {*} request + * @param {*} idType + * @returns an id if there is one, or undefined + */ +function getId(request, idType) { + let id; + if (request && request.userId && request.userId[idType] && typeof request.userId === 'object') { + id = request.userId[idType]; + } + return id; +} diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 2e992d3298c..cdded54e307 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; - - beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); - }); - - afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); - }); - - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; - - adapter.track({ eventType, args }); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); - }); - - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); - }); + let xhr; + let requests; + let adapter; - describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); }); afterEach(function () { - events.getEvents.restore(); + xhr.restore(); + adapter.disableAnalytics(); }); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; - adapter.enableAnalytics(); - events.emit(eventType, args); + adapter.track({ eventType, args }); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; - adapter.enableAnalytics(); events.emit(eventType, args); + adapter.enableAnalytics(); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + describe(`WHEN an event occurs after enable analytics\n`, function () { + beforeEach(function () { + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + afterEach(function () { + events.getEvents.restore(); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); - }); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); - }); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - expect(requests.length).to.equal(1); - }); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); - afterEach(function () { - Math.random.restore(); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); events.emit(eventType, args); expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; + + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); + }); + + afterEach(function () { + Math.random.restore(); + }); + + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - events.emit(eventType, args); - expect(requests.length).to.equal(0); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(0); + }); }); }); }); -}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js new file mode 100644 index 00000000000..803e4b012ed --- /dev/null +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -0,0 +1,227 @@ +import { expect } from 'chai'; +import { spec } from 'modules/yieldmoBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +describe('YieldmoAdapter', function () { + const adapter = newBidder(spec); + const ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; + + let tdid = '8d146286-91d4-4958-aff4-7e489dd1abd6'; + + let bid = { + bidder: 'yieldmo', + params: { + bidFloor: 0.1 + }, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + crumbs: { + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + }, + userId: { + tdid, + } + }; + let bidArray = [bid]; + + describe('isBidRequestValid', function () { + it('should return true when necessary information is found', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + + it('should return false when necessary information is not found', function () { + // empty bid + expect(spec.isBidRequestValid({})).to.be.false; + + // empty bidId + bid.bidId = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + + // empty adUnitCode + bid.bidId = '30b31c1838de1e'; + bid.adUnitCode = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + + bid.adUnitCode = 'adunit-code'; + }); + }); + + describe('buildRequests', function () { + it('should attempt to send bid requests to the endpoint via GET', function () { + const request = spec.buildRequests(bidArray); + expect(request.method).to.equal('GET'); + expect(request.url).to.be.equal(ENDPOINT); + }); + + it('should not blow up if crumbs is undefined', function () { + let bidArray = [ + { ...bid, crumbs: undefined } + ] + expect(function () { spec.buildRequests(bidArray) }).not.to.throw() + }) + + it('should place bid information into the p parameter of data', function () { + let placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); + + bidArray.push({ + bidder: 'yieldmo', + params: { + bidFloor: 0.2 + }, + adUnitCode: 'adunit-code-1', + sizes: [[300, 250], [300, 600]], + bidId: '123456789', + bidderRequestId: '987654321', + auctionId: '0246810', + crumbs: { + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + } + + }); + + // multiple placements + placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); + }); + + it('should add placement id if given', function () { + bidArray[0].params.placementId = 'ym_1293871298'; + let placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); + expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"'); + + bidArray[1].params.placementId = 'ym_0987654321'; + placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); + expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"'); + }); + + it('should add additional information to data parameter of request', function () { + const data = spec.buildRequests(bidArray).data; + expect(data.hasOwnProperty('page_url')).to.be.true; + expect(data.hasOwnProperty('bust')).to.be.true; + expect(data.hasOwnProperty('pr')).to.be.true; + expect(data.hasOwnProperty('scrd')).to.be.true; + expect(data.dnt).to.be.false; + expect(data.e).to.equal(90); + expect(data.hasOwnProperty('description')).to.be.true; + expect(data.hasOwnProperty('title')).to.be.true; + expect(data.hasOwnProperty('h')).to.be.true; + expect(data.hasOwnProperty('w')).to.be.true; + expect(data.hasOwnProperty('pubcid')).to.be.true; + }); + + it('should add pubcid as parameter of request', function () { + const pubcidBid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: { + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' + } + }; + const data = spec.buildRequests([pubcidBid]).data; + expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); + }); + + it('should add unified id as parameter of request', function () { + const unifiedIdBid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: { + tdid, + } + }; + const data = spec.buildRequests([unifiedIdBid]).data; + expect(data.tdid).to.deep.equal(tdid); + }); + + it('should add schain if it is in the bidRequest', () => { + const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; + bidArray[0].schain = schain; + const request = spec.buildRequests([bidArray[0]]); + expect(request.data.schain).equal(JSON.stringify(schain)); + }) + }); + + describe('interpretResponse', function () { + let serverResponse; + + beforeEach(function () { + serverResponse = { + body: [{ + callback_id: '21989fdbef550a', + cpm: 3.45455, + width: 300, + height: 250, + ad: '
', + creative_id: '9874652394875' + }], + header: 'header?' + }; + }) + + it('should correctly reorder the server response', function () { + const newResponse = spec.interpretResponse(serverResponse); + expect(newResponse.length).to.be.equal(1); + expect(newResponse[0]).to.deep.equal({ + requestId: '21989fdbef550a', + cpm: 3.45455, + width: 300, + height: 250, + creativeId: '9874652394875', + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: '
' + }); + }); + + it('should not add responses if the cpm is 0 or null', function () { + serverResponse.body[0].cpm = 0; + let response = spec.interpretResponse(serverResponse); + expect(response).to.deep.equal([]); + + serverResponse.body[0].cpm = null; + response = spec.interpretResponse(serverResponse); + expect(response).to.deep.equal([]) + }); + }); + + describe('getUserSync', function () { + const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; + let options = { + iframeEnabled: true, + pixelEnabled: true + }; + + it('should return a tracker with type and url as parameters', function () { + if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) { + expect(spec.getUserSync(options)).to.deep.equal([{ + type: 'iframe', + url: SYNC_ENDPOINT + utils.getOrigin() + }]); + + options.iframeEnabled = false; + expect(spec.getUserSync(options)).to.deep.equal([]); + } else { + // not ios, so tracker will fail + expect(spec.getUserSync(options)).to.deep.equal([]); + } + }); + }); +}); From 078dde02ece8681ea5d0a81918537b7f73293817 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:08:46 -0400 Subject: [PATCH 19/49] Revert "add stringified schain" This reverts commit 4fd8634f12133945ac44e9b550237321e71fc549. --- modules/yieldmoBidAdapter.js | 5 - test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++---------- test/spec/modules/yieldmoBidAdapter_spec.js | 7 - 3 files changed, 121 insertions(+), 133 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index eaa053456d0..fd09cbaa4ea 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -27,8 +27,6 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(bidRequests) { - console.log('bid requests'); - console.log(bidRequests); let serverRequest = { p: [], page_url: utils.getTopWindowUrl(), @@ -57,9 +55,6 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } - if (request.schain) { - serverRequest.schain = JSON.stringify(request.schain); - } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index cdded54e307..2e992d3298c 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; + let xhr; + let requests; + let adapter; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); + }); + + afterEach(function () { + xhr.restore(); + adapter.disableAnalytics(); + }); + + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; + + adapter.track({ eventType, args }); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + }); + + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + }); + describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); + events.getEvents.restore(); }); - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - adapter.track({ eventType, args }); + adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - events.emit(eventType, args); adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); - describe(`WHEN an event occurs after enable analytics\n`, function () { - beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - afterEach(function () { - events.getEvents.restore(); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + events.emit(eventType, args); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + expect(requests.length).to.equal(1); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); }); - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - adapter.enableAnalytics(); - events.emit(eventType, args); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + afterEach(function () { + Math.random.restore(); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); events.emit(eventType, args); expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; - - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); - }); - - afterEach(function () { - Math.random.restore(); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } }); + events.emit(eventType, args); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); - - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(0); - }); + expect(requests.length).to.equal(0); }); }); }); +}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 803e4b012ed..60fe25db95e 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -149,13 +149,6 @@ describe('YieldmoAdapter', function () { const data = spec.buildRequests([unifiedIdBid]).data; expect(data.tdid).to.deep.equal(tdid); }); - - it('should add schain if it is in the bidRequest', () => { - const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; - bidArray[0].schain = schain; - const request = spec.buildRequests([bidArray[0]]); - expect(request.data.schain).equal(JSON.stringify(schain)); - }) }); describe('interpretResponse', function () { From 76395dbf4a8d9308767f327c4f5f9aa6c5ae8820 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Wed, 16 Oct 2019 15:01:18 -0400 Subject: [PATCH 20/49] pass along gdpr consent string and gdpr applies through get --- modules/yieldmoBidAdapter.js | 9 ++++- test/spec/modules/yieldmoBidAdapter_spec.js | 41 ++++++++++++++++----- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index fd09cbaa4ea..1226ce32392 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -26,7 +26,7 @@ export const spec = { * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(bidRequests) { + buildRequests: function(bidRequests, bidderRequest) { let serverRequest = { p: [], page_url: utils.getTopWindowUrl(), @@ -38,7 +38,12 @@ export const spec = { description: getPageDescription(), title: localWindow.document.title || '', w: localWindow.innerWidth, - h: localWindow.innerHeight + h: localWindow.innerHeight, + user: JSON.stringify({ + // case of undefined, stringify will remove param + gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, + consentString: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined + }) }; bidRequests.forEach((request) => { diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 60fe25db95e..c148684323a 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -27,6 +27,16 @@ describe('YieldmoAdapter', function () { } }; let bidArray = [bid]; + let bidderRequest = { + 'bidderCode': 'yieldmo', + 'auctionId': 'e3a336ad-2761-4a1c-b421-ecc7c5294a34', + 'bidderRequestId': '14c4ede8c693f', + 'bids': bidArray, + 'auctionStart': 1520001292880, + 'timeout': 3000, + 'start': 1520001292884, + 'doneCbCallCount': 0 + } describe('isBidRequestValid', function () { it('should return true when necessary information is found', function () { @@ -52,7 +62,7 @@ describe('YieldmoAdapter', function () { describe('buildRequests', function () { it('should attempt to send bid requests to the endpoint via GET', function () { - const request = spec.buildRequests(bidArray); + const request = spec.buildRequests(bidArray, bidderRequest); expect(request.method).to.equal('GET'); expect(request.url).to.be.equal(ENDPOINT); }); @@ -61,11 +71,11 @@ describe('YieldmoAdapter', function () { let bidArray = [ { ...bid, crumbs: undefined } ] - expect(function () { spec.buildRequests(bidArray) }).not.to.throw() + expect(function () { spec.buildRequests(bidArray, bidderRequest) }).not.to.throw() }) it('should place bid information into the p parameter of data', function () { - let placementInfo = spec.buildRequests(bidArray).data.p; + let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); bidArray.push({ @@ -85,24 +95,24 @@ describe('YieldmoAdapter', function () { }); // multiple placements - placementInfo = spec.buildRequests(bidArray).data.p; + placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); }); it('should add placement id if given', function () { bidArray[0].params.placementId = 'ym_1293871298'; - let placementInfo = spec.buildRequests(bidArray).data.p; + let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"'); bidArray[1].params.placementId = 'ym_0987654321'; - placementInfo = spec.buildRequests(bidArray).data.p; + placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"'); }); it('should add additional information to data parameter of request', function () { - const data = spec.buildRequests(bidArray).data; + const data = spec.buildRequests(bidArray, bidderRequest).data; expect(data.hasOwnProperty('page_url')).to.be.true; expect(data.hasOwnProperty('bust')).to.be.true; expect(data.hasOwnProperty('pr')).to.be.true; @@ -129,7 +139,7 @@ describe('YieldmoAdapter', function () { pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' } }; - const data = spec.buildRequests([pubcidBid]).data; + const data = spec.buildRequests([pubcidBid], bidderRequest).data; expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); }); @@ -146,9 +156,22 @@ describe('YieldmoAdapter', function () { tdid, } }; - const data = spec.buildRequests([unifiedIdBid]).data; + const data = spec.buildRequests([unifiedIdBid], bidderRequest).data; expect(data.tdid).to.deep.equal(tdid); }); + + it('should add gdpr information to request if available', () => { + bidderRequest.gdprConsent = { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'vendorData': {'blerp': 1}, + 'gdprApplies': true + } + const data = spec.buildRequests(bidArray, bidderRequest).data; + expect(data.user).equal(JSON.stringify({ + 'gdprApplies': true, + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' + })); + }); }); describe('interpretResponse', function () { From c8f1bb62d799c74b1406495964f85242efa72e69 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Thu, 17 Oct 2019 11:24:26 -0400 Subject: [PATCH 21/49] use paramter gdprConsent --- modules/yieldmoBidAdapter.js | 2 +- test/spec/modules/yieldmoBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 1226ce32392..725a361789b 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -39,7 +39,7 @@ export const spec = { title: localWindow.document.title || '', w: localWindow.innerWidth, h: localWindow.innerHeight, - user: JSON.stringify({ + gdprConsent: JSON.stringify({ // case of undefined, stringify will remove param gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, consentString: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index c148684323a..78cddf44e38 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -167,7 +167,7 @@ describe('YieldmoAdapter', function () { 'gdprApplies': true } const data = spec.buildRequests(bidArray, bidderRequest).data; - expect(data.user).equal(JSON.stringify({ + expect(data.gdprConsent).equal(JSON.stringify({ 'gdprApplies': true, 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' })); From f44b9ba098b79b6965d150a6f0135c7396d77906 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:05:08 -0400 Subject: [PATCH 22/49] add stringified schain --- modules/yieldmoBidAdapter.js | 3 + test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++---------- test/spec/modules/yieldmoBidAdapter_spec.js | 6 + 3 files changed, 130 insertions(+), 121 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 725a361789b..22b20511daf 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -60,6 +60,9 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } + if (request.schain) { + serverRequest.schain = JSON.stringify(request.schain); + } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 2e992d3298c..cdded54e307 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; - - beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); - }); - - afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); - }); - - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; - - adapter.track({ eventType, args }); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); - }); - - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); - }); + let xhr; + let requests; + let adapter; - describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); }); afterEach(function () { - events.getEvents.restore(); + xhr.restore(); + adapter.disableAnalytics(); }); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; - adapter.enableAnalytics(); - events.emit(eventType, args); + adapter.track({ eventType, args }); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; - adapter.enableAnalytics(); events.emit(eventType, args); + adapter.enableAnalytics(); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + describe(`WHEN an event occurs after enable analytics\n`, function () { + beforeEach(function () { + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + afterEach(function () { + events.getEvents.restore(); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); - }); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); - }); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - expect(requests.length).to.equal(1); - }); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); - afterEach(function () { - Math.random.restore(); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); events.emit(eventType, args); expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; + + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); + }); + + afterEach(function () { + Math.random.restore(); + }); + + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - events.emit(eventType, args); - expect(requests.length).to.equal(0); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(0); + }); }); }); }); -}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 78cddf44e38..f143caa8c1e 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -172,6 +172,12 @@ describe('YieldmoAdapter', function () { 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' })); }); + it('should add schain if it is in the bidRequest', () => { + const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; + bidArray[0].schain = schain; + const request = spec.buildRequests([bidArray[0]]); + expect(request.data.schain).equal(JSON.stringify(schain)); + }) }); describe('interpretResponse', function () { From 3c089125671a0b334b2cccd12a03a462d90c12a6 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 17:33:15 -0400 Subject: [PATCH 23/49] don't change other files --- test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++++++--------------- 1 file changed, 121 insertions(+), 121 deletions(-) diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index cdded54e307..2e992d3298c 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; + let xhr; + let requests; + let adapter; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); + }); + + afterEach(function () { + xhr.restore(); + adapter.disableAnalytics(); + }); + + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; + + adapter.track({ eventType, args }); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + }); + + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + }); + describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); + events.getEvents.restore(); }); - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - adapter.track({ eventType, args }); + adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - events.emit(eventType, args); adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); - describe(`WHEN an event occurs after enable analytics\n`, function () { - beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - afterEach(function () { - events.getEvents.restore(); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + events.emit(eventType, args); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + expect(requests.length).to.equal(1); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); }); - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - adapter.enableAnalytics(); - events.emit(eventType, args); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + afterEach(function () { + Math.random.restore(); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); events.emit(eventType, args); expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; - - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); - }); - - afterEach(function () { - Math.random.restore(); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } }); + events.emit(eventType, args); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); - - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(0); - }); + expect(requests.length).to.equal(0); }); }); }); +}); From 2bd4486756d8bc4d8ea46a61325c4fa319193598 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Mon, 21 Oct 2019 17:37:12 -0400 Subject: [PATCH 24/49] change parameter namves --- modules/yieldmoBidAdapter.js | 6 +++--- test/spec/modules/yieldmoBidAdapter_spec.js | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 22b20511daf..a3623941ddc 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -39,10 +39,10 @@ export const spec = { title: localWindow.document.title || '', w: localWindow.innerWidth, h: localWindow.innerHeight, - gdprConsent: JSON.stringify({ + userConsent: JSON.stringify({ // case of undefined, stringify will remove param - gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, - consentString: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined + gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, + cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined }) }; diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index f143caa8c1e..139997ec2ee 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -167,11 +167,12 @@ describe('YieldmoAdapter', function () { 'gdprApplies': true } const data = spec.buildRequests(bidArray, bidderRequest).data; - expect(data.gdprConsent).equal(JSON.stringify({ + expect(data.userConsent).equal(JSON.stringify({ 'gdprApplies': true, - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' + 'cmp': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' })); }); + it('should add schain if it is in the bidRequest', () => { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; From b05b9af700331b9852cd5ba3ff7b45194dda434d Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 25 Oct 2019 11:20:43 -0400 Subject: [PATCH 25/49] updates bidder module to be 3.0 compliant, and tests --- modules/yieldmoBidAdapter.js | 2 +- test/spec/modules/yieldmoBidAdapter_spec.js | 28 ++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index a3623941ddc..c0a40616b79 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -114,7 +114,7 @@ function addPlacement(request) { const placementInfo = { placement_id: request.adUnitCode, callback_id: request.bidId, - sizes: request.sizes + sizes: request.mediaTypes.banner.sizes } if (request.params) { if (request.params.placementId) { diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 139997ec2ee..81c0108ab0d 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -15,7 +15,11 @@ describe('YieldmoAdapter', function () { bidFloor: 0.1 }, adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -76,7 +80,7 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.1}]'); bidArray.push({ bidder: 'yieldmo', @@ -84,7 +88,11 @@ describe('YieldmoAdapter', function () { bidFloor: 0.2 }, adUnitCode: 'adunit-code-1', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '123456789', bidderRequestId: '987654321', auctionId: '0246810', @@ -96,7 +104,7 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{sizes":[[300,250],[300,600]]}},"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.2}]'); }); it('should add placement id if given', function () { @@ -131,7 +139,11 @@ describe('YieldmoAdapter', function () { bidder: 'yieldmo', params: {}, adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -148,7 +160,11 @@ describe('YieldmoAdapter', function () { bidder: 'yieldmo', params: {}, adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', From 317b18f26e28d27a72cbac1c12272df8c28c656a Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 1 Nov 2019 13:15:14 -0400 Subject: [PATCH 26/49] deletes openxoutstream adapter --- modules/openxoutstreamBidAdapter.js | 212 ---------------- modules/openxoutstreamBidAdapter.md | 43 ---- .../modules/openxoutstreamBidAdapter_spec.js | 237 ------------------ 3 files changed, 492 deletions(-) delete mode 100644 modules/openxoutstreamBidAdapter.js delete mode 100644 modules/openxoutstreamBidAdapter.md delete mode 100644 test/spec/modules/openxoutstreamBidAdapter_spec.js diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js deleted file mode 100644 index b9760c0c3bb..00000000000 --- a/modules/openxoutstreamBidAdapter.js +++ /dev/null @@ -1,212 +0,0 @@ -import { config } from '../src/config'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import * as utils from '../src/utils'; -import { BANNER } from '../src/mediaTypes'; - -const SUPPORTED_AD_TYPES = [BANNER]; -const BIDDER_CODE = 'openxoutstream'; -const BIDDER_CONFIG = 'hb_pb_ym'; -const BIDDER_VERSION = '1.0.1'; -const CURRENCY = 'USD'; -const NET_REVENUE = true; -const TIME_TO_LIVE = 300; -const YM_SCRIPT = `!function(e,t){if(void 0===t._ym){var a=Math.round(5*Math.random()/3)+'';t._ym='';var m=e.createElement('script');m.type='text/javascript',m.async=!0,m.src='//static.yieldmo.com/ym.'+a+'.js',(e.getElementsByTagName('head')[0]||e.getElementsByTagName('body')[0]).appendChild(m)}else t._ym instanceof String||void 0===t._ym.chkPls||t._ym.chkPls()}(document,window);`; -const PLACEMENT_ID = '1986307928000988495'; -const PUBLISHER_ID = '1986307525700126029'; -const CR_ID = '2052941939925262540'; -const AD_ID = '1991358644725162800'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: SUPPORTED_AD_TYPES, - isBidRequestValid: function(bidRequest) { - return !!(bidRequest.params.delDomain && bidRequest.params.unit) - }, - buildRequests: function(bidRequests, bidderRequest) { - if (bidRequests.length === 0) { - return []; - } - let requests = []; - bidRequests.forEach(bid => { - requests.push(buildOXBannerRequest(bid, bidderRequest)); - }) - return requests; - }, - interpretResponse: function(bid, serverResponse) { - return handleVastResponse(bid, serverResponse.payload) - }, -}; - -function getViewportDimensions(isIfr) { - let width; - let height; - let tWin = window; - let body; - - if (isIfr) { - let tDoc; - try { - tWin = window.top; - tDoc = window.top.document; - } catch (e) { - return; - } - body = tDoc.body; - - width = tWin.innerWidth || docEl.clientWidth || body.clientWidth; - height = tWin.innerHeight || docEl.clientHeight || body.clientHeight; - } else { - width = tWin.innerWidth || docEl.clientWidth; - height = tWin.innerHeight || docEl.clientHeight; - } - - return `${width}x${height}`; -} - -function buildCommonQueryParamsFromBids(bid, bidderRequest) { - const isInIframe = utils.inIframe(); - let defaultParams; - const height = '184'; - const width = '414'; - const aus = '304x184%7C412x184%7C375x184%7C414x184'; - defaultParams = { - ju: config.getConfig('pageUrl') || bidderRequest.refererInfo.referer, - ch: document.charSet || document.characterSet, - res: `${screen.width}x${screen.height}x${screen.colorDepth}`, - ifr: isInIframe, - tz: new Date().getTimezoneOffset(), - tws: getViewportDimensions(isInIframe), - be: 1, - bc: bid.params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, - auid: bid.params.unit, - dddid: bid.transactionId, - openrtb: '%7B%22mimes%22%3A%5B%22video%2Fmp4%22%5D%7D', - nocache: new Date().getTime(), - vht: height, - vwd: width, - aus: aus - }; - - if (utils.deepAccess(bidderRequest, 'gdprConsent')) { - let gdprConsentConfig = bidderRequest.gdprConsent; - - if (gdprConsentConfig.consentString !== undefined) { - defaultParams.gdpr_consent = gdprConsentConfig.consentString; - } - - if (gdprConsentConfig.gdprApplies !== undefined) { - defaultParams.gdpr = gdprConsentConfig.gdprApplies ? 1 : 0; - } - - if (config.getConfig('consentManagement.cmpApi') === 'iab') { - defaultParams.x_gdpr_f = 1; - } - } - - return defaultParams; -} - -function buildOXBannerRequest(bid, bidderRequest) { - let queryParams = buildCommonQueryParamsFromBids(bid, bidderRequest); - - if (bid.params.doNotTrack) { - queryParams.ns = 1; - } - - if (config.getConfig('coppa') === true || bid.params.coppa) { - queryParams.tfcd = 1; - } - - let url = `https://${bid.params.delDomain}/v/1.0/avjp`; - return { - method: 'GET', - url: url, - data: queryParams, - payload: {'bid': bid} - }; -} - -function handleVastResponse(response, serverResponse) { - const body = response.body - let bidResponses = []; - if (response !== undefined && body.vastUrl !== '' && body.pub_rev && body.pub_rev > 0) { - const openHtmlTag = ''; - const closeHtmlTag = ''; - const sdkScript = createSdkScript().outerHTML; - const placementDiv = createPlacementDiv(); - placementDiv.dataset.pId = PUBLISHER_ID; - const placementDivString = placementDiv.outerHTML; - const adResponse = getTemplateAdResponse(body.vastUrl); - const adResponseString = JSON.stringify(adResponse); - const ymAdsScript = ''; - - let bidResponse = {}; - bidResponse.requestId = serverResponse.bid.bidId; - bidResponse.bidderCode = BIDDER_CODE; - bidResponse.netRevenue = NET_REVENUE; - bidResponse.currency = CURRENCY; - bidResponse.cpm = Number(body.pub_rev) / 1000; - bidResponse.creativeId = body.adid; - bidResponse.height = body.height; - bidResponse.width = body.width; - bidResponse.vastUrl = body.vastUrl; - bidResponse.ttl = TIME_TO_LIVE; - bidResponse.mediaType = BANNER; - bidResponse.ad = openHtmlTag + placementDivString + ymAdsScript + sdkScript + closeHtmlTag; - - bidResponses.push(bidResponse); - } - return bidResponses; -} -registerBidder(spec); - -// HELPER FUNCTIONS -function createSdkScript() { - const script = document.createElement('script'); - script.innerHTML = YM_SCRIPT; - return script; -} -function createPlacementDiv() { - const div = document.createElement('div'); - div.id = `ym_${PLACEMENT_ID}`; - div.classList.add('ym'); - div.dataset.lfId = CR_ID; - return div -} - -/** - * Create a nativeplay template with the placement id and vastURL. - * @param vastUrl - */ -const getTemplateAdResponse = (vastUrl) => { - return { - loader: 'openxoutstream', - availability_zone: '', - data: [ - { - ads: [ - { - actions: {}, - adv_id: AD_ID, - configurables: { - cta_button_copy: 'Learn More', - vast_click_tracking: 'true', - vast_url: vastUrl, - }, - cr_id: CR_ID, - } - ], - column_count: 1, - configs: { - allowable_height: '248', - header_copy: 'You May Like', - ping: 'true', - }, - creative_format_id: 40, - css: '', - placement_id: PLACEMENT_ID, - } - ], - nc: 0, - }; -}; diff --git a/modules/openxoutstreamBidAdapter.md b/modules/openxoutstreamBidAdapter.md deleted file mode 100644 index 0eebb28463b..00000000000 --- a/modules/openxoutstreamBidAdapter.md +++ /dev/null @@ -1,43 +0,0 @@ -# Overview - -``` -Module Name: OpenX Outstream Bidder Adapter -Module Type: Bidder Adapter -Maintainer: opensource@yieldmo.com, jimmy.tu@openx.com -Note: Ads will only render in mobile -``` - -# Description - -Module that connects to OpenX's demand sources for outstream to Yieldmo. - -This bid adapter supports Banner. - -Note that the only supported size for demand is currently 400 x 300. - -# Example -```javascript -var adUnits = [ - { - code: 'test-div', - mediaTypes: { - 'banner': { - sizes: [[400, 300], // a display size - } - }, - bids: [ - { - bidder: 'openxoutstream', - params: { - unit: '540141567', - delDomain: 'se-demo-d.openx.net', - } - } - ] - } -]; -``` - -# Additional Details -[Banner Ads](https://docs.openx.com/Content/developers/containers/prebid-adapter.html) - diff --git a/test/spec/modules/openxoutstreamBidAdapter_spec.js b/test/spec/modules/openxoutstreamBidAdapter_spec.js deleted file mode 100644 index 9d2b7082a22..00000000000 --- a/test/spec/modules/openxoutstreamBidAdapter_spec.js +++ /dev/null @@ -1,237 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/openxoutstreamBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('OpenXOutstreamAdapter', function () { - const adapter = newBidder(spec); - const URLBASE = '/v/1.0/avjp'; - const BIDDER = 'openxoutstream'; - const div = document.createElement('div'); - const PLACEMENT_ID = '1986307928000988495'; - const YM_SCRIPT = `!function(e,t){if(void 0===t._ym){var a=Math.round(5*Math.random()/3)+'';t._ym='';var m=e.createElement('script');m.type='text/javascript',m.async=!0,m.src='//static.yieldmo.com/ym.'+a+'.js',(e.getElementsByTagName('head')[0]||e.getElementsByTagName('body')[0]).appendChild(m)}else t._ym instanceof String||void 0===t._ym.chkPls||t._ym.chkPls()}(document,window);`; - const PUBLISHER_ID = '1986307525700126029'; - const CR_ID = '2052941939925262540'; - const AD_ID = '1991358644725162800'; - - describe('isBidRequestValid', function () { - describe('when request is for a banner ad', function () { - let bannerBid; - beforeEach(function () { - bannerBid = { - bidder: BIDDER, - params: {}, - adUnitCode: 'adunit-code', - mediaTypes: {banner: {}}, - sizes: [[300, 250], [300, 600]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; - }); - it('should return false when there is no delivery domain', function () { - bannerBid.params = {'unit': '12345678'}; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - - describe('when there is a delivery domain', function () { - beforeEach(function () { - bannerBid.params = {delDomain: 'test-delivery-domain'} - }); - - it('should return false if there is no adunit id and sizes are defined', function () { - bannerBid.mediaTypes.banner.sizes = [720, 90]; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - - it('should return true if there is delivery domain and unit', function () { - bannerBid.params.unit = '12345678'; - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); - }); - it('should return false if there is unit but no delivery domain', function () { - bannerBid.params = {unit: '12345678'}; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - it('shoud return false if there is no delivery domain and no unit', function () { - bannerBid.params = {}; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }) - }); - }); - }); - - describe('buildRequests for banner ads', function () { - const bidRequestsWithMediaType = [{ - 'bidder': BIDDER, - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'mediaType': 'banner', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' - }]; - - const mockBidderRequest = {refererInfo: {}}; - - it('should send bid request to openx url via GET, with mediaType specified as banner', function () { - const request = spec.buildRequests(bidRequestsWithMediaType, mockBidderRequest); - const params = bidRequestsWithMediaType[0].params; - expect(request[0].url).to.equal(`https://` + params.delDomain + URLBASE); - expect(request[0].method).to.equal('GET'); - }); - - it('should send ad unit ids, height, and width when any are defined', function () { - const bidRequestsWithUnitIds = [{ - 'bidder': BIDDER, - 'params': { - 'unit': '540141567', - 'height': '200', - 'width': '250', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - 'bidId': 'test-bid-id-2', - 'bidderRequestId': 'test-bid-request-2', - 'auctionId': 'test-auction-2' - }, { - 'bidder': BIDDER, - 'params': { - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - 'bidId': 'test-bid-id-1', - 'bidderRequestId': 'test-bid-request-1', - 'auctionId': 'test-auction-1' - }]; - const request = spec.buildRequests(bidRequestsWithUnitIds, mockBidderRequest); - expect(request[0].data.auid).to.equal(`${bidRequestsWithUnitIds[0].params.unit}`); - expect(request[0].data.vht).to.not.equal(`${bidRequestsWithUnitIds[0].params.height}`); - expect(request[0].data.vwd).to.not.equal(`${bidRequestsWithUnitIds[0].params.width}`); - expect(request[0].data.vht).to.equal('184'); - expect(request[0].data.vwd).to.equal('414'); - expect(request[0].data.aus).to.equal('304x184%7C412x184%7C375x184%7C414x184'); - }); - - describe('interpretResponse', function () { - let serverResponse; - let serverRequest; - - beforeEach(function () { - serverResponse = { - body: { - width: 300, - height: 250, - pub_rev: 3000, - bidderCode: 'openxoutstream', - vastUrl: 'test.vast.url', - mediaType: 'banner', - adid: '9874652394875' - }, - header: 'header?', - }; - serverRequest = { - payload: { - bid: { - bidId: '2d36ac90d654af', - }, - } - }; - }); - - it('should correctly reorder the server response', function () { - const newResponse = spec.interpretResponse(serverResponse, serverRequest); - const openHtmlTag = ''; - const closeHtmlTag = ''; - const sdkScript = createSdkScript().outerHTML; - const placementDiv = createPlacementDiv(); - placementDiv.dataset.pId = PUBLISHER_ID; - const placementDivString = placementDiv.outerHTML; - const adResponse = getTemplateAdResponse(serverResponse.body.vastUrl, PLACEMENT_ID); - const adResponseString = JSON.stringify(adResponse); - const ymAdsScript = ''; - expect(newResponse.length).to.be.equal(1); - expect(newResponse[0]).to.deep.equal({ - requestId: '2d36ac90d654af', - bidderCode: 'openxoutstream', - vastUrl: 'test.vast.url', - mediaType: 'banner', - cpm: 3, - width: 300, - height: 250, - creativeId: '9874652394875', - currency: 'USD', - netRevenue: true, - ttl: 300, - ad: openHtmlTag + placementDivString + ymAdsScript + sdkScript + closeHtmlTag - }); - }); - - it('should not add responses if the cpm is 0 or null', function () { - serverResponse.body.pub_rev = 0; - let response = spec.interpretResponse(serverResponse, serverRequest); - expect(response).to.deep.equal([]); - - serverResponse.body.pub_rev = null; - response = spec.interpretResponse(serverResponse, serverRequest); - expect(response).to.deep.equal([]) - }); - }); - }) - - function createSdkScript() { - const script = document.createElement('script'); - script.innerHTML = YM_SCRIPT; - return script; - } - function createPlacementDiv() { - div.id = `ym_${PLACEMENT_ID}`; - div.classList.add('ym'); - div.dataset.lfId = CR_ID; - return div - } - const getTemplateAdResponse = (vastUrl) => { - return { - loader: 'openxoutstream', - availability_zone: '', - data: [ - { - ads: [ - { - actions: {}, - adv_id: AD_ID, - configurables: { - cta_button_copy: 'Learn More', - vast_click_tracking: 'true', - vast_url: vastUrl, - }, - cr_id: CR_ID, - } - ], - column_count: 1, - configs: { - allowable_height: '248', - header_copy: 'You May Like', - ping: 'true', - }, - creative_format_id: 40, - css: '', - placement_id: PLACEMENT_ID, - } - ], - nc: 0, - }; - }; -}); From 493ea6648a08b5edfb7a40f736c3fcd516cd5e08 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 1 Nov 2019 13:51:18 -0400 Subject: [PATCH 27/49] fix broken yieldmo test --- test/spec/modules/yieldmoBidAdapter_spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 81c0108ab0d..007bc034e8c 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -80,8 +80,8 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.1}]'); - + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); + // console.log('placementInfo! ', placementInfo); bidArray.push({ bidder: 'yieldmo', params: { @@ -104,7 +104,7 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{sizes":[[300,250],[300,600]]}},"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.2}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); }); it('should add placement id if given', function () { From f66291a5389e82249ac7ffc5daf135c575591e05 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 1 Nov 2019 13:55:08 -0400 Subject: [PATCH 28/49] remove log --- test/spec/modules/yieldmoBidAdapter_spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 007bc034e8c..2594f61f9b4 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -81,7 +81,6 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); - // console.log('placementInfo! ', placementInfo); bidArray.push({ bidder: 'yieldmo', params: { From ba44122f806a1476497af26841ca26180095bff6 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 22 Nov 2019 10:58:56 -0500 Subject: [PATCH 29/49] remove utils functions that will be depricated in 3.0 and use new referer object in bidderRequest --- modules/yieldmoBidAdapter.js | 4 ++-- test/spec/modules/yieldmoBidAdapter_spec.js | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index c0a40616b79..f101521c2e5 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -29,9 +29,9 @@ export const spec = { buildRequests: function(bidRequests, bidderRequest) { let serverRequest = { p: [], - page_url: utils.getTopWindowUrl(), + page_url: bidderRequest.refererInfo.referer, bust: new Date().getTime().toString(), - pr: utils.getTopWindowReferrer(), + pr: bidderRequest.refererInfo.referer, scrd: localWindow.devicePixelRatio || 0, dnt: getDNT(), e: getEnvironment(), diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 2594f61f9b4..b24447e8468 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -39,7 +39,12 @@ describe('YieldmoAdapter', function () { 'auctionStart': 1520001292880, 'timeout': 3000, 'start': 1520001292884, - 'doneCbCallCount': 0 + 'doneCbCallCount': 0, + 'refererInfo': { + 'numIframes': 1, + 'reachedTop': true, + 'referer': 'yieldmo.com' + } } describe('isBidRequestValid', function () { @@ -191,7 +196,7 @@ describe('YieldmoAdapter', function () { it('should add schain if it is in the bidRequest', () => { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; - const request = spec.buildRequests([bidArray[0]]); + const request = spec.buildRequests([bidArray[0]], bidderRequest); expect(request.data.schain).equal(JSON.stringify(schain)); }) }); From e18550404c991931eebb4d8fe121e26678d78726 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Tue, 26 Nov 2019 11:00:42 -0500 Subject: [PATCH 30/49] use prebids gettopwindow util functions. update markdown with 3.0 compliant ad units object --- modules/yieldmoBidAdapter.js | 10 +--------- modules/yieldmoBidAdapter.md | 6 +++++- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index f101521c2e5..6a0bd9654b7 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -7,7 +7,7 @@ const TIME_TO_LIVE = 300; const NET_REVENUE = true; const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; -const localWindow = getTopWindow(); +const localWindow = utils.getWindowTop(); export const spec = { code: BIDDER_CODE, @@ -180,14 +180,6 @@ function getPageDescription() { } } -function getTopWindow() { - try { - return window.top; - } catch (e) { - return window; - } -} - /*************************************** * Detect Environment Helper Functions ***************************************/ diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index d1e34a41ecb..ef5f07a4eb9 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -18,7 +18,11 @@ var adUnits = [ // Banner adUnit { code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300,600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + } bids: [{ bidder: 'yieldmo', params: { From 0072141b2eca1f17a1e217c007ca504bcad963a1 Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Tue, 26 Nov 2019 16:48:57 -0500 Subject: [PATCH 31/49] Pass along us_privacy string --- modules/yieldmoBidAdapter.js | 4 ++-- test/spec/modules/yieldmoBidAdapter_spec.js | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 6a0bd9654b7..ccf565df5da 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -43,7 +43,8 @@ export const spec = { // case of undefined, stringify will remove param gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined - }) + }), + us_privacy: bidderRequest && bidderRequest.us_privacy, }; bidRequests.forEach((request) => { @@ -74,7 +75,6 @@ export const spec = { /** * Makes Yieldmo Ad Server response compatible to Prebid specs * @param serverResponse successful response from Ad Server - * @param bidderRequest original bidRequest * @return {Bid[]} an array of bids */ interpretResponse: function(serverResponse) { diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index b24447e8468..6a4a142975f 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -193,6 +193,13 @@ describe('YieldmoAdapter', function () { })); }); + it('should add ccpa information to request if available', () => { + const privacy = '1YNY'; + bidderRequest.us_privacy = privacy; + const data = spec.buildRequests(bidArray, bidderRequest).data; + expect(data.us_privacy).equal(privacy); + }); + it('should add schain if it is in the bidRequest', () => { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; From b8716557cef0f8d3e7e40b37a70b5cc3ea9b21a9 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Fri, 9 Feb 2018 09:39:45 -0500 Subject: [PATCH 32/49] update maintainer email --- modules/yieldmoBidAdapter.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index ef5f07a4eb9..3c1aa09829b 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -4,6 +4,10 @@ Module Name: Yieldmo Bid Adapter Module Type: Bidder Adapter Maintainer: opensource@yieldmo.com +<<<<<<< HEAD +======= +Note: Our ads will only render in mobile +>>>>>>> 889e5f0f... update maintainer email ``` # Description From 828a404e8eec397d8e6cc97e0afaea456a5513e9 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:05:08 -0400 Subject: [PATCH 33/49] add stringified schain --- modules/yieldmoBidAdapter.js | 6 + test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++---------- test/spec/modules/yieldmoBidAdapter_spec.js | 7 + 3 files changed, 134 insertions(+), 121 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index ccf565df5da..3320765cc98 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -26,7 +26,13 @@ export const spec = { * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. * @return ServerRequest Info describing the request to the server. */ +<<<<<<< HEAD buildRequests: function(bidRequests, bidderRequest) { +======= + buildRequests: function(bidRequests) { + console.log('bid requests'); + console.log(bidRequests); +>>>>>>> 4fd8634f... add stringified schain let serverRequest = { p: [], page_url: bidderRequest.refererInfo.referer, diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 2e992d3298c..cdded54e307 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; - - beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); - }); - - afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); - }); - - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; - - adapter.track({ eventType, args }); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); - }); - - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); - }); + let xhr; + let requests; + let adapter; - describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); }); afterEach(function () { - events.getEvents.restore(); + xhr.restore(); + adapter.disableAnalytics(); }); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; - adapter.enableAnalytics(); - events.emit(eventType, args); + adapter.track({ eventType, args }); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; - adapter.enableAnalytics(); events.emit(eventType, args); + adapter.enableAnalytics(); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + describe(`WHEN an event occurs after enable analytics\n`, function () { + beforeEach(function () { + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + afterEach(function () { + events.getEvents.restore(); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); - }); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); - }); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - expect(requests.length).to.equal(1); - }); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); - afterEach(function () { - Math.random.restore(); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); events.emit(eventType, args); expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; + + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); + }); + + afterEach(function () { + Math.random.restore(); + }); + + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - events.emit(eventType, args); - expect(requests.length).to.equal(0); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(0); + }); }); }); }); -}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 6a4a142975f..62d1bee1f89 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -180,6 +180,7 @@ describe('YieldmoAdapter', function () { expect(data.tdid).to.deep.equal(tdid); }); +<<<<<<< HEAD it('should add gdpr information to request if available', () => { bidderRequest.gdprConsent = { 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', @@ -204,6 +205,12 @@ describe('YieldmoAdapter', function () { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; const request = spec.buildRequests([bidArray[0]], bidderRequest); +======= + it('should add schain if it is in the bidRequest', () => { + const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; + bidArray[0].schain = schain; + const request = spec.buildRequests([bidArray[0]]); +>>>>>>> 4fd8634f... add stringified schain expect(request.data.schain).equal(JSON.stringify(schain)); }) }); From 34b7b872e85f98c718b2eae8a9e3eea8b1eff8b9 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:08:46 -0400 Subject: [PATCH 34/49] Revert "add stringified schain" This reverts commit 4fd8634f12133945ac44e9b550237321e71fc549. --- modules/yieldmoBidAdapter.js | 7 - test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++---------- test/spec/modules/yieldmoBidAdapter_spec.js | 9 +- 3 files changed, 122 insertions(+), 136 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 3320765cc98..eaedd7cabba 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -26,13 +26,9 @@ export const spec = { * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. * @return ServerRequest Info describing the request to the server. */ -<<<<<<< HEAD buildRequests: function(bidRequests, bidderRequest) { -======= - buildRequests: function(bidRequests) { console.log('bid requests'); console.log(bidRequests); ->>>>>>> 4fd8634f... add stringified schain let serverRequest = { p: [], page_url: bidderRequest.refererInfo.referer, @@ -67,9 +63,6 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } - if (request.schain) { - serverRequest.schain = JSON.stringify(request.schain); - } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index cdded54e307..2e992d3298c 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; + let xhr; + let requests; + let adapter; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); + }); + + afterEach(function () { + xhr.restore(); + adapter.disableAnalytics(); + }); + + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; + + adapter.track({ eventType, args }); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + }); + + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + }); + describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); + events.getEvents.restore(); }); - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - adapter.track({ eventType, args }); + adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - events.emit(eventType, args); adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); - describe(`WHEN an event occurs after enable analytics\n`, function () { - beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - afterEach(function () { - events.getEvents.restore(); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + events.emit(eventType, args); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + expect(requests.length).to.equal(1); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); }); - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - adapter.enableAnalytics(); - events.emit(eventType, args); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + afterEach(function () { + Math.random.restore(); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); events.emit(eventType, args); expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; - - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); - }); - - afterEach(function () { - Math.random.restore(); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } }); + events.emit(eventType, args); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); - - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(0); - }); + expect(requests.length).to.equal(0); }); }); }); +}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 62d1bee1f89..532652fbdd0 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -179,8 +179,7 @@ describe('YieldmoAdapter', function () { const data = spec.buildRequests([unifiedIdBid], bidderRequest).data; expect(data.tdid).to.deep.equal(tdid); }); - -<<<<<<< HEAD + it('should add gdpr information to request if available', () => { bidderRequest.gdprConsent = { 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', @@ -205,12 +204,6 @@ describe('YieldmoAdapter', function () { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; bidArray[0].schain = schain; const request = spec.buildRequests([bidArray[0]], bidderRequest); -======= - it('should add schain if it is in the bidRequest', () => { - const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; - bidArray[0].schain = schain; - const request = spec.buildRequests([bidArray[0]]); ->>>>>>> 4fd8634f... add stringified schain expect(request.data.schain).equal(JSON.stringify(schain)); }) }); From af9fa8cc068a94e0401f3434281b2342dd86ac12 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 15:05:08 -0400 Subject: [PATCH 35/49] add stringified schain --- modules/yieldmoBidAdapter.js | 3 + test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++++++--------------- 2 files changed, 124 insertions(+), 121 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index eaedd7cabba..103cb03f92f 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -63,6 +63,9 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } + if (request.schain) { + serverRequest.schain = JSON.stringify(request.schain); + } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 2e992d3298c..cdded54e307 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; - - beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); - }); - - afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); - }); - - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; - - adapter.track({ eventType, args }); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); - }); - - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); - }); + let xhr; + let requests; + let adapter; - describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); }); afterEach(function () { - events.getEvents.restore(); + xhr.restore(); + adapter.disableAnalytics(); }); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; - adapter.enableAnalytics(); - events.emit(eventType, args); + adapter.track({ eventType, args }); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; - adapter.enableAnalytics(); events.emit(eventType, args); + adapter.enableAnalytics(); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + describe(`WHEN an event occurs after enable analytics\n`, function () { + beforeEach(function () { + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + afterEach(function () { + events.getEvents.restore(); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); - }); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); - }); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - expect(requests.length).to.equal(1); - }); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; + adapter.enableAnalytics(); + events.emit(eventType, args); - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); - afterEach(function () { - Math.random.restore(); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); events.emit(eventType, args); expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; + + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); + }); + + afterEach(function () { + Math.random.restore(); + }); + + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - events.emit(eventType, args); - expect(requests.length).to.equal(0); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } + }); + events.emit(eventType, args); + + expect(requests.length).to.equal(0); + }); }); }); }); -}); From 94fc46ab5f61d4e03322db9e0308d372ca0f696b Mon Sep 17 00:00:00 2001 From: Melody Li Date: Tue, 15 Oct 2019 17:33:15 -0400 Subject: [PATCH 36/49] don't change other files --- test/spec/AnalyticsAdapter_spec.js | 242 ++++++++++++++--------------- 1 file changed, 121 insertions(+), 121 deletions(-) diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index cdded54e307..2e992d3298c 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -20,175 +20,175 @@ describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - let xhr; - let requests; - let adapter; + let xhr; + let requests; + let adapter; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); + }); + + afterEach(function () { + xhr.restore(); + adapter.disableAnalytics(); + }); + + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; + + adapter.track({ eventType, args }); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + }); + + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; + + events.emit(eventType, args); + adapter.enableAnalytics(); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + }); + describe(`WHEN an event occurs after enable analytics\n`, function () { beforeEach(function () { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = (request) => requests.push(request); - adapter = new AnalyticsAdapter(config); + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); afterEach(function () { - xhr.restore(); - adapter.disableAnalytics(); + events.getEvents.restore(); }); - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; + it('SHOULD call global when a bidWon event occurs', function () { + const eventType = BID_WON; + const args = { more: 'info' }; - adapter.track({ eventType, args }); + adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; + it('SHOULD call global when a adRenderFailed event occurs', function () { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; - events.emit(eventType, args); adapter.enableAnalytics(); + events.emit(eventType, args); let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); - describe(`WHEN an event occurs after enable analytics\n`, function () { - beforeEach(function () { - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests - }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; - afterEach(function () { - events.getEvents.restore(); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidWon event occurs', function () { - const eventType = BID_WON; - const args = { more: 'info' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a adRenderFailed event occurs', function () { - const eventType = AD_RENDER_FAILED; - const args = { call: 'adRenderFailed' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidRequest event occurs', function () { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when an addAdUnits event occurs', function () { - const eventType = ADD_AD_UNITS; - const args = { call: 'addAdUnits' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidResponse event occurs', function () { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a requestBids event occurs', function () { - const eventType = REQUEST_BIDS; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidTimeout event occurs', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidRequest event occurs', function () { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); - }); + events.emit(eventType, args); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidResponse event occurs', function () { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + expect(requests.length).to.equal(1); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + describe(`AND sampling is enabled\n`, function () { + const eventType = BID_WON; + const args = { more: 'info' }; - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); + beforeEach(function () { + sinon.stub(Math, 'random').returns(0.5); }); - it('SHOULD call global when a bidTimeout event occurs', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - adapter.enableAnalytics(); - events.emit(eventType, args); - - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); + afterEach(function () { + Math.random.restore(); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); + it(`THEN should enable analytics when random number is in sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } + }); events.emit(eventType, args); expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - describe(`AND sampling is enabled\n`, function () { - const eventType = BID_WON; - const args = { more: 'info' }; - - beforeEach(function () { - sinon.stub(Math, 'random').returns(0.5); - }); - - afterEach(function () { - Math.random.restore(); + it(`THEN should disable analytics when random number is outside sample range`, function () { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } }); + events.emit(eventType, args); - it(`THEN should enable analytics when random number is in sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(1); - let result = JSON.parse(requests[0].requestBody); - expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); - }); - - it(`THEN should disable analytics when random number is outside sample range`, function () { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } - }); - events.emit(eventType, args); - - expect(requests.length).to.equal(0); - }); + expect(requests.length).to.equal(0); }); }); }); +}); From b221b6859d14db456af9677394abb43c27e9d0a8 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Mon, 21 Oct 2019 17:37:12 -0400 Subject: [PATCH 37/49] change parameter namves --- modules/yieldmoBidAdapter.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 103cb03f92f..b00645dd991 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -45,8 +45,12 @@ export const spec = { // case of undefined, stringify will remove param gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined +<<<<<<< HEAD }), us_privacy: bidderRequest && bidderRequest.us_privacy, +======= + }) +>>>>>>> 17108a40... change parameter namves }; bidRequests.forEach((request) => { From 76aed8a1952093ef857a8aa308b5fa90af2989d4 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 25 Oct 2019 11:20:43 -0400 Subject: [PATCH 38/49] updates bidder module to be 3.0 compliant, and tests --- test/spec/modules/yieldmoBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 532652fbdd0..71b50f90536 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -108,7 +108,7 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{sizes":[[300,250],[300,600]]}},"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.2}]'); }); it('should add placement id if given', function () { From 9c115244574b0ce14d7e6069e5a15fb22ec3bf36 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 1 Nov 2019 13:51:18 -0400 Subject: [PATCH 39/49] fix broken yieldmo test --- test/spec/modules/yieldmoBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 71b50f90536..532652fbdd0 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -108,7 +108,7 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","mediaTypes":{"banner":{sizes":[[300,250],[300,600]]}},"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","mediaTypes":{"banner":{"sizes":[[300,250],[300,600]]}},"bidFloor":0.2}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); }); it('should add placement id if given', function () { From 6911ad8d51996f1dfc6e1b877624f516da537342 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Fri, 22 Nov 2019 10:58:56 -0500 Subject: [PATCH 40/49] remove utils functions that will be depricated in 3.0 and use new referer object in bidderRequest From 797b0400228ff06ffbf8788c0e6dbeb382a11870 Mon Sep 17 00:00:00 2001 From: Andrew Holz Date: Tue, 26 Nov 2019 11:00:42 -0500 Subject: [PATCH 41/49] use prebids gettopwindow util functions. update markdown with 3.0 compliant ad units object From d257f97d6b636ddf9f697b02501d58ba3c25c511 Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Thu, 19 Dec 2019 22:24:08 -0500 Subject: [PATCH 42/49] Pass along us_privacy string --- modules/yieldmoBidAdapter.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index b00645dd991..103cb03f92f 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -45,12 +45,8 @@ export const spec = { // case of undefined, stringify will remove param gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined -<<<<<<< HEAD }), us_privacy: bidderRequest && bidderRequest.us_privacy, -======= - }) ->>>>>>> 17108a40... change parameter namves }; bidRequests.forEach((request) => { From b212e387fbf8f877156b9f2a2ec11d885abdd00d Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Mon, 23 Dec 2019 13:21:35 -0500 Subject: [PATCH 43/49] Clean up console --- modules/yieldmoBidAdapter.js | 2 -- modules/yieldmoBidAdapter.md | 3 --- 2 files changed, 5 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 103cb03f92f..ccf565df5da 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -27,8 +27,6 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(bidRequests, bidderRequest) { - console.log('bid requests'); - console.log(bidRequests); let serverRequest = { p: [], page_url: bidderRequest.refererInfo.referer, diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index 3c1aa09829b..0f86d2507d1 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -4,10 +4,7 @@ Module Name: Yieldmo Bid Adapter Module Type: Bidder Adapter Maintainer: opensource@yieldmo.com -<<<<<<< HEAD -======= Note: Our ads will only render in mobile ->>>>>>> 889e5f0f... update maintainer email ``` # Description From 0185407646a6ba15a9d99ab19cc1ea0f3b6bdadd Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Mon, 23 Dec 2019 13:35:40 -0500 Subject: [PATCH 44/49] Do not undo my featureeee --- modules/yieldmoBidAdapter.js | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index ccf565df5da..0531c7d695f 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -5,7 +5,6 @@ const BIDDER_CODE = 'yieldmo'; const CURRENCY = 'USD'; const TIME_TO_LIVE = 300; const NET_REVENUE = true; -const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; const localWindow = utils.getWindowTop(); @@ -89,15 +88,8 @@ export const spec = { } return bids; }, - getUserSync: function(syncOptions) { - if (trackingEnabled(syncOptions)) { - return [{ - type: 'iframe', - url: SYNC_ENDPOINT + utils.getOrigin() - }]; - } else { - return []; - } + getUserSyncs: function(syncOptions) { + return []; } } registerBidder(spec); @@ -145,22 +137,6 @@ function createNewBid(response) { }; } -/** - * Detects if tracking is allowed - * @returns false if dnt or if not iframe/pixel enabled - */ -function trackingEnabled(options) { - return (isIOS() && !getDNT() && options.iframeEnabled); -} - -/** - * Detects whether we're in iOS - * @returns true if in iOS - */ -function isIOS() { - return /iPhone|iPad|iPod/i.test(window.navigator.userAgent); -} - /** * Detects whether dnt is true * @returns true if user enabled dnt From 09301d13a8b246f6dcb2e182473acece0411e36f Mon Sep 17 00:00:00 2001 From: Michal Date: Tue, 31 Mar 2020 11:54:51 -0400 Subject: [PATCH 45/49] CRITEO RTUS For prebid --- modules/yieldmoBidAdapter.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index c8347cceae0..53929196ab2 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -60,6 +60,10 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } + const criteoId = getId(request, 'criteoId'); + if (criteoId) { + serverRequest.cri_prebid = criteoId; + } if (request.schain) { serverRequest.schain = JSON.stringify(request.schain); } From dfd8c586c126e201c177ea14e7ce4cf607921923 Mon Sep 17 00:00:00 2001 From: Michal Date: Tue, 31 Mar 2020 12:22:28 -0400 Subject: [PATCH 46/49] Tests for CRITEO RTUS For prebid --- test/spec/modules/yieldmoBidAdapter_spec.js | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 7c5159add6c..00229fe7196 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -8,6 +8,7 @@ describe('YieldmoAdapter', function () { const ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; let tdid = '8d146286-91d4-4958-aff4-7e489dd1abd6'; + let criteoId = 'aff4'; let bid = { bidder: 'yieldmo', @@ -180,6 +181,27 @@ describe('YieldmoAdapter', function () { expect(data.tdid).to.deep.equal(tdid); }); + it('should add CRITEO RTUS id as parameter of request', function () { + const criteoIdBid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: { + criteoId + } + }; + const data = spec.buildRequests([criteoIdBid], bidderRequest).data; + expect(data.cri_prebid).to.deep.equal(criteoId); + }); + it('should add gdpr information to request if available', () => { bidderRequest.gdprConsent = { 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', From 4fa7cef5af24dce8f7032effbad145f9721e7fe0 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Fri, 3 Apr 2020 11:13:54 -0400 Subject: [PATCH 47/49] Revert "Do not undo my featureeee" This reverts commit 0185407646a6ba15a9d99ab19cc1ea0f3b6bdadd. --- modules/yieldmoBidAdapter.js | 154 +++++++++++++++++++++++------------ 1 file changed, 101 insertions(+), 53 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 53929196ab2..6f3a24d6896 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -1,21 +1,22 @@ -import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; +import * as utils from "../src/utils"; +import { registerBidder } from "../src/adapters/bidderFactory"; -const BIDDER_CODE = 'yieldmo'; -const CURRENCY = 'USD'; +const BIDDER_CODE = "yieldmo"; +const CURRENCY = "USD"; const TIME_TO_LIVE = 300; const NET_REVENUE = true; -const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; +const SYNC_ENDPOINT = "https://static.yieldmo.com/blank.min.html?orig="; +const SERVER_ENDPOINT = "https://ads.yieldmo.com/exchange/prebid"; const localWindow = utils.getWindowTop(); export const spec = { code: BIDDER_CODE, - supportedMediaTypes: ['banner'], + supportedMediaTypes: ["banner"], /** - * Determines whether or not the given bid request is valid. - * @param {object} bid, bid to validate - * @return boolean, true if valid, otherwise false - */ + * Determines whether or not the given bid request is valid. + * @param {object} bid, bid to validate + * @return boolean, true if valid, otherwise false + */ isBidRequestValid: function(bid) { return !!(bid && bid.adUnitCode && bid.bidId); }, @@ -35,20 +36,26 @@ export const spec = { dnt: getDNT(), e: getEnvironment(), description: getPageDescription(), - title: localWindow.document.title || '', + title: localWindow.document.title || "", w: localWindow.innerWidth, h: localWindow.innerHeight, userConsent: JSON.stringify({ // case of undefined, stringify will remove param - gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, - cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined + gdprApplies: + bidderRequest && bidderRequest.gdprConsent + ? bidderRequest.gdprConsent.gdprApplies + : undefined, + cmp: + bidderRequest && bidderRequest.gdprConsent + ? bidderRequest.gdprConsent.consentString + : undefined }), - us_privacy: bidderRequest && bidderRequest.us_privacy, + us_privacy: bidderRequest && bidderRequest.us_privacy }; - bidRequests.forEach((request) => { + bidRequests.forEach(request => { serverRequest.p.push(addPlacement(request)); - const pubcid = getId(request, 'pubcid'); + const pubcid = getId(request, "pubcid"); if (pubcid) { serverRequest.pubcid = pubcid; } else if (request.crumbs) { @@ -56,11 +63,11 @@ export const spec = { serverRequest.pubcid = request.crumbs.pubcid; } } - const tdid = getId(request, 'tdid'); + const tdid = getId(request, "tdid"); if (tdid) { serverRequest.tdid = tdid; } - const criteoId = getId(request, 'criteoId'); + const criteoId = getId(request, "criteoId"); if (criteoId) { serverRequest.cri_prebid = criteoId; } @@ -68,12 +75,12 @@ export const spec = { serverRequest.schain = JSON.stringify(request.schain); } }); - serverRequest.p = '[' + serverRequest.p.toString() + ']'; + serverRequest.p = "[" + serverRequest.p.toString() + "]"; return { - method: 'GET', + method: "GET", url: SERVER_ENDPOINT, data: serverRequest - } + }; }, /** * Makes Yieldmo Ad Server response compatible to Prebid specs @@ -84,7 +91,7 @@ export const spec = { let bids = []; let data = serverResponse.body; if (data.length > 0) { - data.forEach((response) => { + data.forEach(response => { if (response.cpm && response.cpm > 0) { bids.push(createNewBid(response)); } @@ -92,10 +99,19 @@ export const spec = { } return bids; }, - getUserSyncs: function(syncOptions) { - return []; + getUserSync: function(syncOptions) { + if (trackingEnabled(syncOptions)) { + return [ + { + type: "iframe", + url: SYNC_ENDPOINT + utils.getOrigin() + } + ]; + } else { + return []; + } } -} +}; registerBidder(spec); /*************************************** @@ -111,7 +127,7 @@ function addPlacement(request) { placement_id: request.adUnitCode, callback_id: request.bidId, sizes: request.mediaTypes.banner.sizes - } + }; if (request.params) { if (request.params.placementId) { placementInfo.ym_placement_id = request.params.placementId; @@ -124,12 +140,12 @@ function addPlacement(request) { } /** - * creates a new bid with response information - * @param response server response - */ + * creates a new bid with response information + * @param response server response + */ function createNewBid(response) { return { - requestId: response['callback_id'], + requestId: response["callback_id"], cpm: response.cpm, width: response.width, height: response.height, @@ -142,11 +158,29 @@ function createNewBid(response) { } /** - * Detects whether dnt is true - * @returns true if user enabled dnt - */ + * Detects if tracking is allowed + * @returns false if dnt or if not iframe/pixel enabled + */ +function trackingEnabled(options) { + return isIOS() && !getDNT() && options.iframeEnabled; +} + +/** + * Detects whether we're in iOS + * @returns true if in iOS + */ +function isIOS() { + return /iPhone|iPad|iPod/i.test(window.navigator.userAgent); +} + +/** + * Detects whether dnt is true + * @returns true if user enabled dnt + */ function getDNT() { - return window.doNotTrack === '1' || window.navigator.doNotTrack === '1' || false; + return ( + window.doNotTrack === "1" || window.navigator.doNotTrack === "1" || false + ); } /** @@ -154,9 +188,11 @@ function getDNT() { */ function getPageDescription() { if (document.querySelector('meta[name="description"]')) { - return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. + return document + .querySelector('meta[name="description"]') + .getAttribute("content"); // Value of the description metadata from the publisher's page. } else { - return ''; + return ""; } } @@ -180,9 +216,9 @@ function getPageDescription() { */ /** - * Detects what environment we're in - * @returns Environment kind - */ + * Detects what environment we're in + * @returns Environment kind + */ function getEnvironment() { if (isSuperSandboxedIframe()) { return 89; @@ -208,28 +244,31 @@ function getEnvironment() { } /** - * @returns true if we are running on the top window at dispatch time - */ + * @returns true if we are running on the top window at dispatch time + */ function isCodeOnPage() { return window === window.parent; } /** - * @returns true if the environment is both DFP and AMP - */ + * @returns true if the environment is both DFP and AMP + */ function isDfpInAmp() { return isDfp() && isAmp(); } /** - * @returns true if the window is in an iframe whose id and parent element id match DFP - */ + * @returns true if the window is in an iframe whose id and parent element id match DFP + */ function isDfp() { try { const frameElement = window.frameElement; const parentElement = window.frameElement.parentNode; if (frameElement && parentElement) { - return frameElement.id.indexOf('google_ads_iframe') > -1 && parentElement.id.indexOf('google_ads_iframe') > -1; + return ( + frameElement.id.indexOf("google_ads_iframe") > -1 && + parentElement.id.indexOf("google_ads_iframe") > -1 + ); } return false; } catch (e) { @@ -238,8 +277,8 @@ function isDfp() { } /** -* @returns true if there is an AMP context object -*/ + * @returns true if there is an AMP context object + */ function isAmp() { try { const ampContext = window.context || window.parent.context; @@ -265,7 +304,11 @@ function isSafeFrame() { function isDFPSafeFrame() { if (window.location && window.location.href) { const href = window.location.href; - return isSafeFrame() && href.indexOf('google') !== -1 && href.indexOf('safeframe') !== -1; + return ( + isSafeFrame() && + href.indexOf("google") !== -1 && + href.indexOf("safeframe") !== -1 + ); } return false; } @@ -281,9 +324,9 @@ function isSandboxedIframe() { * Return true if we cannot document.write to a child iframe (this implies no allow-same-origin) */ function isSuperSandboxedIframe() { - const sacrificialIframe = window.document.createElement('iframe'); + const sacrificialIframe = window.document.createElement("iframe"); try { - sacrificialIframe.setAttribute('style', 'display:none'); + sacrificialIframe.setAttribute("style", "display:none"); window.document.body.appendChild(sacrificialIframe); sacrificialIframe.contentWindow._testVar = true; window.document.body.removeChild(sacrificialIframe); @@ -298,7 +341,7 @@ function isSuperSandboxedIframe() { * @returns true if the window has the attribute identifying MRAID */ function isMraid() { - return !!(window.mraid); + return !!window.mraid; } /** @@ -309,7 +352,12 @@ function isMraid() { */ function getId(request, idType) { let id; - if (request && request.userId && request.userId[idType] && typeof request.userId === 'object') { + if ( + request && + request.userId && + request.userId[idType] && + typeof request.userId === "object" + ) { id = request.userId[idType]; } return id; From 28c143b6f86d4c9884f5590fc714ad6446d960e5 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Fri, 3 Apr 2020 12:19:39 -0400 Subject: [PATCH 48/49] linting --- modules/yieldmoBidAdapter.js | 50 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 6f3a24d6896..94136839e74 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -1,17 +1,17 @@ -import * as utils from "../src/utils"; -import { registerBidder } from "../src/adapters/bidderFactory"; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; -const BIDDER_CODE = "yieldmo"; -const CURRENCY = "USD"; +const BIDDER_CODE = 'yieldmo'; +const CURRENCY = 'USD'; const TIME_TO_LIVE = 300; const NET_REVENUE = true; -const SYNC_ENDPOINT = "https://static.yieldmo.com/blank.min.html?orig="; -const SERVER_ENDPOINT = "https://ads.yieldmo.com/exchange/prebid"; +const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; +const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; const localWindow = utils.getWindowTop(); export const spec = { code: BIDDER_CODE, - supportedMediaTypes: ["banner"], + supportedMediaTypes: ['banner'], /** * Determines whether or not the given bid request is valid. * @param {object} bid, bid to validate @@ -36,7 +36,7 @@ export const spec = { dnt: getDNT(), e: getEnvironment(), description: getPageDescription(), - title: localWindow.document.title || "", + title: localWindow.document.title || '', w: localWindow.innerWidth, h: localWindow.innerHeight, userConsent: JSON.stringify({ @@ -55,7 +55,7 @@ export const spec = { bidRequests.forEach(request => { serverRequest.p.push(addPlacement(request)); - const pubcid = getId(request, "pubcid"); + const pubcid = getId(request, 'pubcid'); if (pubcid) { serverRequest.pubcid = pubcid; } else if (request.crumbs) { @@ -63,11 +63,11 @@ export const spec = { serverRequest.pubcid = request.crumbs.pubcid; } } - const tdid = getId(request, "tdid"); + const tdid = getId(request, 'tdid'); if (tdid) { serverRequest.tdid = tdid; } - const criteoId = getId(request, "criteoId"); + const criteoId = getId(request, 'criteoId'); if (criteoId) { serverRequest.cri_prebid = criteoId; } @@ -75,9 +75,9 @@ export const spec = { serverRequest.schain = JSON.stringify(request.schain); } }); - serverRequest.p = "[" + serverRequest.p.toString() + "]"; + serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { - method: "GET", + method: 'GET', url: SERVER_ENDPOINT, data: serverRequest }; @@ -103,7 +103,7 @@ export const spec = { if (trackingEnabled(syncOptions)) { return [ { - type: "iframe", + type: 'iframe', url: SYNC_ENDPOINT + utils.getOrigin() } ]; @@ -145,7 +145,7 @@ function addPlacement(request) { */ function createNewBid(response) { return { - requestId: response["callback_id"], + requestId: response['callback_id'], cpm: response.cpm, width: response.width, height: response.height, @@ -179,7 +179,7 @@ function isIOS() { */ function getDNT() { return ( - window.doNotTrack === "1" || window.navigator.doNotTrack === "1" || false + window.doNotTrack === '1' || window.navigator.doNotTrack === '1' || false ); } @@ -190,9 +190,9 @@ function getPageDescription() { if (document.querySelector('meta[name="description"]')) { return document .querySelector('meta[name="description"]') - .getAttribute("content"); // Value of the description metadata from the publisher's page. + .getAttribute('content'); // Value of the description metadata from the publisher's page. } else { - return ""; + return ''; } } @@ -266,8 +266,8 @@ function isDfp() { const parentElement = window.frameElement.parentNode; if (frameElement && parentElement) { return ( - frameElement.id.indexOf("google_ads_iframe") > -1 && - parentElement.id.indexOf("google_ads_iframe") > -1 + frameElement.id.indexOf('google_ads_iframe') > -1 && + parentElement.id.indexOf('google_ads_iframe') > -1 ); } return false; @@ -306,8 +306,8 @@ function isDFPSafeFrame() { const href = window.location.href; return ( isSafeFrame() && - href.indexOf("google") !== -1 && - href.indexOf("safeframe") !== -1 + href.indexOf('google') !== -1 && + href.indexOf('safeframe') !== -1 ); } return false; @@ -324,9 +324,9 @@ function isSandboxedIframe() { * Return true if we cannot document.write to a child iframe (this implies no allow-same-origin) */ function isSuperSandboxedIframe() { - const sacrificialIframe = window.document.createElement("iframe"); + const sacrificialIframe = window.document.createElement('iframe'); try { - sacrificialIframe.setAttribute("style", "display:none"); + sacrificialIframe.setAttribute('style', 'display:none'); window.document.body.appendChild(sacrificialIframe); sacrificialIframe.contentWindow._testVar = true; window.document.body.removeChild(sacrificialIframe); @@ -356,7 +356,7 @@ function getId(request, idType) { request && request.userId && request.userId[idType] && - typeof request.userId === "object" + typeof request.userId === 'object' ) { id = request.userId[idType]; } From 3bf64e02f8b9a01d9e6ee0b510c63fc6c7c8e0d6 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Fri, 3 Apr 2020 13:33:17 -0400 Subject: [PATCH 49/49] add test back in: --- test/spec/modules/yieldmoBidAdapter_spec.js | 187 +++++++++++++------- 1 file changed, 119 insertions(+), 68 deletions(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 00229fe7196..4e962e7a2af 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -13,40 +13,43 @@ describe('YieldmoAdapter', function () { let bid = { bidder: 'yieldmo', params: { - bidFloor: 0.1 + bidFloor: 0.1, }, adUnitCode: 'adunit-code', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', crumbs: { - pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da', }, userId: { tdid, - } + }, }; let bidArray = [bid]; let bidderRequest = { - 'bidderCode': 'yieldmo', - 'auctionId': 'e3a336ad-2761-4a1c-b421-ecc7c5294a34', - 'bidderRequestId': '14c4ede8c693f', - 'bids': bidArray, - 'auctionStart': 1520001292880, - 'timeout': 3000, - 'start': 1520001292884, - 'doneCbCallCount': 0, - 'refererInfo': { - 'numIframes': 1, - 'reachedTop': true, - 'referer': 'yieldmo.com' - } - } + bidderCode: 'yieldmo', + auctionId: 'e3a336ad-2761-4a1c-b421-ecc7c5294a34', + bidderRequestId: '14c4ede8c693f', + bids: bidArray, + auctionStart: 1520001292880, + timeout: 3000, + start: 1520001292884, + doneCbCallCount: 0, + refererInfo: { + numIframes: 1, + reachedTop: true, + referer: 'yieldmo.com', + }, + }; describe('isBidRequestValid', function () { it('should return true when necessary information is found', function () { @@ -78,38 +81,44 @@ describe('YieldmoAdapter', function () { }); it('should not blow up if crumbs is undefined', function () { - let bidArray = [ - { ...bid, crumbs: undefined } - ] - expect(function () { spec.buildRequests(bidArray, bidderRequest) }).not.to.throw() - }) + let bidArray = [{ ...bid, crumbs: undefined }]; + expect(function () { + spec.buildRequests(bidArray, bidderRequest); + }).not.to.throw(); + }); it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); + expect(placementInfo).to.equal( + '[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]' + ); bidArray.push({ bidder: 'yieldmo', params: { - bidFloor: 0.2 + bidFloor: 0.2, }, adUnitCode: 'adunit-code-1', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '123456789', bidderRequestId: '987654321', auctionId: '0246810', crumbs: { - pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' - } - + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da', + }, }); // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); + expect(placementInfo).to.equal( + '[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]' + ); }); it('should add placement id if given', function () { @@ -146,18 +155,23 @@ describe('YieldmoAdapter', function () { adUnitCode: 'adunit-code', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: { - pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' - } + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2', + }, }; const data = spec.buildRequests([pubcidBid], bidderRequest).data; - expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); + expect(data.pubcid).to.deep.equal( + 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' + ); }); it('should add unified id as parameter of request', function () { @@ -167,15 +181,18 @@ describe('YieldmoAdapter', function () { adUnitCode: 'adunit-code', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: { tdid, - } + }, }; const data = spec.buildRequests([unifiedIdBid], bidderRequest).data; expect(data.tdid).to.deep.equal(tdid); @@ -188,15 +205,18 @@ describe('YieldmoAdapter', function () { adUnitCode: 'adunit-code', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: { - criteoId - } + criteoId, + }, }; const data = spec.buildRequests([criteoIdBid], bidderRequest).data; expect(data.cri_prebid).to.deep.equal(criteoId); @@ -204,15 +224,17 @@ describe('YieldmoAdapter', function () { it('should add gdpr information to request if available', () => { bidderRequest.gdprConsent = { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'vendorData': {'blerp': 1}, - 'gdprApplies': true - } + consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + vendorData: { blerp: 1 }, + gdprApplies: true, + }; const data = spec.buildRequests(bidArray, bidderRequest).data; - expect(data.userConsent).equal(JSON.stringify({ - 'gdprApplies': true, - 'cmp': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' - })); + expect(data.userConsent).equal( + JSON.stringify({ + gdprApplies: true, + cmp: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + }) + ); }); it('should add ccpa information to request if available', () => { @@ -223,11 +245,15 @@ describe('YieldmoAdapter', function () { }); it('should add schain if it is in the bidRequest', () => { - const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; + const schain = { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + }; bidArray[0].schain = schain; const request = spec.buildRequests([bidArray[0]], bidderRequest); expect(request.data.schain).equal(JSON.stringify(schain)); - }) + }); }); describe('interpretResponse', function () { @@ -235,17 +261,20 @@ describe('YieldmoAdapter', function () { beforeEach(function () { serverResponse = { - body: [{ - callback_id: '21989fdbef550a', - cpm: 3.45455, - width: 300, - height: 250, - ad: '
', - creative_id: '9874652394875' - }], - header: 'header?' + body: [ + { + callback_id: '21989fdbef550a', + cpm: 3.45455, + width: 300, + height: 250, + ad: + '
', + creative_id: '9874652394875', + }, + ], + header: 'header?', }; - }) + }); it('should correctly reorder the server response', function () { const newResponse = spec.interpretResponse(serverResponse); @@ -259,7 +288,8 @@ describe('YieldmoAdapter', function () { currency: 'USD', netRevenue: true, ttl: 300, - ad: '
' + ad: + '
', }); }); @@ -270,11 +300,32 @@ describe('YieldmoAdapter', function () { serverResponse.body[0].cpm = null; response = spec.interpretResponse(serverResponse); - expect(response).to.deep.equal([]) + expect(response).to.deep.equal([]); }); }); - describe('getUserSyncs', function () { - expect(spec.getUserSyncs({})).to.deep.equal([]); + describe('getUserSync', function () { + const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; + let options = { + iframeEnabled: true, + pixelEnabled: true, + }; + + it('should return a tracker with type and url as parameters', function () { + if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) { + expect(spec.getUserSync(options)).to.deep.equal([ + { + type: 'iframe', + url: SYNC_ENDPOINT + utils.getOrigin(), + }, + ]); + + options.iframeEnabled = false; + expect(spec.getUserSync(options)).to.deep.equal([]); + } else { + // not ios, so tracker will fail + expect(spec.getUserSync(options)).to.deep.equal([]); + } + }); }); });