From a6dd6858cb8bb07eae1e8004d778dba6eac99b3a Mon Sep 17 00:00:00 2001 From: Patryk Grzegorczyk Date: Mon, 29 Sep 2025 17:15:17 +0200 Subject: [PATCH 1/7] [ADO-981] Adocean adapter --- modules/adoceanBidAdapter.js | 211 +++++++++++++++++++++++++++++++++++ modules/adoceanBidAdapter.md | 30 +++++ 2 files changed, 241 insertions(+) create mode 100644 modules/adoceanBidAdapter.js create mode 100644 modules/adoceanBidAdapter.md diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js new file mode 100644 index 00000000000..79382246f11 --- /dev/null +++ b/modules/adoceanBidAdapter.js @@ -0,0 +1,211 @@ +import { _each, isStr, isArray } from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import {BANNER, VIDEO} from '../src/mediaTypes.js'; + +const BIDDER_CODE = 'adocean'; +const URL_SAFE_FIELDS = { + schain: true, + slaves: true +}; + +function buildEndpointUrl(emiter, payloadMap) { + const payload = []; + _each(payloadMap, function(v, k) { + payload.push(k + '=' + (URL_SAFE_FIELDS[k] ? v : encodeURIComponent(v))); + }); + + const randomizedPart = Math.random().toString().slice(2); + return 'https://' + emiter + '/_' + randomizedPart + '/ad.json?' + payload.join('&'); +} + +function buildRequest(masterBidRequests, masterId, gdprConsent) { + let emiter; + const payload = { + id: masterId, + slaves: [] + }; + if (gdprConsent) { + payload.gdpr_consent = gdprConsent.consentString || undefined; + payload.gdpr = gdprConsent.gdprApplies ? 1 : 0; + } + const anyKey = Object.keys(masterBidRequests)[0]; + if (masterBidRequests[anyKey].schain) { + payload.schain = serializeSupplyChain(masterBidRequests[anyKey].schain); + } + + const anyBid = masterBidRequests[anyKey]; + if (anyBid && anyBid.userId && anyBid.userId.gemiusId) { + payload.aouserid = anyBid.userId.gemiusId; + } + + const bidIdMap = {}; + const uniquePartLength = 10; + _each(masterBidRequests, function(bid, slaveId) { + if (!emiter) { + emiter = bid.params.emiter; + } + + const rawSlaveId = bid.params.slaveId.replace('adocean', ''); + payload.slaves.push(rawSlaveId.slice(-uniquePartLength)); + + bidIdMap[slaveId] = bid.bidId; + + if (bid.mediaTypes.video) { + if (bid.mediaTypes.video.context === 'instream') { + payload.dur = bid.mediaTypes.video.maxduration; + payload.maxdur = bid.mediaTypes.video.maxduration; + payload.mindur = bid.mediaTypes.video.minduration; + payload.spots = 1; + } + if (bid.mediaTypes.video.context === 'adpod') { + const durationRangeSec = bid.mediaTypes.video.durationRangeSec; + const spots = getAdPodSpots(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec); + const maxDuration = Math.max(...durationRangeSec); + payload.dur = bid.mediaTypes.video.adPodDurationSec; + payload.maxdur = maxDuration; + payload.spots = spots; + } + } + }); + + payload.slaves = payload.slaves.join(','); + + return { + method: 'GET', + url: buildEndpointUrl(emiter, payload), + data: '', + bidIdMap: bidIdMap + }; +} + +function getAdPodSpots(adPodDurationSec, durationRangeSec) { + const minAllowedDuration = Math.min(...durationRangeSec); + const numberOfSpots = Math.floor(adPodDurationSec / minAllowedDuration); + return numberOfSpots; +} + +const SCHAIN_FIELDS = ['asi', 'sid', 'hp', 'rid', 'name', 'domain', 'ext']; +function serializeSupplyChain(schain) { + const header = `${schain.ver},${schain.complete}!`; + + const serializedNodes = []; + _each(schain.nodes, function(node) { + const serializedNode = SCHAIN_FIELDS + .map(fieldName => { + if (fieldName === 'ext') { + // do not serialize ext data, just mark if it was available + return ('ext' in node ? '1' : '0'); + } + if (fieldName in node) { + return encodeURIComponent(node[fieldName]).replace(/!/g, '%21'); + } + return ''; + }) + .join(','); + serializedNodes.push(serializedNode); + }); + + return header + serializedNodes.join('!'); +} + +function assignToMaster(bidRequest, bidRequestsByMaster) { + const masterId = bidRequest.params.masterId; + const slaveId = bidRequest.params.slaveId; + const masterBidRequests = bidRequestsByMaster[masterId] = bidRequestsByMaster[masterId] || [{}]; + let i = 0; + while (masterBidRequests[i] && masterBidRequests[i][slaveId]) { + i++; + } + if (!masterBidRequests[i]) { + masterBidRequests[i] = {}; + } + masterBidRequests[i][slaveId] = bidRequest; +} + +function interpretResponse(placementResponse, bidRequest, bids) { + const requestId = bidRequest.bidIdMap[placementResponse.id]; + if (!placementResponse.error && requestId) { + if (!placementResponse.code || !placementResponse.height || !placementResponse.width || !placementResponse.price) { + return; + } + let adCode = decodeURIComponent(placementResponse.code); + + const bid = { + cpm: parseFloat(placementResponse.price), + currency: placementResponse.currency, + height: parseInt(placementResponse.height, 10), + requestId: requestId, + width: parseInt(placementResponse.width, 10), + netRevenue: false, + ttl: parseInt(placementResponse.ttl), + creativeId: placementResponse.crid, + meta: { + advertiserDomains: placementResponse.adomain || [] + } + }; + if (placementResponse.isVideo) { + bid.meta.mediaType = VIDEO; + bid.vastXml = adCode; + } else { + bid.meta.mediaType = BANNER; + bid.ad = adCode; + } + + bids.push(bid); + } +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + + isBidRequestValid: function(bid) { + const requiredParams = ['slaveId', 'masterId', 'emiter']; + if (requiredParams.some(name => !isStr(bid.params[name]) || !bid.params[name].length)) { + return false; + } + + if (bid.mediaTypes.banner) { + return true; + } + if (bid.mediaTypes.video) { + if (bid.mediaTypes.video.context === 'instream') { + return true; + } + if (bid.mediaTypes.video.context === 'adpod') { + return !bid.mediaTypes.video.requireExactDuration; + } + } + return false; + }, + + buildRequests: function(validBidRequests, bidderRequest) { + const bidRequestsByMaster = {}; + let requests = []; + + _each(validBidRequests, function(bidRequest) { + assignToMaster(bidRequest, bidRequestsByMaster); + }); + + _each(bidRequestsByMaster, function(masterRequests, masterId) { + _each(masterRequests, function(instanceRequests) { + requests.push(buildRequest(instanceRequests, masterId, bidderRequest.gdprConsent)); + }); + }); + + return requests; + }, + + interpretResponse: function(serverResponse, bidRequest) { + let bids = []; + + if (isArray(serverResponse.body)) { + _each(serverResponse.body, function(placementResponse) { + interpretResponse(placementResponse, bidRequest, bids); + }); + } + + return bids; + } +}; +registerBidder(spec); diff --git a/modules/adoceanBidAdapter.md b/modules/adoceanBidAdapter.md new file mode 100644 index 00000000000..c173c438ca9 --- /dev/null +++ b/modules/adoceanBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +Module Name: AdOcean Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@gemius.com + +# Description + +AdOcean Bidder Adapter for Prebid.js. +Banner and video formats are supported. + +# Test Parameters +```js + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "adocean", + params: { + slaveId: 'TODO', + masterId: 'TODO', + emiter: 'myao.adocean.pl' + } + } + ] + } + ]; +``` From 51ce6075055ceb7dc31f78ea36ecf17f1cfa70be Mon Sep 17 00:00:00 2001 From: Patryk Grzegorczyk Date: Tue, 30 Sep 2025 13:15:03 +0200 Subject: [PATCH 2/7] [ADO-981] Tests and some bug fixes --- modules/adoceanBidAdapter.js | 13 +- modules/adoceanBidAdapter.md | 58 ++- test/spec/modules/adoceanBidAdapter_spec.js | 414 ++++++++++++++++++++ 3 files changed, 467 insertions(+), 18 deletions(-) create mode 100644 test/spec/modules/adoceanBidAdapter_spec.js diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 79382246f11..67d0d9d2116 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -52,13 +52,20 @@ function buildRequest(masterBidRequests, masterId, gdprConsent) { if (bid.mediaTypes.video) { if (bid.mediaTypes.video.context === 'instream') { - payload.dur = bid.mediaTypes.video.maxduration; - payload.maxdur = bid.mediaTypes.video.maxduration; - payload.mindur = bid.mediaTypes.video.minduration; + if (bid.mediaTypes.video.maxduration) { + payload.dur = bid.mediaTypes.video.maxduration; + payload.maxdur = bid.mediaTypes.video.maxduration; + } + if (bid.mediaTypes.video.minduration) { + payload.mindur = bid.mediaTypes.video.minduration; + } payload.spots = 1; } if (bid.mediaTypes.video.context === 'adpod') { const durationRangeSec = bid.mediaTypes.video.durationRangeSec; + if (!bid.mediaTypes.video.adPodDurationSec || !isArray(durationRangeSec) || durationRangeSec.length === 0) { + return; + } const spots = getAdPodSpots(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec); const maxDuration = Math.max(...durationRangeSec); payload.dur = bid.mediaTypes.video.adPodDurationSec; diff --git a/modules/adoceanBidAdapter.md b/modules/adoceanBidAdapter.md index c173c438ca9..bf012ee080c 100644 --- a/modules/adoceanBidAdapter.md +++ b/modules/adoceanBidAdapter.md @@ -9,22 +9,50 @@ Maintainer: prebid@gemius.com AdOcean Bidder Adapter for Prebid.js. Banner and video formats are supported. -# Test Parameters +# Test Parameters Banner ```js var adUnits = [ - { - code: 'test-div', - sizes: [[300, 250]], - bids: [ - { - bidder: "adocean", - params: { - slaveId: 'TODO', - masterId: 'TODO', - emiter: 'myao.adocean.pl' - } + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: "adocean", + params: { + slaveId: 'TODO', + masterId: 'TODO', + emiter: 'myao.adocean.pl' } - ] - } - ]; + } + ] + } + ]; +``` +# Test Parameters Video +```js + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [300, 250] + } + }, + bids: [ + { + bidder: "adocean", + params: { + slaveId: 'TODO', + masterId: 'TODO', + emiter: 'myao.adocean.pl' + } + } + ] + } + ]; ``` diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js new file mode 100644 index 00000000000..9a275f81d4e --- /dev/null +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -0,0 +1,414 @@ +import { expect } from 'chai'; +import { spec } from 'modules/adoceanBidAdapter.js'; +import { newBidder } from 'src/adapters/bidderFactory.js'; +import { deepClone } from 'src/utils.js'; + +describe('AdoceanAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + const bannerBid = { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + const invalidBid = Object.assign({}, bannerBid); + delete invalidBid.params; + invalidBid.params = { + masterId: 0 + }; + + expect(spec.isBidRequestValid(invalidBid)).to.equal(false); + }); + + const videoInscreenBid = { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + video: { + context: 'instream', + playerSize: [300, 250] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + }; + it('should return true for instream video', function () { + expect(spec.isBidRequestValid(videoInscreenBid)).to.equal(true); + }); + + const videoAdpodBid = { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + video: { + context: 'adpod', + playerSize: [300, 250], + adPodDurationSec: 300, + durationRangeSec: [15, 30], + requireExactDuration: false + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + }; + it('should return true for adpod video without requireExactDuration', function () { + expect(spec.isBidRequestValid(videoAdpodBid)).to.equal(true); + }); + it('should return false for adpod video with requireExactDuration', function () { + const invalidBid = Object.assign({}, videoAdpodBid); + invalidBid.mediaTypes.video.requireExactDuration = true; + expect(spec.isBidRequestValid(invalidBid)).to.equal(false); + }); + + const videoOutstreamBid = { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + }; + it('should return false for outstream video', function () { + expect(spec.isBidRequestValid(videoOutstreamBid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [ + { + 'bidder': 'adocean', + 'params': { + 'masterId': 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + 'slaveId': 'adoceanmyaozpniqismex', + 'emiter': 'myao.adocean.pl' + }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'adocean', + 'params': { + 'masterId': 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + 'slaveId': 'adoceanmyaozpniqismex', + 'emiter': 'myao.adocean.pl' + }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 200], [600, 250]] + } + }, + 'bidId': '30b31c1838de1f', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + const schainExample = { + 'schain': { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001!,2', + rid: 'BidRequest1', + hp: 1 + } + ] + } + }; + + const bidderRequest = { + gdprConsent: { + consentString: 'BOQHk-4OSlWKFBoABBPLBd-AAAAgWAHAACAAsAPQBSACmgFTAOkA', + gdprApplies: true + } + }; + + it('should send two requests if slave is duplicated', function () { + const nrOfRequests = spec.buildRequests(bidRequests, bidderRequest).length; + expect(nrOfRequests).to.equal(2); + }); + + it('should add bidIdMap with correct slaveId => bidId mapping', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (let i = 0; i < bidRequests.length; i++) { + expect(requests[i]).to.exist; + expect(requests[i].bidIdMap).to.exist; + expect(requests[i].bidIdMap[bidRequests[i].params.slaveId]).to.equal(bidRequests[i].bidId); + } + }); + + it('sends bid request to url via GET', function () { + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.method).to.equal('GET'); + expect(request.url).to.match(new RegExp(`^https://${bidRequests[0].params.emiter}/_[0-9]*/ad.json`)); + }); + + it('should attach id to url', function () { + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.url).to.include('id=' + bidRequests[0].params.masterId); + }); + + it('should attach consent information to url', function () { + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.url).to.include('gdpr=1'); + expect(request.url).to.include('gdpr_consent=' + bidderRequest.gdprConsent.consentString); + }); + + it('should attach slaves information to url', function () { + let requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[0].url).to.include('slaves=zpniqismex'); + expect(requests[1].url).to.include('slaves=zpniqismex'); + + const differentSlavesBids = deepClone(bidRequests); + differentSlavesBids[1].params.slaveId = 'adoceanmyaowafpdwlrks'; + requests = spec.buildRequests(differentSlavesBids, bidderRequest); + expect(requests.length).to.equal(1); + expect(requests[0].url).to.include('slaves=zpniqismex,wafpdwlrks'); + }); + + it('should attach schain parameter if available', function() { + let requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests.some(e => e.url.includes('schain='))).to.be.false; + + const bidsWithSchain = deepClone(bidRequests).map(e => ({...e, ...schainExample})); + requests = spec.buildRequests(bidsWithSchain, bidderRequest); + expect(requests.every(e => e.url.includes('schain=1.0,1!directseller.com,00001%21%2C2,1,BidRequest1,,,0')), + `One of urls does not contain valid schain param: ${requests.map(e => e.url).join('\n')}`).to.be.true; + }); + }); + + describe('interpretResponseBanner', function () { + const response = { + 'body': [ + { + 'id': 'adoceanmyaozpniqismex', + 'price': '0.019000', + 'ttl': '360', + 'crid': 'veeinoriep', + 'currency': 'EUR', + 'width': '300', + 'height': '250', + 'isVideo': false, + 'code': '%3C!--%20Creative%20--%3E', + 'adomain': ['adocean.pl'] + } + ], + 'headers': { + 'get': function() {} + } + }; + + const bidRequest = { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bidIdMap: { + adoceanmyaozpniqismex: '30b31c1838de1e' + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + }; + + it('should get correct bid response', function () { + const expectedResponse = [ + { + 'requestId': '30b31c1838de1e', + 'cpm': 0.019000, + 'currency': 'EUR', + 'width': 300, + 'height': 250, + 'ad': '', + 'creativeId': 'veeinoriep', + 'ttl': 360, + 'netRevenue': false, + 'meta': { + 'advertiserDomains': ['adocean.pl'], + 'mediaType': 'banner' + } + } + ]; + + const result = spec.interpretResponse(response, bidRequest); + expect(result).to.have.lengthOf(1, 'Response should contain 1 bid'); + let resultKeys = Object.keys(result[0]); + expect(resultKeys.sort()).to.deep.equal(Object.keys(expectedResponse[0]).sort(), 'Response keys do not match'); + resultKeys.forEach(function(k) { + if (k === 'ad') { + expect(result[0][k]).to.match(/$/, 'ad does not match'); + } else if (k === 'meta') { + expect(result[0][k]).to.deep.equal(expectedResponse[0][k], 'meta does not match'); + } else { + expect(result[0][k]).to.equal(expectedResponse[0][k], `${k} does not match`); + } + }); + }); + + it('handles nobid responses', function () { + response.body = [ + { + 'id': 'adoceanmyaolafpjwftbz', + 'error': 'true' + } + ]; + + const result = spec.interpretResponse(response, bidRequest); + expect(result).to.have.lengthOf(0, 'Error response should be empty'); + }); + }); + + describe('interpretResponseVideo', function () { + const response = { + 'body': [ + { + 'id': 'adoceanmyaolifgmvmpfj', + 'price': '0.019000', + 'ttl': '360', + 'crid': 'qpqhltkgpu', + 'currency': 'EUR', + 'width': '300', + 'height': '250', + 'isVideo': true, + 'code': '%3C!--%20Video%20Creative%20--%3E', + 'adomain': ['adocean.pl'] + } + ], + 'headers': { + 'get': function() {} + } + }; + + const bidRequest = { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaolifgmvmpfj', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + bidIdMap: { + adoceanmyaolifgmvmpfj: '30b31c1838de1e' + }, + mediaTypes: { + video: { + playerSize: [200, 200], + context: 'instream' + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + }; + + it('should get correct bid response', function () { + const expectedResponse = [ + { + 'requestId': '30b31c1838de1e', + 'cpm': 0.019000, + 'currency': 'EUR', + 'width': 300, + 'height': 250, + 'vastXml': '', + 'creativeId': 'qpqhltkgpu', + 'ttl': 360, + 'netRevenue': false, + 'meta': { + 'advertiserDomains': ['adocean.pl'], + 'mediaType': 'video' + } + } + ]; + + const result = spec.interpretResponse(response, bidRequest); + expect(result).to.have.lengthOf(1, 'Response should contain 1 bid'); + let resultKeys = Object.keys(result[0]); + expect(resultKeys.sort()).to.deep.equal(Object.keys(expectedResponse[0]).sort(), 'Response keys do not match'); + resultKeys.forEach(function(k) { + if (k === 'vastXml') { + expect(result[0][k]).to.match(/$/, 'vastXml does not match'); + } else if (k === 'meta') { + expect(result[0][k]).to.deep.equal(expectedResponse[0][k], 'meta does not match'); + } else { + expect(result[0][k]).to.equal(expectedResponse[0][k], `${k} does not match`); + } + }); + }); + + it('handles nobid responses', function () { + response.body = [ + { + 'id': 'adoceanmyaolafpjwftbz', + 'error': 'true' + } + ]; + + const result = spec.interpretResponse(response, bidRequest); + expect(result).to.have.lengthOf(0, 'Error response should be empty'); + }); + }); +}); From 5a02f310e6548d74e9df7b0ed7dd18df82018565 Mon Sep 17 00:00:00 2001 From: Patryk Grzegorczyk Date: Tue, 30 Sep 2025 16:22:45 +0200 Subject: [PATCH 3/7] [ADO-981] Video tests --- modules/adoceanBidAdapter.js | 94 +++++--------- test/spec/modules/adoceanBidAdapter_spec.js | 131 ++++++++++++++++---- 2 files changed, 137 insertions(+), 88 deletions(-) diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 67d0d9d2116..a32814b638f 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -18,64 +18,57 @@ function buildEndpointUrl(emiter, payloadMap) { return 'https://' + emiter + '/_' + randomizedPart + '/ad.json?' + payload.join('&'); } -function buildRequest(masterBidRequests, masterId, gdprConsent) { - let emiter; +function buildRequest(bid, gdprConsent) { + const emiter = bid.params.emiter; + const masterId = bid.params.masterId; + const slaveId = bid.params.slaveId; const payload = { id: masterId, - slaves: [] + slaves: "" }; if (gdprConsent) { payload.gdpr_consent = gdprConsent.consentString || undefined; payload.gdpr = gdprConsent.gdprApplies ? 1 : 0; } - const anyKey = Object.keys(masterBidRequests)[0]; - if (masterBidRequests[anyKey].schain) { - payload.schain = serializeSupplyChain(masterBidRequests[anyKey].schain); + if (bid.schain) { + payload.schain = serializeSupplyChain(bid.schain); } - const anyBid = masterBidRequests[anyKey]; - if (anyBid && anyBid.userId && anyBid.userId.gemiusId) { - payload.aouserid = anyBid.userId.gemiusId; + if (bid.userId && bid.userId.gemiusId) { + payload.aouserid = bid.userId.gemiusId; } const bidIdMap = {}; const uniquePartLength = 10; - _each(masterBidRequests, function(bid, slaveId) { - if (!emiter) { - emiter = bid.params.emiter; - } - const rawSlaveId = bid.params.slaveId.replace('adocean', ''); - payload.slaves.push(rawSlaveId.slice(-uniquePartLength)); + const rawSlaveId = bid.params.slaveId.replace('adocean', ''); + payload.slaves = rawSlaveId.slice(-uniquePartLength); - bidIdMap[slaveId] = bid.bidId; + bidIdMap[slaveId] = bid.bidId; - if (bid.mediaTypes.video) { - if (bid.mediaTypes.video.context === 'instream') { - if (bid.mediaTypes.video.maxduration) { - payload.dur = bid.mediaTypes.video.maxduration; - payload.maxdur = bid.mediaTypes.video.maxduration; - } - if (bid.mediaTypes.video.minduration) { - payload.mindur = bid.mediaTypes.video.minduration; - } - payload.spots = 1; + if (bid.mediaTypes.video) { + if (bid.mediaTypes.video.context === 'instream') { + if (bid.mediaTypes.video.maxduration) { + payload.dur = bid.mediaTypes.video.maxduration; + payload.maxdur = bid.mediaTypes.video.maxduration; } - if (bid.mediaTypes.video.context === 'adpod') { - const durationRangeSec = bid.mediaTypes.video.durationRangeSec; - if (!bid.mediaTypes.video.adPodDurationSec || !isArray(durationRangeSec) || durationRangeSec.length === 0) { - return; - } - const spots = getAdPodSpots(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec); - const maxDuration = Math.max(...durationRangeSec); - payload.dur = bid.mediaTypes.video.adPodDurationSec; - payload.maxdur = maxDuration; - payload.spots = spots; + if (bid.mediaTypes.video.minduration) { + payload.mindur = bid.mediaTypes.video.minduration; } + payload.spots = 1; } - }); - - payload.slaves = payload.slaves.join(','); + if (bid.mediaTypes.video.context === 'adpod') { + const durationRangeSec = bid.mediaTypes.video.durationRangeSec; + if (!bid.mediaTypes.video.adPodDurationSec || !isArray(durationRangeSec) || durationRangeSec.length === 0) { + return; + } + const spots = getAdPodSpots(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec); + const maxDuration = Math.max(...durationRangeSec); + payload.dur = bid.mediaTypes.video.adPodDurationSec; + payload.maxdur = maxDuration; + payload.spots = spots; + } + } return { method: 'GET', @@ -115,20 +108,6 @@ function serializeSupplyChain(schain) { return header + serializedNodes.join('!'); } -function assignToMaster(bidRequest, bidRequestsByMaster) { - const masterId = bidRequest.params.masterId; - const slaveId = bidRequest.params.slaveId; - const masterBidRequests = bidRequestsByMaster[masterId] = bidRequestsByMaster[masterId] || [{}]; - let i = 0; - while (masterBidRequests[i] && masterBidRequests[i][slaveId]) { - i++; - } - if (!masterBidRequests[i]) { - masterBidRequests[i] = {}; - } - masterBidRequests[i][slaveId] = bidRequest; -} - function interpretResponse(placementResponse, bidRequest, bids) { const requestId = bidRequest.bidIdMap[placementResponse.id]; if (!placementResponse.error && requestId) { @@ -187,17 +166,10 @@ export const spec = { }, buildRequests: function(validBidRequests, bidderRequest) { - const bidRequestsByMaster = {}; let requests = []; _each(validBidRequests, function(bidRequest) { - assignToMaster(bidRequest, bidRequestsByMaster); - }); - - _each(bidRequestsByMaster, function(masterRequests, masterId) { - _each(masterRequests, function(instanceRequests) { - requests.push(buildRequest(instanceRequests, masterId, bidderRequest.gdprConsent)); - }); + requests.push(buildRequest(bidRequest, bidderRequest.gdprConsent)); }); return requests; diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index 9a275f81d4e..34f24884cae 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -123,42 +123,42 @@ describe('AdoceanAdapter', function () { describe('buildRequests', function () { const bidRequests = [ { - 'bidder': 'adocean', - 'params': { - 'masterId': 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', - 'slaveId': 'adoceanmyaozpniqismex', - 'emiter': 'myao.adocean.pl' + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' }, - 'adUnitCode': 'adunit-code', - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] } }, - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', }, { - 'bidder': 'adocean', - 'params': { - 'masterId': 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', - 'slaveId': 'adoceanmyaozpniqismex', - 'emiter': 'myao.adocean.pl' + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' }, - 'adUnitCode': 'adunit-code', - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 200], [600, 250]] + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 200], [600, 250]] } }, - 'bidId': '30b31c1838de1f', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', + bidId: '30b31c1838de1f', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', } ]; const schainExample = { - 'schain': { + schain: { ver: '1.0', complete: 1, nodes: [ @@ -218,8 +218,17 @@ describe('AdoceanAdapter', function () { const differentSlavesBids = deepClone(bidRequests); differentSlavesBids[1].params.slaveId = 'adoceanmyaowafpdwlrks'; requests = spec.buildRequests(differentSlavesBids, bidderRequest); - expect(requests.length).to.equal(1); - expect(requests[0].url).to.include('slaves=zpniqismex,wafpdwlrks'); + expect(requests.length).to.equal(2); + let firstSlaveInExactlyOneUrl = false; + if (requests[0].url.includes('slaves=zpniqismex') ^ requests[1].url.includes('slaves=zpniqismex')) { + firstSlaveInExactlyOneUrl = true; + } + let secondSlaveInExactlyOneUrl = false; + if (requests[0].url.includes('slaves=wafpdwlrks') ^ requests[1].url.includes('slaves=wafpdwlrks')) { + secondSlaveInExactlyOneUrl = true; + } + expect(firstSlaveInExactlyOneUrl, 'First slave is present in exactly one url').to.be.true; + expect(secondSlaveInExactlyOneUrl, 'Second slave is present in exactly one url').to.be.true; }); it('should attach schain parameter if available', function() { @@ -231,6 +240,74 @@ describe('AdoceanAdapter', function () { expect(requests.every(e => e.url.includes('schain=1.0,1!directseller.com,00001%21%2C2,1,BidRequest1,,,0')), `One of urls does not contain valid schain param: ${requests.map(e => e.url).join('\n')}`).to.be.true; }); + + const videoInstreamBidRequests = [ + { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + video: { + playerSize: [200, 200], + context: 'instream', + minduration: 10, + maxduration: 60, + } + }, + bidId: '30b31c1838de1g', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a476', + } + ]; + it('should build correct video instream request', function () { + const request = spec.buildRequests(videoInstreamBidRequests, bidderRequest)[0]; + expect(request).to.exist; + expect(request.url).to.include('id=' + videoInstreamBidRequests[0].params.masterId); + expect(request.url).to.include('slaves=zpniqismex'); + expect(request.url).to.include('spots=1'); + expect(request.url).to.include('dur=60'); + expect(request.url).to.include('maxdur=60'); + expect(request.url).to.include('mindur=10'); + }); + + const videoAdpodBidRequests = [ + { + bidder: 'adocean', + params: { + masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + slaveId: 'adoceanmyaozpniqismex', + emiter: 'myao.adocean.pl' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + video: { + playerSize: [200, 200], + context: 'adpod', + adPodDurationSec: 300, + durationRangeSec: [15, 30], + requireExactDuration: false + } + }, + bidId: '30b31c1838de1h', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a476', + } + ]; + + it('should build correct video adpod request', function () { + const request = spec.buildRequests(videoAdpodBidRequests, bidderRequest)[0]; + expect(request).to.exist; + expect(request.url).to.include('id=' + videoAdpodBidRequests[0].params.masterId); + expect(request.url).to.include('slaves=zpniqismex'); + expect(request.url).to.include('spots=20'); // 300 / 15 = 20 + expect(request.url).to.include('dur=300'); + expect(request.url).to.include('maxdur=30'); + expect(request.url).to.not.include('mindur='); + }); }); describe('interpretResponseBanner', function () { From 21e4b1e3f0a18a5d943e566aa0bdb5014602b6c0 Mon Sep 17 00:00:00 2001 From: Patryk Grzegorczyk Date: Wed, 1 Oct 2025 14:02:23 +0200 Subject: [PATCH 4/7] [ADO-981] Ao sizes --- modules/adoceanBidAdapter.js | 4 +++- test/spec/modules/adoceanBidAdapter_spec.js | 14 ++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index a32814b638f..7c5822ede93 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -1,4 +1,4 @@ -import { _each, isStr, isArray } from '../src/utils.js'; +import { _each, isStr, isArray, parseSizesInput } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; @@ -68,6 +68,8 @@ function buildRequest(bid, gdprConsent) { payload.maxdur = maxDuration; payload.spots = spots; } + } else if (bid.mediaTypes.banner) { + payload.aosize = parseSizesInput(bid.mediaTypes.banner.sizes).join(','); } return { diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index 34f24884cae..fc952c5fe5b 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -214,21 +214,15 @@ describe('AdoceanAdapter', function () { let requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests[0].url).to.include('slaves=zpniqismex'); expect(requests[1].url).to.include('slaves=zpniqismex'); + expect(requests[0].url).to.include('aosize=300x250%2C300x600'); + expect(requests[1].url).to.include('aosize=300x200%2C600x250'); const differentSlavesBids = deepClone(bidRequests); differentSlavesBids[1].params.slaveId = 'adoceanmyaowafpdwlrks'; requests = spec.buildRequests(differentSlavesBids, bidderRequest); expect(requests.length).to.equal(2); - let firstSlaveInExactlyOneUrl = false; - if (requests[0].url.includes('slaves=zpniqismex') ^ requests[1].url.includes('slaves=zpniqismex')) { - firstSlaveInExactlyOneUrl = true; - } - let secondSlaveInExactlyOneUrl = false; - if (requests[0].url.includes('slaves=wafpdwlrks') ^ requests[1].url.includes('slaves=wafpdwlrks')) { - secondSlaveInExactlyOneUrl = true; - } - expect(firstSlaveInExactlyOneUrl, 'First slave is present in exactly one url').to.be.true; - expect(secondSlaveInExactlyOneUrl, 'Second slave is present in exactly one url').to.be.true; + expect(requests[0].url).to.include('slaves=zpniqismex'); + expect(requests[1].url).to.include('slaves=wafpdwlrks'); }); it('should attach schain parameter if available', function() { From 5447fe0d8001e2591fddd88fdda8c7b55f55942a Mon Sep 17 00:00:00 2001 From: Patryk Grzegorczyk Date: Thu, 2 Oct 2025 10:33:20 +0200 Subject: [PATCH 5/7] [ADO-981] Review changes --- modules/adoceanBidAdapter.js | 34 ++----------------- test/spec/modules/adoceanBidAdapter_spec.js | 36 ++++----------------- 2 files changed, 9 insertions(+), 61 deletions(-) diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 7c5822ede93..39eb45059f5 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -1,10 +1,9 @@ import { _each, isStr, isArray, parseSizesInput } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; const BIDDER_CODE = 'adocean'; const URL_SAFE_FIELDS = { - schain: true, slaves: true }; @@ -30,9 +29,6 @@ function buildRequest(bid, gdprConsent) { payload.gdpr_consent = gdprConsent.consentString || undefined; payload.gdpr = gdprConsent.gdprApplies ? 1 : 0; } - if (bid.schain) { - payload.schain = serializeSupplyChain(bid.schain); - } if (bid.userId && bid.userId.gemiusId) { payload.aouserid = bid.userId.gemiusId; @@ -62,7 +58,7 @@ function buildRequest(bid, gdprConsent) { if (!bid.mediaTypes.video.adPodDurationSec || !isArray(durationRangeSec) || durationRangeSec.length === 0) { return; } - const spots = getAdPodSpots(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec); + const spots = calculateAdPodSpotsNumber(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec); const maxDuration = Math.max(...durationRangeSec); payload.dur = bid.mediaTypes.video.adPodDurationSec; payload.maxdur = maxDuration; @@ -80,36 +76,12 @@ function buildRequest(bid, gdprConsent) { }; } -function getAdPodSpots(adPodDurationSec, durationRangeSec) { +function calculateAdPodSpotsNumber(adPodDurationSec, durationRangeSec) { const minAllowedDuration = Math.min(...durationRangeSec); const numberOfSpots = Math.floor(adPodDurationSec / minAllowedDuration); return numberOfSpots; } -const SCHAIN_FIELDS = ['asi', 'sid', 'hp', 'rid', 'name', 'domain', 'ext']; -function serializeSupplyChain(schain) { - const header = `${schain.ver},${schain.complete}!`; - - const serializedNodes = []; - _each(schain.nodes, function(node) { - const serializedNode = SCHAIN_FIELDS - .map(fieldName => { - if (fieldName === 'ext') { - // do not serialize ext data, just mark if it was available - return ('ext' in node ? '1' : '0'); - } - if (fieldName in node) { - return encodeURIComponent(node[fieldName]).replace(/!/g, '%21'); - } - return ''; - }) - .join(','); - serializedNodes.push(serializedNode); - }); - - return header + serializedNodes.join('!'); -} - function interpretResponse(placementResponse, bidRequest, bids) { const requestId = bidRequest.bidIdMap[placementResponse.id]; if (!placementResponse.error && requestId) { diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index fc952c5fe5b..0f060f23a28 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -36,12 +36,7 @@ describe('AdoceanAdapter', function () { }); it('should return false when required params are not passed', function () { - const invalidBid = Object.assign({}, bannerBid); - delete invalidBid.params; - invalidBid.params = { - masterId: 0 - }; - + const invalidBid = Object.assign({}, bannerBid, {params: {masterId: 0}}); expect(spec.isBidRequestValid(invalidBid)).to.equal(false); }); @@ -63,6 +58,7 @@ describe('AdoceanAdapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', }; + it('should return true for instream video', function () { expect(spec.isBidRequestValid(videoInscreenBid)).to.equal(true); }); @@ -88,9 +84,11 @@ describe('AdoceanAdapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', }; + it('should return true for adpod video without requireExactDuration', function () { expect(spec.isBidRequestValid(videoAdpodBid)).to.equal(true); }); + it('should return false for adpod video with requireExactDuration', function () { const invalidBid = Object.assign({}, videoAdpodBid); invalidBid.mediaTypes.video.requireExactDuration = true; @@ -115,6 +113,7 @@ describe('AdoceanAdapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', }; + it('should return false for outstream video', function () { expect(spec.isBidRequestValid(videoOutstreamBid)).to.equal(false); }); @@ -157,20 +156,6 @@ describe('AdoceanAdapter', function () { auctionId: '1d1a030790a475', } ]; - const schainExample = { - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001!,2', - rid: 'BidRequest1', - hp: 1 - } - ] - } - }; const bidderRequest = { gdprConsent: { @@ -225,16 +210,6 @@ describe('AdoceanAdapter', function () { expect(requests[1].url).to.include('slaves=wafpdwlrks'); }); - it('should attach schain parameter if available', function() { - let requests = spec.buildRequests(bidRequests, bidderRequest); - expect(requests.some(e => e.url.includes('schain='))).to.be.false; - - const bidsWithSchain = deepClone(bidRequests).map(e => ({...e, ...schainExample})); - requests = spec.buildRequests(bidsWithSchain, bidderRequest); - expect(requests.every(e => e.url.includes('schain=1.0,1!directseller.com,00001%21%2C2,1,BidRequest1,,,0')), - `One of urls does not contain valid schain param: ${requests.map(e => e.url).join('\n')}`).to.be.true; - }); - const videoInstreamBidRequests = [ { bidder: 'adocean', @@ -257,6 +232,7 @@ describe('AdoceanAdapter', function () { auctionId: '1d1a030790a476', } ]; + it('should build correct video instream request', function () { const request = spec.buildRequests(videoInstreamBidRequests, bidderRequest)[0]; expect(request).to.exist; From 5c36f56927839bf826c89cdbeaf47269dcd2de5d Mon Sep 17 00:00:00 2001 From: Patryk Grzegorczyk Date: Mon, 6 Oct 2025 13:07:48 +0200 Subject: [PATCH 6/7] [ADO-981] Updated bidder md file --- modules/adoceanBidAdapter.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/adoceanBidAdapter.md b/modules/adoceanBidAdapter.md index bf012ee080c..bee8ee512ff 100644 --- a/modules/adoceanBidAdapter.md +++ b/modules/adoceanBidAdapter.md @@ -16,15 +16,15 @@ Banner and video formats are supported. code: 'test-div', mediaTypes: { banner: { - sizes: [[300, 250]] + sizes: [[300, 200]] } }, bids: [ { bidder: "adocean", params: { - slaveId: 'TODO', - masterId: 'TODO', + slaveId: 'adoceanmyaotcpiltmmnj', + masterId: 'ek1AWtSWh3BOa_x2P1vlMQ_uXXJpJcbhsHAY5PFQjWD.D7', emiter: 'myao.adocean.pl' } } @@ -40,15 +40,15 @@ Banner and video formats are supported. mediaTypes: { video: { context: 'instream', - playerSize: [300, 250] + playerSize: [300, 200] } }, bids: [ { bidder: "adocean", params: { - slaveId: 'TODO', - masterId: 'TODO', + slaveId: 'adoceanmyaonenfcoqfnd', + masterId: '2k6gA7RWl08Zn0bi42RV8LNCANpKb6LqhvKzbmK3pzP.U7', emiter: 'myao.adocean.pl' } } From 0bd3bad1d1546357b977cb4febdc7d8e8b0c8ade Mon Sep 17 00:00:00 2001 From: Patryk Grzegorczyk Date: Tue, 7 Oct 2025 13:41:20 +0200 Subject: [PATCH 7/7] [ADO-981] Change param name --- modules/adoceanBidAdapter.js | 10 +++++----- modules/adoceanBidAdapter.md | 4 ++-- test/spec/modules/adoceanBidAdapter_spec.js | 22 ++++++++++----------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 39eb45059f5..6f6548a1ba8 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -7,18 +7,18 @@ const URL_SAFE_FIELDS = { slaves: true }; -function buildEndpointUrl(emiter, payloadMap) { +function buildEndpointUrl(emitter, payloadMap) { const payload = []; _each(payloadMap, function(v, k) { payload.push(k + '=' + (URL_SAFE_FIELDS[k] ? v : encodeURIComponent(v))); }); const randomizedPart = Math.random().toString().slice(2); - return 'https://' + emiter + '/_' + randomizedPart + '/ad.json?' + payload.join('&'); + return 'https://' + emitter + '/_' + randomizedPart + '/ad.json?' + payload.join('&'); } function buildRequest(bid, gdprConsent) { - const emiter = bid.params.emiter; + const emitter = bid.params.emitter; const masterId = bid.params.masterId; const slaveId = bid.params.slaveId; const payload = { @@ -70,7 +70,7 @@ function buildRequest(bid, gdprConsent) { return { method: 'GET', - url: buildEndpointUrl(emiter, payload), + url: buildEndpointUrl(emitter, payload), data: '', bidIdMap: bidIdMap }; @@ -120,7 +120,7 @@ export const spec = { supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bid) { - const requiredParams = ['slaveId', 'masterId', 'emiter']; + const requiredParams = ['slaveId', 'masterId', 'emitter']; if (requiredParams.some(name => !isStr(bid.params[name]) || !bid.params[name].length)) { return false; } diff --git a/modules/adoceanBidAdapter.md b/modules/adoceanBidAdapter.md index bee8ee512ff..c7b55ddc5c3 100644 --- a/modules/adoceanBidAdapter.md +++ b/modules/adoceanBidAdapter.md @@ -25,7 +25,7 @@ Banner and video formats are supported. params: { slaveId: 'adoceanmyaotcpiltmmnj', masterId: 'ek1AWtSWh3BOa_x2P1vlMQ_uXXJpJcbhsHAY5PFQjWD.D7', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' } } ] @@ -49,7 +49,7 @@ Banner and video formats are supported. params: { slaveId: 'adoceanmyaonenfcoqfnd', masterId: '2k6gA7RWl08Zn0bi42RV8LNCANpKb6LqhvKzbmK3pzP.U7', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' } } ] diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index 0f060f23a28..53a82ec963d 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -18,7 +18,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -45,7 +45,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -68,7 +68,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -100,7 +100,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -126,7 +126,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -143,7 +143,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -181,7 +181,7 @@ describe('AdoceanAdapter', function () { it('sends bid request to url via GET', function () { const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.method).to.equal('GET'); - expect(request.url).to.match(new RegExp(`^https://${bidRequests[0].params.emiter}/_[0-9]*/ad.json`)); + expect(request.url).to.match(new RegExp(`^https://${bidRequests[0].params.emitter}/_[0-9]*/ad.json`)); }); it('should attach id to url', function () { @@ -216,7 +216,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -250,7 +250,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -306,7 +306,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaozpniqismex', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -395,7 +395,7 @@ describe('AdoceanAdapter', function () { params: { masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', slaveId: 'adoceanmyaolifgmvmpfj', - emiter: 'myao.adocean.pl' + emitter: 'myao.adocean.pl' }, adUnitCode: 'adunit-code', bidIdMap: {