diff --git a/test/ads/interstitial_ad_manager_unit.js b/test/ads/interstitial_ad_manager_unit.js
index 3abb6d9e76..0b0d5cec58 100644
--- a/test/ads/interstitial_ad_manager_unit.js
+++ b/test/ads/interstitial_ad_manager_unit.js
@@ -14,14 +14,18 @@ describe('Interstitial Ad manager', () => {
let adContainer;
/** @type {!shaka.Player} */
let player;
- /** @type {!shaka.test.FakeVideo} */
- let mockVideo;
+ /** @type {!HTMLVideoElement} */
+ let video;
/** @type {!jasmine.Spy} */
let onEventSpy;
/** @type {!shaka.ads.InterstitialAdManager} */
let interstitialAdManager;
beforeEach(() => {
+ // Allows us to use a timer instead of requestVideoFrameCallback
+ // (which doesn't work well in all platform tests)
+ spyOn(shaka.util.Platform, 'isSmartTV').and.returnValue(true);
+
function dependencyInjector(player) {
// Create a networking engine that always returns an empty buffer.
networkingEngine = new shaka.test.FakeNetworkingEngine();
@@ -32,10 +36,15 @@ describe('Interstitial Ad manager', () => {
adContainer =
/** @type {!HTMLElement} */ (document.createElement('div'));
player = new shaka.Player(null, null, dependencyInjector);
- mockVideo = new shaka.test.FakeVideo();
+ video = shaka.test.UiUtils.createVideoElement();
onEventSpy = jasmine.createSpy('onEvent');
interstitialAdManager = new shaka.ads.InterstitialAdManager(
- adContainer, player, mockVideo, shaka.test.Util.spyFunc(onEventSpy));
+ adContainer, player, video, shaka.test.Util.spyFunc(onEventSpy));
+ const config = shaka.util.PlayerConfiguration.createDefault().ads;
+ // We always support multiple video elements so that we can properly
+ // control timing in unit tests.
+ config.supportsMultipleMediaElements = true;
+ interstitialAdManager.configure(config);
});
afterEach(async () => {
@@ -1063,20 +1072,171 @@ describe('Interstitial Ad manager', () => {
expect(onEventSpy).toHaveBeenCalledWith(
jasmine.objectContaining(eventValue1));
});
+
+ it('ignore empty', async () => {
+ const vmap = [
+ '',
+ '',
+ '',
+ ].join('');
+
+ networkingEngine.setResponseText('test:/vmap', vmap);
+
+ await interstitialAdManager.addAdUrlInterstitial('test:/vmap');
+
+ expect(onEventSpy).not.toHaveBeenCalled();
+ });
+ });
+
+ it('plays pre-roll correctly', async () => {
+ const metadata = {
+ startTime: 0,
+ endTime: null,
+ values: [
+ {
+ key: 'ID',
+ data: 'PREROLL',
+ },
+ {
+ key: 'CUE',
+ data: 'PRE',
+ },
+ {
+ key: 'X-ASSET-URI',
+ data: 'test.m3u8',
+ },
+ {
+ key: 'X-RESTRICT',
+ data: 'SKIP,JUMP',
+ },
+ ],
+ };
+ await interstitialAdManager.addMetadata(metadata);
+
+ video.dispatchEvent(new Event('timeupdate'));
+
+ await shaka.test.Util.shortDelay();
+
+ expect(onEventSpy).toHaveBeenCalledTimes(2);
+ const eventValue1 = {
+ type: 'ad-cue-points-changed',
+ cuepoints: [
+ {
+ start: 0,
+ end: null,
+ },
+ ],
+ };
+ expect(onEventSpy).toHaveBeenCalledWith(
+ jasmine.objectContaining(eventValue1));
+ const eventValue2 = {
+ type: 'ad-started',
+ };
+ expect(onEventSpy).toHaveBeenCalledWith(
+ jasmine.objectContaining(eventValue2));
});
- it('ignore empty', async () => {
- const vmap = [
- '',
- '',
- '',
- ].join('');
+ it('dispatch skip event correctly', async () => {
+ const metadata = {
+ startTime: 0,
+ endTime: null,
+ values: [
+ {
+ key: 'ID',
+ data: 'PREROLL',
+ },
+ {
+ key: 'CUE',
+ data: 'PRE',
+ },
+ {
+ key: 'X-ASSET-URI',
+ data: 'test.m3u8',
+ },
+ ],
+ };
+ await interstitialAdManager.addMetadata(metadata);
+
+ video.dispatchEvent(new Event('timeupdate'));
+
+ await shaka.test.Util.shortDelay();
+
+ expect(onEventSpy).toHaveBeenCalledTimes(3);
+ const eventValue1 = {
+ type: 'ad-cue-points-changed',
+ cuepoints: [
+ {
+ start: 0,
+ end: null,
+ },
+ ],
+ };
+ expect(onEventSpy).toHaveBeenCalledWith(
+ jasmine.objectContaining(eventValue1));
+ const eventValue2 = {
+ type: 'ad-started',
+ };
+ expect(onEventSpy).toHaveBeenCalledWith(
+ jasmine.objectContaining(eventValue2));
+ const eventValue3 = {
+ type: 'ad-skip-state-changed',
+ };
+ expect(onEventSpy).toHaveBeenCalledWith(
+ jasmine.objectContaining(eventValue3));
+ });
+
+ it('jumping a mid-roll with JUMP restriction is not allowed', async () => {
+ const metadata = {
+ startTime: 10,
+ endTime: null,
+ values: [
+ {
+ key: 'ID',
+ data: 'MIDROLL',
+ },
+ {
+ key: 'X-ASSET-URI',
+ data: 'test.m3u8',
+ },
+ {
+ key: 'X-RESTRICT',
+ data: 'SKIP,JUMP',
+ },
+ ],
+ };
+ await interstitialAdManager.addMetadata(metadata);
- networkingEngine.setResponseText('test:/vmap', vmap);
+ video.currentTime = 0;
+ video.dispatchEvent(new Event('timeupdate'));
+
+ await shaka.test.Util.shortDelay();
+
+ expect(onEventSpy).toHaveBeenCalledTimes(1);
+ const eventValue1 = {
+ type: 'ad-cue-points-changed',
+ cuepoints: [
+ {
+ start: 10,
+ end: null,
+ },
+ ],
+ };
+ expect(onEventSpy).toHaveBeenCalledWith(
+ jasmine.objectContaining(eventValue1));
- await interstitialAdManager.addAdUrlInterstitial('test:/vmap');
+ video.currentTime = 20;
+ video.dispatchEvent(new Event('timeupdate'));
- expect(onEventSpy).not.toHaveBeenCalled();
+ await shaka.test.Util.delay(0.25);
+
+ if (video.currentTime == 20) {
+ expect(onEventSpy).toHaveBeenCalledTimes(2);
+ const eventValue2 = {
+ type: 'ad-started',
+ };
+ expect(onEventSpy).toHaveBeenCalledWith(
+ jasmine.objectContaining(eventValue2));
+ }
});
});