diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 0f6648fc509..fff0e4c2ed8 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -3,6 +3,7 @@ import { tryAppendQueryString } from '../libraries/urlUtils/urlUtils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { Renderer } from '../src/Renderer.js'; import { getStorageManager } from '../src/storageManager.js'; import { deepAccess, deepSetValue, logError, logWarn, mergeDeep } from '../src/utils.js'; @@ -16,6 +17,7 @@ const COOKIE_SYNC_ORIGIN = 'https://apps.smartadserver.com'; const COOKIE_SYNC_URL = `${COOKIE_SYNC_ORIGIN}/diff/templates/asset/csync.html`; const DEFAULT_TTL = 300; const LOG_PREFIX = 'Equativ:'; +const OUTSTREAM_RENDERER_URL = 'https://apps.sascdn.com/diff/video-outstream/equativ-video-outstream.js'; const PID_STORAGE_NAME = 'eqt_pid'; let feedbackArray = []; @@ -244,6 +246,32 @@ export const converter = ortbConverter({ ttl: DEFAULT_TTL }, + bidResponse(buildBidResponse, bid, context) { + const { bidRequest } = context; + const bidResponse = buildBidResponse(bid, context); + + if (bidResponse.mediaType === VIDEO && bidRequest.mediaTypes.video.context === 'outstream') { + const renderer = Renderer.install({ + adUnitCode: bidRequest.adUnitCode, + id: bidRequest.bidId, + url: OUTSTREAM_RENDERER_URL, + }); + + renderer.setRender((bid) => { + bid.renderer.push(() => { + window.EquativVideoOutstream.renderAd({ + slotId: bid.adUnitCode, + vast: bid.vastUrl || bid.vastXml + }); + }); + }); + + bidResponse.renderer = renderer; + } + + return bidResponse; + }, + imp(buildImp, bidRequest, context) { const imp = buildImp(bidRequest, context); const { siteId, pageId, formatId } = bidRequest.params; diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index 32f5c05077f..0e1cfd77360 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -1,4 +1,5 @@ import { converter, getImpIdMap, spec, storage } from 'modules/equativBidAdapter.js'; +import { Renderer } from 'src/Renderer.js'; import * as utils from '../../../src/utils.js'; describe('Equativ bid adapter tests', () => { @@ -109,6 +110,7 @@ describe('Equativ bid adapter tests', () => { privacy: 1, ver: '1.2', }; + const DEFAULT_NATIVE_BID_REQUESTS = [ { adUnitCode: 'equativ_native_42', @@ -1043,6 +1045,105 @@ describe('Equativ bid adapter tests', () => { expect(result.bids[0]).to.have.property('ttl').that.eq(120); }); + + describe('outstream', () => { + const bidId = 'abcd1234'; + + const bidRequests = [{ + bidId, + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + context: 'outstream' + } + }, + params: { + networkId: 111 + } + }]; + + it('should add renderer', () => { + const request = spec.buildRequests( + bidRequests, + { + bidderCode: 'equativ', + bids: bidRequests + } + )[0]; + + const response = { + body: { + seatbid: [ + { + bid: [{ mtype: 2 }] + } + ] + } + }; + + const impIdMap = getImpIdMap(); + response.body.seatbid[0].bid[0].impid = Object.keys(impIdMap).find(key => impIdMap[key] === bidId); + const bid = spec.interpretResponse(response, request).bids[0]; + + expect(bid).to.have.property('renderer'); + expect(bid.renderer).to.be.instanceof(Renderer); + expect(bid.renderer.url).eq('https://apps.sascdn.com/diff/video-outstream/equativ-video-outstream.js'); + }); + + it('should initialize and set renderer', () => { + const fakeRenderer = { + push: (cb) => cb(), + setRender: sinon.stub() + }; + + const installStub = sandBox.stub(Renderer, 'install').returns(fakeRenderer); + const renderAdStub = sandBox.stub(); + + window.EquativVideoOutstream = { renderAd: renderAdStub }; + + const request = spec.buildRequests( + bidRequests, + { + bidderCode: 'equativ', + bids: bidRequests + } + )[0]; + + expect(installStub.notCalled).to.be.true; + expect(fakeRenderer.setRender.notCalled).to.be.true; + + const response = { + body: { + seatbid: [ + { + bid: [{ + mtype: 2, + renderer: fakeRenderer + }] + } + ] + } + }; + + const impIdMap = getImpIdMap(); + response.body.seatbid[0].bid[0].impid = Object.keys(impIdMap).find(key => impIdMap[key] === bidId); + + const bid = spec.interpretResponse(response, request).bids[0]; + + expect(installStub.calledOnce).to.be.true; + expect(fakeRenderer.setRender.calledOnce).to.be.true; + + const renderFn = fakeRenderer.setRender.firstCall.args[0]; + + renderFn(bid); + + expect(renderAdStub.calledOnce).to.be.true; + expect(renderAdStub.firstCall.args[0]).to.have.property('slotId'); + expect(renderAdStub.firstCall.args[0]).to.have.property('vast'); + }); + }); }); describe('isBidRequestValid', () => {