Files
shaka-player/test/ui/ad_ui_unit.js
T
Sandra Lokshina 8cb5001984 Replace our skip button with the IMA's default one.
According to the agreement with the IMA team, we will
no longer hide their UI during ads. Instead we will
incorporate their elements into our layout.
(Some of the elements they expose are legally required
or business critical for partners for certain types of
ads).
This change replaces our skip button with the IMA one
and tweaks our layout to make it fit better.
We are keeping our ad counter and the 'Ad X of Y'
element.
Our skip button will stay in the library, and we will
use it for other (non IMA) ad integrations.

Change-Id: I648c6c65a34607685a409a264c2a03d74cc4d461
2020-04-22 21:03:11 +00:00

369 lines
11 KiB
JavaScript

/** @license
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
describe('Ad UI', () => {
const UiUtils = shaka.test.UiUtils;
/** @type {!Element} */
let cssLink;
/** @type {!HTMLElement} */
let container;
/** @type {!HTMLMediaElement} */
let video;
/** @type {!shaka.test.FakeAd} */
let ad;
/** @type {!shaka.test.FakeAdManager} */
let adManager;
beforeAll(async () => {
// Add css file
cssLink = document.createElement('link');
await UiUtils.setupCSS(cssLink);
shaka.Player.setAdManagerFactory(() => new shaka.test.FakeAdManager());
});
afterEach(async () => {
await UiUtils.cleanupUI();
});
afterAll(() => {
document.head.removeChild(cssLink);
shaka.Player.setAdManagerFactory(() => new shaka.ads.AdManager());
});
beforeEach(() => {
container =
/** @type {!HTMLElement} */ (document.createElement('div'));
document.body.appendChild(container);
video = shaka.test.UiUtils.createVideoElement();
container.appendChild(video);
UiUtils.createUIThroughAPI(container, video);
adManager = video['ui'].getControls().getPlayer().getAdManager();
});
it('is invisible if no ad is playing', () => {
const adControlsContainer =
UiUtils.getElementByClassName(container, 'shaka-ad-controls');
UiUtils.confirmElementHidden(adControlsContainer);
});
it('becomes visible if an ad is playing', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await p;
const adControlsContainer =
UiUtils.getElementByClassName(container, 'shaka-ad-controls');
UiUtils.confirmElementDisplayed(adControlsContainer);
});
it('hides when an ad is done playing', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const pStart =
waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
const pStop =
waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STOPPED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await pStart;
const adControlsContainer =
UiUtils.getElementByClassName(container, 'shaka-ad-controls');
UiUtils.confirmElementDisplayed(adControlsContainer);
adManager.finishAd();
await pStop;
UiUtils.confirmElementHidden(adControlsContainer);
});
// TODO: Skip button isn't currently used. Re-enable this suit
// once we have other, non-IMA ad integrations.
xdescribe('skip button', () => {
/** @type {!HTMLButtonElement} */
let skipButton;
beforeEach(() => {
skipButton =
/** @type {!HTMLButtonElement} */ (UiUtils.getElementByClassName(
container, 'shaka-skip-ad-button'));
});
it('is invisible if an unskippable ad is playing', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await p;
UiUtils.confirmElementHidden(skipButton);
});
it('becomes visible if a skippable ad is playing', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ 10,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await p;
UiUtils.confirmElementDisplayed(skipButton);
});
it('correctly shows the time until the ad can be skipped', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ 10,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await p;
const skipCounter =
UiUtils.getElementByClassName(container, 'shaka-skip-ad-counter');
UiUtils.confirmElementDisplayed(skipCounter);
expect(skipCounter.textContent).toBe('10');
});
it('is disabled if skip count is greater than 0', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ 10,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await p;
expect(skipButton.disabled).toBe(true);
});
it('is enabled if an ad can be skipped now', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const pStart =
waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
const pSkip = waiter.waitForEvent(
adManager, shaka.ads.AdManager.AD_SKIP_STATE_CHANGED);
ad = new shaka.test.FakeAd(/* skipIn= */ 0,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await pStart;
adManager.changeSkipState();
await pSkip;
expect(skipButton.disabled).toBe(false);
});
it('hides skip counter if an ad can be skipped now', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const pStart =
waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
const pSkip = waiter.waitForEvent(
adManager, shaka.ads.AdManager.AD_SKIP_STATE_CHANGED);
ad = new shaka.test.FakeAd(/* skipIn= */ 10,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await pStart;
const skipCounter =
UiUtils.getElementByClassName(container, 'shaka-skip-ad-counter');
UiUtils.confirmElementDisplayed(skipCounter);
// Set ad to be skippable now
ad.setTimeUntilSkippable(0);
adManager.changeSkipState();
await pSkip;
UiUtils.confirmElementHidden(skipCounter);
});
});
describe('ad counter', () => {
/** @type {!HTMLElement} */
let adCounter;
/** @type {!shaka.ui.Localization} */
let localization;
beforeEach(() => {
adCounter = UiUtils.getElementByClassName(
container, 'shaka-ad-counter-span');
localization = video['ui'].getControls().getLocalization();
});
it('displays correct ad time', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
ad.setRemainingTime(5); // seconds
await p;
// Ad counter has an internal timer that fires every 0.5 sec
// to check the state. Give it a full second to make sure it
// has time to catch up to the new remaining time value.
await shaka.test.Util.delay(1);
const expectedTimeString = '0:05 / 0:10';
const LocIds = shaka.ui.Locales.Ids;
const raw = localization.resolve(LocIds.AD_TIME);
expect(adCounter.textContent).toBe(
raw.replace('[AD_TIME]', expectedTimeString));
});
});
describe('ad position', () => {
/** @type {!HTMLElement} */
let adPosition;
/** @type {!shaka.ui.Localization} */
let localization;
beforeEach(() => {
adPosition = UiUtils.getElementByClassName(
container, 'shaka-ad-position-span');
localization = video['ui'].getControls().getLocalization();
});
it('correctly shows "X of Y ads" for a sequence of several ads',
async () => {
const position = 2;
const adsInPod = 3;
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(
adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ position, /* totalAdsInPod= */ adsInPod);
adManager.startAd(ad);
await p;
const LocIds = shaka.ui.Locales.Ids;
const expectedString = localization.resolve(LocIds.AD_PROGRESS)
.replace('[AD_ON]', String(position))
.replace('[NUM_ADS]', String(adsInPod));
expect(adPosition.textContent).toBe(expectedString);
});
});
describe('timeline', () => {
/** @type {!HTMLElement} */
let seekBar;
/** @type {!HTMLElement} */
let adMarkersBar;
beforeEach(() => {
seekBar = UiUtils.getElementByClassName(
container, 'shaka-seek-bar-container');
adMarkersBar = UiUtils.getElementByClassName(
container, 'shaka-ad-markers');
});
it('dissappears when an ad is playing', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await p;
UiUtils.confirmElementHidden(seekBar);
});
it('ad markers aren\'t displayed if there are no ads', () => {
expect(adMarkersBar.style.background).toBe('');
});
});
describe('overflow menu', () => {
/** @type {!HTMLElement} */
let overflowMenuButton;
beforeEach(() => {
overflowMenuButton = UiUtils.getElementByClassName(
container, 'shaka-overflow-menu-button');
});
it('is hidden when an ad is playing', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const p = waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await p;
UiUtils.confirmElementHidden(overflowMenuButton);
});
it('is displayed when an ad stops playing', async () => {
const eventManager = new shaka.util.EventManager();
const waiter = new shaka.test.Waiter(eventManager);
const pStart =
waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STARTED);
const pStop =
waiter.waitForEvent(adManager, shaka.ads.AdManager.AD_STOPPED);
ad = new shaka.test.FakeAd(/* skipIn= */ null,
/* position= */ 1, /* totalAdsInPod= */ 1);
adManager.startAd(ad);
await pStart;
UiUtils.confirmElementHidden(overflowMenuButton);
adManager.finishAd();
await pStop;
UiUtils.confirmElementDisplayed(overflowMenuButton);
});
});
});