From 83a420f066d2bc429afeccdc230b58f4152fcfdb Mon Sep 17 00:00:00 2001 From: theodab Date: Fri, 23 Sep 2022 00:50:17 -0700 Subject: [PATCH] test: Add additional test for ads (#4501) Issue #4481 --- test/ads/ad_manager_unit.js | 209 +++++++++++++++++++++++++++++++----- 1 file changed, 180 insertions(+), 29 deletions(-) diff --git a/test/ads/ad_manager_unit.js b/test/ads/ad_manager_unit.js index d2c58a81ac..edcfc3fa9b 100644 --- a/test/ads/ad_manager_unit.js +++ b/test/ads/ad_manager_unit.js @@ -25,45 +25,156 @@ describe('Ad manager', () => { /** @type {!HTMLElement} */ (document.createElement('div')); }); - it('doesn\'t init CS if CS IMA is missing', () => { - const error = createError( - shaka.util.Error.Severity.CRITICAL, - shaka.util.Error.Code.CS_IMA_SDK_MISSING); + describe('client side', () => { + it('doesn\'t init if CS IMA is missing', () => { + const error = createError( + shaka.util.Error.Severity.CRITICAL, + shaka.util.Error.Code.CS_IMA_SDK_MISSING); - expect(() => adManager.initClientSide( - adContainer, mockVideo)).toThrow(error); - }); + expect(() => adManager.initClientSide( + adContainer, mockVideo)).toThrow(error); + }); - it('doesn\'t init SS if SS IMA is missing', () => { - const error = createError( - shaka.util.Error.Severity.CRITICAL, - shaka.util.Error.Code.SS_IMA_SDK_MISSING); + it('doesn\'t request ads until CS is initialized', () => { + setupFakeIMA(); + const error = createError( + shaka.util.Error.Severity.RECOVERABLE, + shaka.util.Error.Code.CS_AD_MANAGER_NOT_INITIALIZED); - expect(() => adManager.initServerSide( - adContainer, mockVideo)).toThrow(error); - }); + const request = new google.ima.AdsRequest(); + request.adTagUrl = 'fakeTag'; + + expect(() => adManager.requestClientSideAds(request)).toThrow(error); + }); + + it('doesn\'t request ads if CS events return no ad', () => { + setupFakeIMA(); + + const request = new google.ima.AdsRequest(); + request.adTagUrl = 'fakeTag'; + + /** @type {google.ima.AdsLoader} */ + let mockAdsLoaderInstance; + let numAdsRequested = 0; + /** @type {google.ima.AdsManager} */ + let mockAdsManagerInstance; + /** @type {Event} */ + let loadEvent; + /** @type {Event} */ + let startedEventA; + /** @type {Event} */ + let startedEventB; + + /** @suppress {invalidCasts} */ + function makeMocks() { + const mockAdsLoader = class extends shaka.util.FakeEventTarget { + constructor(container) { + super(); + mockAdsLoaderInstance = /** @type {!google.ima.AdsLoader} */ (this); + } + + getSettings() { + return { + setPlayerType: (type) => {}, + setPlayerVersion: (version) => {}, + }; + } - it('doesn\'t request CS ads until CS is initialized', () => { - setupFakeIMA(); - const error = createError( - shaka.util.Error.Severity.RECOVERABLE, - shaka.util.Error.Code.CS_AD_MANAGER_NOT_INITIALIZED); + requestAds(imaRequest) { + numAdsRequested += 1; + } + }; + window['google'].ima.AdsLoader = mockAdsLoader; - const request = new google.ima.AdsRequest(); - request.adTagUrl = 'fakeTag'; + loadEvent = /** @type {!google.ima.AdsManagerLoadedEvent} */ ( + new shaka.util.FakeEvent( + google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED)); + loadEvent.getAdsManager = () => { + const MockAdManager = class extends shaka.util.FakeEventTarget { + constructor() { + super(); + mockAdsManagerInstance = + /** @type {!google.ima.AdsManager} */ (this); + } - expect(() => adManager.requestClientSideAds(request)).toThrow(error); + getCuePoints() { + return []; + } + + getVolume() { + return 0; + } + }; + return new MockAdManager(); + }; + startedEventA = /** @type {!google.ima.AdEvent} */ ( + new shaka.util.FakeEvent(google.ima.AdEvent.Type.STARTED)); + startedEventA.getAd = () => { + return null; + }; + startedEventB = /** @type {!google.ima.AdEvent} */ ( + new shaka.util.FakeEvent(google.ima.AdEvent.Type.STARTED)); + startedEventB.getAd = () => { + return {}; + }; + } + makeMocks(); + + // Set up event listeners. + const eventManager = new shaka.util.EventManager(); + let loaded = false; + let numAdStarted = 0; + const AdManager = shaka.ads.AdManager; + eventManager.listen(adManager, AdManager.IMA_AD_MANAGER_LOADED, () => { + loaded = true; + }); + eventManager.listen(adManager, AdManager.AD_STARTED, () => { + numAdStarted += 1; + }); + + // Set up the ad manager. + adManager.initClientSide(adContainer, mockVideo); + goog.asserts.assert(loadEvent != null, 'loadEvent exists'); + mockAdsLoaderInstance.dispatchEvent(/** @type {!Event} */ (loadEvent)); + expect(loaded).toBe(true); + + // Request an ad, but create an event with no ad. + adManager.requestClientSideAds(request); + expect(numAdsRequested).toBe(1); + mockAdsManagerInstance.dispatchEvent(/** @type {!Event} */ ( + startedEventA)); + expect(numAdStarted).toBe(0); + + // Request another ad. This time, the IMA event has an ad, so the ad + // manager should fire a started event. + adManager.requestClientSideAds(request); + expect(numAdsRequested).toBe(2); + mockAdsManagerInstance.dispatchEvent(/** @type {!Event} */ ( + startedEventB)); + expect(numAdStarted).toBe(1); + }); }); - it('doesn\'t request SS streams until SS is initialized', () => { - setupFakeIMA(); - const error = createError( - shaka.util.Error.Severity.RECOVERABLE, - shaka.util.Error.Code.SS_AD_MANAGER_NOT_INITIALIZED); + describe('server side', () => { + it('doesn\'t init if SS IMA is missing', () => { + const error = createError( + shaka.util.Error.Severity.CRITICAL, + shaka.util.Error.Code.SS_IMA_SDK_MISSING); + + expect(() => adManager.initServerSide( + adContainer, mockVideo)).toThrow(error); + }); + + it('doesn\'t request streams until SS is initialized', () => { + setupFakeIMA(); + const error = createError( + shaka.util.Error.Severity.RECOVERABLE, + shaka.util.Error.Code.SS_AD_MANAGER_NOT_INITIALIZED); - const request = new google.ima.dai.api.StreamRequest(); + const request = new google.ima.dai.api.StreamRequest(); - expect(() => adManager.requestServerSideStream(request)).toThrow(error); + expect(() => adManager.requestServerSideStream(request)).toThrow(error); + }); }); /** @@ -86,5 +197,45 @@ describe('Ad manager', () => { window['google'].ima.AdsRequest = class {}; window['google'].ima.dai.api = {}; window['google'].ima.dai.api.StreamRequest = class {}; + window['google'].ima.settings = {}; + window['google'].ima.settings.setLocale = (locale) => {}; + window['google'].ima.AdsManagerLoadedEvent = {}; + window['google'].ima.AdsManagerLoadedEvent.Type = { + ADS_MANAGER_LOADED: 'ADS_MANAGER_LOADED', + }; + window['google'].ima.AdErrorEvent = {}; + window['google'].ima.AdErrorEvent.Type = { + AD_ERROR: 'AD_ERROR', + }; + window['google'].ima.AdEvent = {}; + window['google'].ima.AdEvent.Type = { + CONTENT_PAUSE_REQUESTED: 'CONTENT_PAUSE_REQUESTED', + STARTED: 'STARTED', + FIRST_QUARTILE: 'FIRST_QUARTILE', + MIDPOINT: 'MIDPOINT', + THIRD_QUARTILE: 'THIRD_QUARTILE', + COMPLETE: 'COMPLETE', + CONTENT_RESUME_REQUESTED: 'CONTENT_RESUME_REQUESTED', + ALL_ADS_COMPLETED: 'ALL_ADS_COMPLETED', + SKIPPED: 'SKIPPED', + VOLUME_CHANGED: 'VOLUME_CHANGED', + VOLUME_MUTED: 'VOLUME_MUTED', + PAUSED: 'PAUSED', + RESUMED: 'RESUMED', + SKIPPABLE_STATE_CHANGED: 'SKIPPABLE_STATE_CHANGED', + CLICK: 'CLICK', + AD_PROGRESS: 'AD_PROGRESS', + AD_BUFFERING: 'AD_BUFFERING', + IMPRESSION: 'IMPRESSION', + DURATION_CHANGE: 'DURATION_CHANGE', + USER_CLOSE: 'USER_CLOSE', + LOADED: 'LOADED', + LINEAR_CHANGED: 'LINEAR_CHANGED', + AD_METADATA: 'AD_METADATA', + LOG: 'LOG', + AD_BREAK_READY: 'AD_BREAK_READY', + INTERACTION: 'INTERACTION', + }; + window['google'].ima.AdDisplayContainer = class { initialize() {} }; } });