From 6f4b9e3038286f50a62b0425fab6457890f46227 Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Tue, 31 Aug 2021 18:54:21 -0400 Subject: [PATCH 01/13] prevents registering a same provider twice --- modules/videoModule/coreVideo.js | 9 +++++++-- modules/videoModule/pbVideo.js | 0 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 modules/videoModule/pbVideo.js diff --git a/modules/videoModule/coreVideo.js b/modules/videoModule/coreVideo.js index 5288dfd9f52..ab75044234e 100644 --- a/modules/videoModule/coreVideo.js +++ b/modules/videoModule/coreVideo.js @@ -1,17 +1,22 @@ -import { vendorDirectory } from './vendorDirectory'; +import { vendorDirectory } from './vendorDirectory.js'; export function VideoCore(submoduleBuilder_) { const submodules = {}; const submoduleBuilder = submoduleBuilder_; function registerProvider(providerConfig) { + const divId = providerConfig.divId; + if (submodules[divId]) { + return; + } + let submodule; try { submodule = submoduleBuilder.build(providerConfig); } catch (e) { throw e; } - submodules[providerConfig.divId] = submodule; + submodules[divId] = submodule; } function getOrtbParams(divId) { diff --git a/modules/videoModule/pbVideo.js b/modules/videoModule/pbVideo.js new file mode 100644 index 00000000000..e69de29bb2d From 42cba91780db0488eece06871832902a361c3112 Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Tue, 31 Aug 2021 18:54:35 -0400 Subject: [PATCH 02/13] adds pb video --- modules/videoModule/pbVideo.js | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/modules/videoModule/pbVideo.js b/modules/videoModule/pbVideo.js index e69de29bb2d..615745c5773 100644 --- a/modules/videoModule/pbVideo.js +++ b/modules/videoModule/pbVideo.js @@ -0,0 +1,51 @@ +import {getGlobal} from '../../src/prebidGlobal.js'; +import {config} from '../../src/config.js'; +import events from '../../src/events.js'; +import CONSTANTS from '../../src/constants.json' +import { videoCoreFactory } from './coreVideo.js' + +export function PbVideo(videoCore_, getConfig_, requestBids_, onPbEvents_) { + const videoCore = videoCore_; + const getConfig = getConfig_; + const requestBids = requestBids_; + const onPbEvents = onPbEvents_; + + function init() { + getConfig('video.providers', providers => { + providers.forEach(provider => { + videoCore.registerProvider(provider); + }); + // maybe video.providers to get changes on providers + // called whenever 'video' is updated + // instantiate anc check for new submodules + }); + + // before bids are requested , getOrtbParams and write to the ad units. + requestBids.before(enrichAdUnits, 40); + + + // bidsBackHandler -> setAdTagUrl + onPbEvents(CONSTANTS.EVENTS.AUCTION_END, function(auctionResult) { + // get winning bid + vast xml + }); + + // analytics registering and surfacing + } + + function enrichAdUnits(nextFn, bidRequest) { + // get oRTB arams + // write to ad units + // let adUnits = bidRequest.adUnits + } + + return { init }; +} + +function pbVideoFactory() { + const videoCore = videoCoreFactory(); + const pbVideo = PbVideo(videoCore, config.getConfig, getGlobal().requestBids, events.on); + pbVideo.init(); + return pbVideo; +} + +pbVideoFactory(); From 61b586bcf21bab5a32263b30470c3d2d8a8b085d Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Wed, 1 Sep 2021 15:51:57 -0400 Subject: [PATCH 03/13] adds video module to submodules list --- integrationExamples/videoModule/index.html | 0 modules/.submodules.json | 4 ++++ modules/videoModule/coreVideo.js | 2 +- modules/videoModule/{pbVideo.js => index.js} | 5 ++--- modules/videoModule/submodules/jwplayerVideoProvider.js | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 integrationExamples/videoModule/index.html rename modules/videoModule/{pbVideo.js => index.js} (94%) diff --git a/integrationExamples/videoModule/index.html b/integrationExamples/videoModule/index.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/modules/.submodules.json b/modules/.submodules.json index 555e8adaefa..c4d279e771a 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -52,5 +52,9 @@ "fpdModule": [ "enrichmentFpdModule", "validationFpdModule" + ], + "videoModule": [ + "coreVideo", + "jwplayerVideoProvider" ] } diff --git a/modules/videoModule/coreVideo.js b/modules/videoModule/coreVideo.js index ab75044234e..36b0a90f4ff 100644 --- a/modules/videoModule/coreVideo.js +++ b/modules/videoModule/coreVideo.js @@ -63,7 +63,7 @@ export function VideoSubmoduleBuilder(vendorDirectory_) { } const submodule = submoduleFactory(providerConfig); - submodule.init && submodule.init(); + submodule && submodule.init && submodule.init(); return submodule; } diff --git a/modules/videoModule/pbVideo.js b/modules/videoModule/index.js similarity index 94% rename from modules/videoModule/pbVideo.js rename to modules/videoModule/index.js index 615745c5773..430354269ef 100644 --- a/modules/videoModule/pbVideo.js +++ b/modules/videoModule/index.js @@ -11,8 +11,8 @@ export function PbVideo(videoCore_, getConfig_, requestBids_, onPbEvents_) { const onPbEvents = onPbEvents_; function init() { - getConfig('video.providers', providers => { - providers.forEach(provider => { + getConfig('video', ({ video }) => { + video.providers.forEach(provider => { videoCore.registerProvider(provider); }); // maybe video.providers to get changes on providers @@ -23,7 +23,6 @@ export function PbVideo(videoCore_, getConfig_, requestBids_, onPbEvents_) { // before bids are requested , getOrtbParams and write to the ad units. requestBids.before(enrichAdUnits, 40); - // bidsBackHandler -> setAdTagUrl onPbEvents(CONSTANTS.EVENTS.AUCTION_END, function(auctionResult) { // get winning bid + vast xml diff --git a/modules/videoModule/submodules/jwplayerVideoProvider.js b/modules/videoModule/submodules/jwplayerVideoProvider.js index 8350739d895..89c439c793c 100644 --- a/modules/videoModule/submodules/jwplayerVideoProvider.js +++ b/modules/videoModule/submodules/jwplayerVideoProvider.js @@ -9,7 +9,7 @@ import { } from '../constants/events.js'; import stateFactory from '../shared/state.js'; import { JWPLAYER_VENDOR } from '../constants/vendorCodes.js'; -import { vendorDirectory } from '../vendorDirectory'; +import { vendorDirectory } from '../vendorDirectory.js'; export function JWPlayerProvider(config, jwplayer_, adState_, timeState_, callbackStorage_, utils) { const jwplayer = jwplayer_; From 944f9c3febe4eaa1c7209fd926a8a5564518048b Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Wed, 1 Sep 2021 15:52:06 -0400 Subject: [PATCH 04/13] adds integration example --- integrationExamples/videoModule/index.html | 102 +++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/integrationExamples/videoModule/index.html b/integrationExamples/videoModule/index.html index e69de29bb2d..dfe1fffef9f 100644 --- a/integrationExamples/videoModule/index.html +++ b/integrationExamples/videoModule/index.html @@ -0,0 +1,102 @@ + + + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+
Div-2
+
+ + + + From ee2882ec7334e04e760b80bb9cfb4f16a8f894c5 Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Wed, 1 Sep 2021 18:32:52 -0400 Subject: [PATCH 05/13] implements ad unit enrichment --- integrationExamples/videoModule/index.html | 24 ++++++++++++++---- modules/videoModule/index.js | 29 ++++++++++++---------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/integrationExamples/videoModule/index.html b/integrationExamples/videoModule/index.html index dfe1fffef9f..130e6aeacaf 100644 --- a/integrationExamples/videoModule/index.html +++ b/integrationExamples/videoModule/index.html @@ -9,18 +9,33 @@ diff --git a/modules/videoModule/index.js b/modules/videoModule/index.js index b89a4ccbd2f..4d318c4d866 100644 --- a/modules/videoModule/index.js +++ b/modules/videoModule/index.js @@ -1,8 +1,8 @@ -import {config} from '../../src/config.js'; +// import {config} from '../../src/config.js'; import events from '../../src/events.js'; import { allVideoEvents } from './constants/events.js'; import CONSTANTS from '../../src/constants.json'; -import { videoCoreFactory } from './coreVideo.js'; +// import { videoCoreFactory } from './coreVideo.js'; events.addEvents(allVideoEvents); @@ -41,17 +41,17 @@ export function PbVideo(videoCore_, getConfig_, pbGlobal_, pbEvents_, videoEvent const oRtbParams = videoCore.getOrtbParams(adUnit.video.divId); adUnit.mediaTypes.video = Object.assign({}, adUnit.mediaTypes.video, oRtbParams); }); - return nextFn.call(this, config); + return nextFn.call(this, bidRequest); } return { init }; } -function pbVideoFactory() { - const videoCore = videoCoreFactory(); - const pbVideo = PbVideo(videoCore, config.getConfig, $$PREBID_GLOBAL$$, events, allVideoEvents); - pbVideo.init(); - return pbVideo; -} - -pbVideoFactory(); +// function pbVideoFactory() { +// const videoCore = videoCoreFactory(); +// const pbVideo = PbVideo(videoCore, config.getConfig, $$PREBID_GLOBAL$$, events, allVideoEvents); +// pbVideo.init(); +// return pbVideo; +// } +// +// pbVideoFactory(); diff --git a/test/spec/modules/videoModule/pbVideo_spec.js b/test/spec/modules/videoModule/pbVideo_spec.js new file mode 100644 index 00000000000..5da936646c3 --- /dev/null +++ b/test/spec/modules/videoModule/pbVideo_spec.js @@ -0,0 +1,79 @@ +import { expect } from 'chai'; +import { PbVideo } from 'modules/videoModule/index.js'; + +let ortbParamsMock = { + 'video': {}, + 'content': {} +} +let videoCoreMock = { + registerProvider: sinon.spy(), + getOrtbParams: () => ortbParamsMock +}; +let getConfigMock = () => {}; +let requestBidsMock = { + before: sinon.spy() +}; +let pbGlobalMock = { + requestBids: requestBidsMock +}; +let pbEventsMock = { + emit: sinon.spy(), + on: sinon.spy() +}; +let videoEventsMock = []; + +let pbVideoFactory = (videoCore, getConfig, pbGlobal, pbEvents, videoEvents) => { + const pbVideo = PbVideo( + videoCore || videoCoreMock, + getConfig || getConfigMock, + pbGlobal || pbGlobalMock, + pbEvents || pbEventsMock, + videoEvents || videoEventsMock + ); + pbVideo.init(); + return pbVideo; +} + +describe('Prebid Video', function () { + describe('Provider Registration', function () { + + }); + + describe('Event Registration', function () { + + }); + + describe('Ad unit Enrichment', function () { + it('registers before:bidRequest hook', function () { + const pbVideo = pbVideoFactory(); + expect(requestBidsMock.before.calledOnce).to.be.true; + }); + + it('requests oRtb params and writes them to ad unit', function() { + const getOrtbParamsSpy = sinon.spy(videoCoreMock, 'getOrtbParams'); + let beforeBidRequestCallback; + const requestBids = { + before: callback_ => beforeBidRequestCallback = callback_ + }; + const pbVideo = pbVideoFactory(null, null, { requestBids }, null); + expect(beforeBidRequestCallback).to.not.be.undefined; + const nextFn = sinon.spy(); + const adUnits = [{ + code: 'ad1', + mediaTypes: { + video: {} + }, + video: { divId: 'divId' } + }]; + beforeBidRequestCallback(nextFn, { adUnits }); + expect(getOrtbParamsSpy.calledOnce).to.be.true; + const adUnit = adUnits[0]; + expect(adUnit.mediaTypes.video).to.have.property('video'); + expect(adUnit.mediaTypes.video).to.have.property('content'); + }); + }); + + describe('Ad tag injection', function () { + // TODO: requires adServer to be implemented + }); +}); From 06c01c61f4344e391224f08817d38db3da633bbb Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Tue, 7 Sep 2021 16:19:27 -0400 Subject: [PATCH 10/13] tests updating video config --- modules/videoModule/index.js | 2 +- test/spec/modules/videoModule/pbVideo_spec.js | 73 ++++++++++++++----- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/modules/videoModule/index.js b/modules/videoModule/index.js index 4d318c4d866..7fca21fbe0c 100644 --- a/modules/videoModule/index.js +++ b/modules/videoModule/index.js @@ -36,7 +36,7 @@ export function PbVideo(videoCore_, getConfig_, pbGlobal_, pbEvents_, videoEvent } function enrichAdUnits(nextFn, bidRequest) { - const adUnits = bidRequest.adUnits || pbGlobal.adUnits; + const adUnits = bidRequest.adUnits || pbGlobal.adUnits || []; adUnits.forEach(adUnit => { const oRtbParams = videoCore.getOrtbParams(adUnit.video.divId); adUnit.mediaTypes.video = Object.assign({}, adUnit.mediaTypes.video, oRtbParams); diff --git a/test/spec/modules/videoModule/pbVideo_spec.js b/test/spec/modules/videoModule/pbVideo_spec.js index 5da936646c3..eba7af9ca97 100644 --- a/test/spec/modules/videoModule/pbVideo_spec.js +++ b/test/spec/modules/videoModule/pbVideo_spec.js @@ -1,26 +1,37 @@ import { expect } from 'chai'; import { PbVideo } from 'modules/videoModule/index.js'; -let ortbParamsMock = { - 'video': {}, - 'content': {} +let ortbParamsMock; +let videoCoreMock; +let getConfigMock; +let requestBidsMock; +let pbGlobalMock; +let pbEventsMock; +let videoEventsMock; + +function resetTestVars() { + ortbParamsMock = { + 'video': {}, + 'content': {} + } + videoCoreMock = { + registerProvider: sinon.spy(), + onEvents: sinon.spy(), + getOrtbParams: () => ortbParamsMock + }; + getConfigMock = () => {}; + requestBidsMock = { + before: sinon.spy() + }; + pbGlobalMock = { + requestBids: requestBidsMock + }; + pbEventsMock = { + emit: sinon.spy(), + on: sinon.spy() + }; + videoEventsMock = []; } -let videoCoreMock = { - registerProvider: sinon.spy(), - getOrtbParams: () => ortbParamsMock -}; -let getConfigMock = () => {}; -let requestBidsMock = { - before: sinon.spy() -}; -let pbGlobalMock = { - requestBids: requestBidsMock -}; -let pbEventsMock = { - emit: sinon.spy(), - on: sinon.spy() -}; -let videoEventsMock = []; let pbVideoFactory = (videoCore, getConfig, pbGlobal, pbEvents, videoEvents) => { const pbVideo = PbVideo( @@ -35,8 +46,30 @@ let pbVideoFactory = (videoCore, getConfig, pbGlobal, pbEvents, videoEvents) => } describe('Prebid Video', function () { - describe('Provider Registration', function () { + beforeEach(() => resetTestVars()); + + describe('Setting video to config', function () { + let providers = [{ divId: 'div1' }, { divId: 'div2' }]; + let getConfigCallback; + let customGetConfig = (video, callback) => { + getConfigCallback = callback; + }; + + beforeEach(() => { + const pbVideo = pbVideoFactory(null, customGetConfig, null, null, null); + getConfigCallback({ video: { providers } }); + }); + it('Should register providers', function () { + expect(videoCoreMock.registerProvider.calledTwice).to.be.true; + }); + + it('Should register events', function () { + expect(videoCoreMock.onEvents.calledTwice).to.be.true; + const onEventsSpy = videoCoreMock.onEvents; + expect(onEventsSpy.getCall(0).args[2]).to.be.equal('div1'); + expect(onEventsSpy.getCall(1).args[2]).to.be.equal('div2'); + }); }); describe('Event Registration', function () { From cc33458b594132c7f860d554046d912152000fc9 Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Tue, 7 Sep 2021 16:43:51 -0400 Subject: [PATCH 11/13] tests events surfacing --- test/spec/modules/videoModule/pbVideo_spec.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test/spec/modules/videoModule/pbVideo_spec.js b/test/spec/modules/videoModule/pbVideo_spec.js index eba7af9ca97..5c52becb7bc 100644 --- a/test/spec/modules/videoModule/pbVideo_spec.js +++ b/test/spec/modules/videoModule/pbVideo_spec.js @@ -70,10 +70,27 @@ describe('Prebid Video', function () { expect(onEventsSpy.getCall(0).args[2]).to.be.equal('div1'); expect(onEventsSpy.getCall(1).args[2]).to.be.equal('div2'); }); + + it('Should emit events off of Prebid\'s Events', function () { + let eventHandler; + const customVideoCore = Object.assign({}, videoCoreMock, { + onEvents: (events, eventHandler_) => eventHandler = eventHandler_ + }); + const pbVideo = pbVideoFactory(customVideoCore, customGetConfig, null, null, null); + getConfigCallback({ video: { providers } }); + const expectedType = 'test_event'; + const expectedPayload = {'test': 'data'}; + eventHandler(expectedType, expectedPayload); + expect(pbEventsMock.emit.calledOnce).to.be.true; + expect(pbEventsMock.emit.getCall(0).args[0]).to.be.equal(expectedType); + expect(pbEventsMock.emit.getCall(0).args[1]).to.be.equal(expectedPayload); + }); }); - describe('Event Registration', function () { + describe('Event triggering', function () { + it('Should emit events off of Prebid\'s Events', function () { + }); }); describe('Ad unit Enrichment', function () { From 2dcc5423380740635f7067cfedb858a37b104155 Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Tue, 7 Sep 2021 16:53:20 -0400 Subject: [PATCH 12/13] nests the event trigger tests --- test/spec/modules/videoModule/pbVideo_spec.js | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/test/spec/modules/videoModule/pbVideo_spec.js b/test/spec/modules/videoModule/pbVideo_spec.js index 5c52becb7bc..10d4c5e494e 100644 --- a/test/spec/modules/videoModule/pbVideo_spec.js +++ b/test/spec/modules/videoModule/pbVideo_spec.js @@ -51,12 +51,12 @@ describe('Prebid Video', function () { describe('Setting video to config', function () { let providers = [{ divId: 'div1' }, { divId: 'div2' }]; let getConfigCallback; - let customGetConfig = (video, callback) => { + let getConfig = (video, callback) => { getConfigCallback = callback; }; beforeEach(() => { - const pbVideo = pbVideoFactory(null, customGetConfig, null, null, null); + pbVideoFactory(null, getConfig); getConfigCallback({ video: { providers } }); }); @@ -71,25 +71,21 @@ describe('Prebid Video', function () { expect(onEventsSpy.getCall(1).args[2]).to.be.equal('div2'); }); - it('Should emit events off of Prebid\'s Events', function () { - let eventHandler; - const customVideoCore = Object.assign({}, videoCoreMock, { - onEvents: (events, eventHandler_) => eventHandler = eventHandler_ + describe('Event triggering', function () { + it('Should emit events off of Prebid\'s Events', function () { + let eventHandler; + const videoCore = Object.assign({}, videoCoreMock, { + onEvents: (events, eventHandler_) => eventHandler = eventHandler_ + }); + pbVideoFactory(videoCore, getConfig); + getConfigCallback({ video: { providers } }); + const expectedType = 'test_event'; + const expectedPayload = {'test': 'data'}; + eventHandler(expectedType, expectedPayload); + expect(pbEventsMock.emit.calledOnce).to.be.true; + expect(pbEventsMock.emit.getCall(0).args[0]).to.be.equal(expectedType); + expect(pbEventsMock.emit.getCall(0).args[1]).to.be.equal(expectedPayload); }); - const pbVideo = pbVideoFactory(customVideoCore, customGetConfig, null, null, null); - getConfigCallback({ video: { providers } }); - const expectedType = 'test_event'; - const expectedPayload = {'test': 'data'}; - eventHandler(expectedType, expectedPayload); - expect(pbEventsMock.emit.calledOnce).to.be.true; - expect(pbEventsMock.emit.getCall(0).args[0]).to.be.equal(expectedType); - expect(pbEventsMock.emit.getCall(0).args[1]).to.be.equal(expectedPayload); - }); - }); - - describe('Event triggering', function () { - it('Should emit events off of Prebid\'s Events', function () { - }); }); @@ -105,7 +101,8 @@ describe('Prebid Video', function () { const requestBids = { before: callback_ => beforeBidRequestCallback = callback_ }; - const pbVideo = pbVideoFactory(null, null, { requestBids }, null); + + const pbVideo = pbVideoFactory(null, null, { requestBids }); expect(beforeBidRequestCallback).to.not.be.undefined; const nextFn = sinon.spy(); const adUnits = [{ @@ -120,6 +117,7 @@ describe('Prebid Video', function () { const adUnit = adUnits[0]; expect(adUnit.mediaTypes.video).to.have.property('video'); expect(adUnit.mediaTypes.video).to.have.property('content'); + expect(nextFn.calledOnce).to.be.true; }); }); From 396158cda73eed037fc18b20cea4f0deb04335f5 Mon Sep 17 00:00:00 2001 From: Karim Mourra Date: Tue, 7 Sep 2021 18:11:02 -0400 Subject: [PATCH 13/13] restores factory --- modules/videoModule/index.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/videoModule/index.js b/modules/videoModule/index.js index 7fca21fbe0c..774704a4c32 100644 --- a/modules/videoModule/index.js +++ b/modules/videoModule/index.js @@ -1,8 +1,8 @@ -// import {config} from '../../src/config.js'; +import {config} from '../../src/config.js'; import events from '../../src/events.js'; import { allVideoEvents } from './constants/events.js'; import CONSTANTS from '../../src/constants.json'; -// import { videoCoreFactory } from './coreVideo.js'; +import { videoCoreFactory } from './coreVideo.js'; events.addEvents(allVideoEvents); @@ -47,11 +47,11 @@ export function PbVideo(videoCore_, getConfig_, pbGlobal_, pbEvents_, videoEvent return { init }; } -// function pbVideoFactory() { -// const videoCore = videoCoreFactory(); -// const pbVideo = PbVideo(videoCore, config.getConfig, $$PREBID_GLOBAL$$, events, allVideoEvents); -// pbVideo.init(); -// return pbVideo; -// } -// -// pbVideoFactory(); +function pbVideoFactory() { + const videoCore = videoCoreFactory(); + const pbVideo = PbVideo(videoCore, config.getConfig, $$PREBID_GLOBAL$$, events, allVideoEvents); + pbVideo.init(); + return pbVideo; +} + +pbVideoFactory();