mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-04 10:19:24 +02:00
1081 lines
35 KiB
JavaScript
1081 lines
35 KiB
JavaScript
import QUnit from 'qunit';
|
|
import sinon from 'sinon';
|
|
import videojs from 'video.js';
|
|
import sharedModuleHooks from './lib/shared-module-hooks.js';
|
|
|
|
QUnit.module('Contrib Ads', sharedModuleHooks());
|
|
|
|
QUnit.test('begins in BeforePreroll', function(assert) {
|
|
assert.equal(this.player.ads._state.constructor.name, 'BeforePreroll');
|
|
});
|
|
|
|
QUnit.test('adstart is fired before a preroll', function(assert) {
|
|
const spy = sinon.spy();
|
|
|
|
assert.expect(1);
|
|
|
|
this.player.on('adstart', spy);
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(spy.callCount, 1, 'a preroll triggers adstart');
|
|
});
|
|
|
|
QUnit.test('player has the .vjs-has-started class once a preroll begins', function(assert) {
|
|
assert.expect(1);
|
|
this.player.trigger('adsready');
|
|
|
|
// This is a bit of a hack in order to not need the test to be async.
|
|
this.player.tech_.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.ok(this.player.hasClass('vjs-has-started'), 'player has .vjs-has-started class');
|
|
});
|
|
|
|
QUnit.test('calls start immediately on play when ads are ready', function(assert) {
|
|
const readyForPrerollSpy = sinon.spy();
|
|
|
|
assert.expect(1);
|
|
|
|
this.player.on('readyforpreroll', readyForPrerollSpy);
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('play');
|
|
assert.strictEqual(readyForPrerollSpy.callCount, 1, 'readyforpreroll was fired');
|
|
});
|
|
|
|
QUnit.test('adds the ad-mode class when a preroll plays', function(assert) {
|
|
assert.expect(1);
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
const el = this.player.el();
|
|
|
|
assert.ok(this.player.hasClass('vjs-ad-playing'), 'the ad class should be in "' + el.className + '"');
|
|
});
|
|
|
|
QUnit.test('removes the ad-mode class when a preroll finishes', function(assert) {
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
this.player.ads.endLinearAdMode();
|
|
const el = this.player.el();
|
|
|
|
assert.notOk(this.player.hasClass('vjs-ad-playing'), 'the ad class should not be in "' + el.className + '"');
|
|
|
|
this.player.trigger('playing');
|
|
});
|
|
|
|
QUnit.test('adds a class while waiting for an ad plugin to load', function(assert) {
|
|
assert.expect(1);
|
|
|
|
this.player.trigger('play');
|
|
const el = this.player.el();
|
|
|
|
assert.ok(this.player.hasClass('vjs-ad-loading'), 'the ad loading class should be in "' + el.className + '"');
|
|
});
|
|
|
|
QUnit.test('adds a class while waiting for a preroll', function(assert) {
|
|
assert.expect(1);
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
const el = this.player.el();
|
|
|
|
assert.ok(this.player.hasClass('vjs-ad-loading'), 'the ad loading class should be in "' + el.className + '"');
|
|
});
|
|
|
|
QUnit.test('removes the loading class when the preroll begins', function(assert) {
|
|
assert.expect(1);
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
this.player.trigger('ads-ad-started');
|
|
const el = this.player.el();
|
|
|
|
assert.notOk(this.player.hasClass('vjs-ad-loading'), 'there should be no ad loading class present in "' + el.className + '"');
|
|
});
|
|
|
|
QUnit.test('removes the loading class when the preroll times out', function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adtimeout');
|
|
this.player.trigger('playing');
|
|
const el = this.player.el();
|
|
|
|
assert.notOk(this.player.hasClass('vjs-ad-loading'), 'there should be no ad loading class present in "' + el.className + '"');
|
|
});
|
|
|
|
QUnit.test('begins resuming to content if there is no preroll', function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.clock.tick(1);
|
|
this.player.trigger('adtimeout');
|
|
|
|
assert.strictEqual(this.player.ads.inAdBreak(), false, 'should not be in an ad break');
|
|
assert.strictEqual(this.player.ads.isContentResuming(), true, 'should be resuming content');
|
|
assert.strictEqual(this.player.ads.isInAdMode(), true, 'should be in ad mode');
|
|
});
|
|
|
|
QUnit.test('removes the poster attribute so it does not flash between videos', function(assert) {
|
|
this.video.poster = 'http://www.videojs.com/img/poster.jpg';
|
|
assert.ok(this.video.poster, 'the poster is present initially');
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(this.video.poster, '', 'poster is removed');
|
|
});
|
|
|
|
QUnit.test('changing the src triggers "contentupdate"', function(assert) {
|
|
const spy = sinon.spy();
|
|
|
|
assert.expect(1);
|
|
|
|
this.player.on('contentupdate', spy);
|
|
|
|
// set src and trigger synthetic 'loadstart'
|
|
this.player.currentSrc = () => 'AH HA!!! I AM NOT A REAL SOURCE';
|
|
this.player.trigger('loadstart');
|
|
assert.strictEqual(spy.callCount, 1, 'one contentupdate event fired');
|
|
});
|
|
|
|
QUnit.test('"contentupdate" should fire when src is changed after postroll', function(assert) {
|
|
const contentupdateSpy = sinon.spy();
|
|
|
|
this.player.on('contentupdate', contentupdateSpy);
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adtimeout');
|
|
this.player.trigger('ended');
|
|
this.player.trigger('adtimeout');
|
|
|
|
// set src and trigger synthetic 'loadstart'
|
|
this.player.src({
|
|
src: 'http://vjs.zencdn.net/v/oceans.webm',
|
|
type: 'video/webm'
|
|
});
|
|
this.player.trigger('loadstart');
|
|
assert.strictEqual(contentupdateSpy.callCount, 1, 'one contentupdate event fired');
|
|
});
|
|
|
|
QUnit.test('"contentupdate" should fire when src is changed after postroll', function(assert) {
|
|
const contentupdateSpy = sinon.spy();
|
|
|
|
this.player.on('contentupdate', contentupdateSpy);
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adtimeout');
|
|
this.player.trigger('ended');
|
|
this.player.trigger('adtimeout');
|
|
this.player.trigger('ended');
|
|
|
|
// set src and trigger synthetic 'loadstart'
|
|
this.player.src({
|
|
src: 'http://vjs.zencdn.net/v/oceans.webm',
|
|
type: 'video/webm'
|
|
});
|
|
this.player.trigger('loadstart');
|
|
assert.strictEqual(contentupdateSpy.callCount, 1, 'one contentupdate event fired');
|
|
});
|
|
|
|
QUnit.test('changing src does not trigger "contentupdate" during ad playback', function(assert) {
|
|
const spy = sinon.spy();
|
|
|
|
this.player.on('contentupdate', spy);
|
|
|
|
// enter ad playback mode
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
|
|
// set src and trigger synthetic 'loadstart'
|
|
this.player.src({
|
|
src: 'http://vjs.zencdn.net/v/oceans.webm',
|
|
type: 'video/webm'
|
|
});
|
|
this.player.trigger('loadstart');
|
|
|
|
// finish playing ad
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(spy.callCount, 0, 'no contentupdate events fired');
|
|
});
|
|
|
|
QUnit.test('the `_playRequested` flag is set on the first play request', function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
assert.strictEqual(
|
|
this.player.ads._playRequested, false,
|
|
'initially set to false'
|
|
);
|
|
assert.strictEqual(
|
|
this.player.ads.isInAdMode(), false,
|
|
'starts in a content state'
|
|
);
|
|
|
|
this.player.trigger('play');
|
|
assert.strictEqual(
|
|
this.player.ads._playRequested, true,
|
|
'_playRequested is now true'
|
|
);
|
|
assert.strictEqual(
|
|
this.player.ads.isInAdMode(), true,
|
|
'now in ad state'
|
|
);
|
|
});
|
|
|
|
QUnit.test('ended event happens after postroll errors out', function(assert) {
|
|
const endedSpy = sinon.spy();
|
|
|
|
this.player.on('ended', endedSpy);
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adtimeout');
|
|
// Entered content
|
|
this.player.trigger('playing');
|
|
this.player.trigger('ended');
|
|
this.player.trigger('adserror');
|
|
|
|
this.clock.tick(1);
|
|
assert.strictEqual(endedSpy.callCount, 1, 'ended event happened');
|
|
});
|
|
|
|
QUnit.test('ended event happens after postroll timed out', function(assert) {
|
|
const endedSpy = sinon.spy();
|
|
|
|
this.player.on('ended', endedSpy);
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adtimeout');
|
|
// Entered content
|
|
this.player.trigger('playing');
|
|
this.player.trigger('ended');
|
|
this.player.trigger('adtimeout');
|
|
|
|
this.clock.tick(1);
|
|
assert.strictEqual(endedSpy.callCount, 1, 'ended event happened');
|
|
});
|
|
|
|
QUnit.test('ended event happens after postroll skipped', function(assert) {
|
|
const endedSpy = sinon.spy();
|
|
|
|
this.player.on('ended', endedSpy);
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
// preroll times out
|
|
this.player.trigger('adtimeout');
|
|
// Entered content
|
|
this.player.trigger('playing');
|
|
// content ends
|
|
this.player.trigger('ended');
|
|
this.player.ads.skipLinearAdMode();
|
|
|
|
this.clock.tick(1);
|
|
assert.strictEqual(endedSpy.callCount, 1, 'ended event happened');
|
|
});
|
|
|
|
QUnit.test('an "ended" event is fired after postroll if not fired naturally', function(assert) {
|
|
const endedSpy = sinon.spy();
|
|
|
|
this.player.on('ended', endedSpy);
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
// skip preroll
|
|
this.player.trigger('adtimeout');
|
|
// return to content
|
|
this.player.trigger('playing');
|
|
// handled by redispatch
|
|
this.player.trigger('ended');
|
|
|
|
assert.strictEqual(endedSpy.callCount, 0, 'no ended event before postroll');
|
|
|
|
// start postroll
|
|
this.player.ads.startLinearAdMode();
|
|
this.player.ads.endLinearAdMode();
|
|
this.player.trigger('resumeended');
|
|
assert.strictEqual(endedSpy.callCount, 1, 'ended event happened');
|
|
});
|
|
|
|
QUnit.test('ended events when content ends first and second time', function(assert) {
|
|
const endedSpy = sinon.spy();
|
|
|
|
this.player.on('ended', endedSpy);
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
// Preroll times out
|
|
this.player.trigger('adtimeout');
|
|
// Entered content
|
|
this.player.trigger('playing');
|
|
// Triggers readyforpostroll
|
|
this.player.trigger('ended');
|
|
|
|
// Postroll starts
|
|
this.player.ads.startLinearAdMode();
|
|
this.player.ads.endLinearAdMode();
|
|
this.player.trigger('resumeended');
|
|
|
|
assert.strictEqual(endedSpy.callCount, 1, 'ended event after postroll');
|
|
|
|
this.player.trigger('ended');
|
|
assert.strictEqual(endedSpy.callCount, 2, 'ended event after ads done');
|
|
});
|
|
|
|
QUnit.test('endLinearAdMode during ad break triggers adend', function(assert) {
|
|
const adendSpy = sinon.spy();
|
|
|
|
this.player.on('adend', adendSpy);
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
|
|
assert.strictEqual(adendSpy.callCount, 0, 'no adend yet');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
|
|
assert.strictEqual(adendSpy.callCount, 1, 'adend happened');
|
|
});
|
|
|
|
QUnit.test('calling startLinearAdMode() when already in ad-playback does not trigger adstart', function(assert) {
|
|
const spy = sinon.spy();
|
|
|
|
this.player.on('adstart', spy);
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(spy.callCount, 1, 'adstart should have fired');
|
|
|
|
// add an extraneous start call
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(spy.callCount, 1, 'adstart should not have fired');
|
|
|
|
// make sure subsequent adstarts trigger again on exit/re-enter
|
|
this.player.ads.endLinearAdMode();
|
|
this.player.trigger('playing');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(spy.callCount, 2, 'adstart should have fired');
|
|
});
|
|
|
|
QUnit.test('calling endLinearAdMode() outside of linear ad mode does not trigger adend', function(assert) {
|
|
const adendSpy = sinon.spy();
|
|
|
|
this.player.on('adend', adendSpy);
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(adendSpy.callCount, 0, 'adend should not have fired right away');
|
|
|
|
this.player.trigger('adsready');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(adendSpy.callCount, 0, 'adend should not have fired after adsready');
|
|
|
|
this.player.trigger('play');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(adendSpy.callCount, 0, 'adend should not have fired after play');
|
|
|
|
this.player.trigger('adtimeout');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(adendSpy.callCount, 0, 'adend should not have fired after adtimeout');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(adendSpy.callCount, 1, 'adend should have fired after preroll');
|
|
});
|
|
|
|
QUnit.test('skipLinearAdMode during ad playback does not trigger adskip', function(assert) {
|
|
const adskipSpy = sinon.spy();
|
|
|
|
this.player.on('adskip', adskipSpy);
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
|
|
this.player.ads.skipLinearAdMode();
|
|
assert.strictEqual(
|
|
adskipSpy.callCount, 0,
|
|
'adskip event should not trigger when skipLinearAdMode is called during an ad'
|
|
);
|
|
});
|
|
|
|
QUnit.test('adsready in content-playback triggers readyforpreroll', function(assert) {
|
|
const spy = sinon.spy();
|
|
|
|
this.player.on('readyforpreroll', spy);
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adtimeout');
|
|
// entered ContentPlayback
|
|
this.player.trigger('playing');
|
|
this.player.trigger('adsready');
|
|
assert.strictEqual(spy.callCount, 1, 'readyforpreroll should have been triggered.');
|
|
});
|
|
|
|
QUnit.test('adsready while preroll content resuming triggers readyforpreroll', function(assert) {
|
|
const spy = sinon.spy();
|
|
|
|
this.player.on('readyforpreroll', spy);
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adtimeout');
|
|
assert.strictEqual(this.player.ads.isContentResuming(), true, 'should be resuming to content');
|
|
this.player.trigger('adsready');
|
|
assert.strictEqual(spy.callCount, 1, 'readyforpreroll should have been triggered.');
|
|
});
|
|
|
|
// ----------------------------------
|
|
// Event prefixing during ad playback
|
|
// ----------------------------------
|
|
|
|
QUnit.test('player events during prerolls are prefixed if tech is reused for ad', function(assert) {
|
|
const sawLoadstart = sinon.spy();
|
|
const sawPlaying = sinon.spy();
|
|
const sawPause = sinon.spy();
|
|
const sawEnded = sinon.spy();
|
|
const sawFirstplay = sinon.spy();
|
|
const sawLoadedalldata = sinon.spy();
|
|
const sawAdloadstart = sinon.spy();
|
|
const sawAdpause = sinon.spy();
|
|
const sawAdended = sinon.spy();
|
|
const sawAdfirstplay = sinon.spy();
|
|
const sawAdloadedalldata = sinon.spy();
|
|
|
|
// play a preroll
|
|
this.player.on('readyforpreroll', function() {
|
|
this.ads.startLinearAdMode();
|
|
});
|
|
|
|
this.player.trigger('play');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
|
|
this.player.ads.snapshot = {
|
|
currentSrc: 'something'
|
|
};
|
|
|
|
// simulate video events that should be prefixed
|
|
this.player.on('loadstart', sawLoadstart);
|
|
this.player.on('playing', sawPlaying);
|
|
this.player.on('pause', sawPause);
|
|
this.player.on('ended', sawEnded);
|
|
this.player.on('firstplay', sawFirstplay);
|
|
this.player.on('loadedalldata', sawLoadedalldata);
|
|
this.player.on('adloadstart', sawAdloadstart);
|
|
this.player.on('adpause', sawAdpause);
|
|
this.player.on('adended', sawAdended);
|
|
this.player.on('adfirstplay', sawAdfirstplay);
|
|
this.player.on('adloadedalldata', sawAdloadedalldata);
|
|
this.player.trigger('firstplay');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('playing');
|
|
this.player.trigger('loadedalldata');
|
|
this.player.trigger('pause');
|
|
this.player.trigger('ended');
|
|
assert.strictEqual(sawLoadstart.callCount, 0, 'no loadstart fired');
|
|
assert.strictEqual(sawPlaying.callCount, 0, 'no playing fired');
|
|
assert.strictEqual(sawPause.callCount, 0, 'no pause fired');
|
|
assert.strictEqual(sawEnded.callCount, 0, 'no ended fired');
|
|
assert.strictEqual(sawFirstplay.callCount, 0, 'no firstplay fired');
|
|
assert.strictEqual(sawLoadedalldata.callCount, 0, 'no loadedalldata fired');
|
|
assert.strictEqual(sawAdloadstart.callCount, 1, 'adloadstart fired');
|
|
assert.strictEqual(sawAdpause.callCount, 1, 'adpause fired');
|
|
assert.strictEqual(sawAdended.callCount, 1, 'adended fired');
|
|
assert.strictEqual(sawAdfirstplay.callCount, 1, 'adfirstplay fired');
|
|
assert.strictEqual(sawAdloadedalldata.callCount, 1, 'adloadedalldata fired');
|
|
});
|
|
|
|
QUnit.test('player events during midrolls are prefixed if tech is reused for ad', function(assert) {
|
|
assert.expect(2);
|
|
|
|
const prefixed = sinon.spy();
|
|
const unprefixed = sinon.spy();
|
|
|
|
// play a midroll
|
|
this.player.trigger('play');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('adtimeout');
|
|
// return to content
|
|
this.player.trigger('playing');
|
|
this.player.ads.startLinearAdMode();
|
|
|
|
this.player.ads.snapshot = {
|
|
currentSrc: 'something'
|
|
};
|
|
|
|
// simulate video events that should be prefixed
|
|
this.player.on(['loadstart', 'playing', 'pause', 'ended', 'firstplay', 'loadedalldata'], unprefixed);
|
|
this.player.on(['adloadstart', 'adpause', 'adended', 'adfirstplay', 'adloadedalldata'], prefixed);
|
|
this.player.trigger('firstplay');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('playing');
|
|
this.player.trigger('loadedalldata');
|
|
this.player.trigger('pause');
|
|
this.player.trigger('ended');
|
|
assert.strictEqual(unprefixed.callCount, 0, 'no unprefixed events fired');
|
|
assert.strictEqual(prefixed.callCount, 5, 'prefixed events fired');
|
|
});
|
|
|
|
QUnit.test('player events during postrolls are prefixed if tech is reused for ad', function(assert) {
|
|
assert.expect(2);
|
|
|
|
const prefixed = sinon.spy();
|
|
const unprefixed = sinon.spy();
|
|
|
|
// play a postroll
|
|
this.player.trigger('play');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('adtimeout');
|
|
// return to content
|
|
this.player.trigger('playing');
|
|
this.player.trigger('ended');
|
|
this.player.ads.startLinearAdMode();
|
|
|
|
this.player.ads.snapshot = {
|
|
currentSrc: 'something'
|
|
};
|
|
|
|
// simulate video events that should be prefixed
|
|
this.player.on(['loadstart', 'playing', 'pause', 'ended', 'firstplay', 'loadedalldata'], unprefixed);
|
|
this.player.on(['adloadstart', 'adpause', 'adended', 'adfirstplay', 'adloadedalldata'], prefixed);
|
|
this.player.trigger('firstplay');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('playing');
|
|
this.player.trigger('loadedalldata');
|
|
this.player.trigger('pause');
|
|
this.player.trigger('ended');
|
|
assert.strictEqual(unprefixed.callCount, 0, 'no unprefixed events fired');
|
|
assert.strictEqual(prefixed.callCount, 5, 'prefixed events fired');
|
|
});
|
|
|
|
QUnit.test('player events during stitched ads are prefixed', function(assert) {
|
|
assert.expect(2);
|
|
|
|
const prefixed = sinon.spy();
|
|
const unprefixed = sinon.spy();
|
|
|
|
this.player.ads.stitchedAds(true);
|
|
|
|
// play a midroll
|
|
this.player.trigger('play');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('adtimeout');
|
|
this.player.trigger('playing');
|
|
this.player.ads.startLinearAdMode();
|
|
|
|
// simulate video events that should be prefixed
|
|
this.player.on(['loadstart', 'playing', 'pause', 'ended', 'firstplay', 'loadedalldata'], unprefixed);
|
|
this.player.on(['adloadstart', 'adplaying', 'adpause', 'adended', 'adfirstplay', 'adloadedalldata'], prefixed);
|
|
this.player.trigger('firstplay');
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('playing');
|
|
this.player.trigger('loadedalldata');
|
|
this.player.trigger('pause');
|
|
this.player.trigger('ended');
|
|
assert.strictEqual(unprefixed.callCount, 0, 'no unprefixed events fired');
|
|
assert.strictEqual(prefixed.callCount, 6, 'prefixed events fired');
|
|
});
|
|
|
|
QUnit.test('player events during content playback are not prefixed', function(assert) {
|
|
assert.expect(3);
|
|
|
|
const prefixed = sinon.spy();
|
|
const unprefixed = sinon.spy();
|
|
|
|
// play content
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('adtimeout');
|
|
this.player.trigger('playing');
|
|
this.player.trigger('loadedalldata');
|
|
|
|
// simulate video events that should not be prefixed
|
|
this.player.on(['seeked', 'playing', 'pause', 'ended', 'firstplay', 'loadedalldata'], unprefixed);
|
|
this.player.on(['adseeked', 'adplaying', 'adpause', 'adended', 'contentended', 'adfirstplay', 'adloadedalldata'], prefixed);
|
|
this.player.trigger('firstplay');
|
|
this.player.trigger('seeked');
|
|
this.player.trigger('playing');
|
|
this.player.trigger('loadedalldata');
|
|
this.player.trigger('pause');
|
|
this.player.trigger('ended');
|
|
assert.strictEqual(unprefixed.callCount, 5, 'unprefixed events fired');
|
|
assert.strictEqual(prefixed.callCount, 1, 'prefixed events fired');
|
|
assert.strictEqual(prefixed.getCall(0).args[0].type, 'contentended', 'prefixed the ended event');
|
|
});
|
|
|
|
QUnit.test('startLinearAdMode should only trigger adstart from correct states', function(assert) {
|
|
|
|
const adstart = sinon.spy();
|
|
|
|
this.player.on('adstart', adstart);
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 0, 'Before play');
|
|
|
|
this.player.trigger('play');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 0, 'Before adsready');
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 1, 'Preroll');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 1, 'During preroll playback');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
this.player.trigger('playing');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 2, 'Midroll');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 2, 'During midroll playback');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
this.player.trigger('playing');
|
|
|
|
this.player.trigger('ended');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 3, 'Postroll');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 3, 'During postroll playback');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(adstart.callCount, 3, 'Ads done');
|
|
|
|
});
|
|
|
|
QUnit.test('ad impl can notify contrib-ads there is no preroll', function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('nopreroll');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adsready');
|
|
|
|
assert.strictEqual(this.player.ads.isInAdMode(), true, 'in ad mode');
|
|
assert.strictEqual(this.player.ads.isContentResuming(), true, 'content is resuming');
|
|
});
|
|
|
|
// Same test as above with different event order because this used to be broken.
|
|
QUnit.test('ad impl can notify contrib-ads there is no preroll 2', function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('nopreroll');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
|
|
assert.strictEqual(this.player.ads.isInAdMode(), true, 'not in ad mode');
|
|
assert.strictEqual(this.player.ads.isContentResuming(), true, 'content is resuming');
|
|
});
|
|
|
|
QUnit.test('ad impl can notify contrib-ads there is no preroll 3', function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('play');
|
|
this.player.trigger('nopreroll');
|
|
this.player.trigger('adsready');
|
|
|
|
assert.strictEqual(this.player.ads.isInAdMode(), true, 'not in ad mode');
|
|
assert.strictEqual(this.player.ads.isContentResuming(), true, 'content is resuming');
|
|
});
|
|
|
|
QUnit.test('ad impl can notify contrib-ads there is no preroll 4', function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('nopreroll');
|
|
this.player.trigger('play');
|
|
|
|
assert.strictEqual(this.player.ads.isInAdMode(), true, 'not in ad mode');
|
|
assert.strictEqual(this.player.ads.isContentResuming(), true, 'content is resuming');
|
|
});
|
|
|
|
QUnit.test('ended event is sent after nopostroll', function(assert) {
|
|
|
|
const ended = sinon.spy();
|
|
|
|
this.player.on('ended', ended);
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('nopostroll');
|
|
this.player.trigger('play');
|
|
this.player.trigger('adsready');
|
|
this.player.ads.skipLinearAdMode();
|
|
this.player.trigger('playing');
|
|
this.player.trigger('readyforpostroll');
|
|
this.clock.tick(1);
|
|
assert.ok(ended.calledOnce, 'Ended triggered');
|
|
|
|
});
|
|
|
|
QUnit.test('ended event is sent with postroll', function(assert) {
|
|
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.skipLinearAdMode();
|
|
this.player.trigger('playing');
|
|
|
|
const ended = sinon.spy();
|
|
|
|
this.player.on('ended', ended);
|
|
|
|
this.player.trigger('readyforpostroll');
|
|
|
|
this.clock.tick(10000);
|
|
assert.ok(ended.calledOnce, 'Ended triggered');
|
|
|
|
});
|
|
|
|
QUnit.test('isLive', function(assert) {
|
|
|
|
// Make videojs.browser writeable
|
|
videojs.browser = Object.assign({}, videojs.browser);
|
|
|
|
this.player.duration = function() {
|
|
return 0;
|
|
};
|
|
videojs.browser.IOS_VERSION = '8';
|
|
assert.strictEqual(this.player.ads.isLive(this.player), true);
|
|
|
|
this.player.duration = function() {
|
|
return 5;
|
|
};
|
|
videojs.browser.IOS_VERSION = '8';
|
|
assert.strictEqual(this.player.ads.isLive(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IOS_VERSION = '8';
|
|
assert.strictEqual(this.player.ads.isLive(this.player), true);
|
|
|
|
this.player.duration = function() {
|
|
return 0;
|
|
};
|
|
videojs.browser.IOS_VERSION = undefined;
|
|
assert.strictEqual(this.player.ads.isLive(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return 5;
|
|
};
|
|
videojs.browser.IOS_VERSION = undefined;
|
|
assert.strictEqual(this.player.ads.isLive(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IOS_VERSION = undefined;
|
|
assert.strictEqual(this.player.ads.isLive(this.player), true);
|
|
|
|
});
|
|
|
|
QUnit.test('shouldPlayContentBehindAd', function(assert) {
|
|
|
|
// Make videojs.browser writeable
|
|
videojs.browser = Object.assign({}, videojs.browser);
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IS_IOS = true;
|
|
videojs.browser.IS_ANDROID = true;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IS_IOS = true;
|
|
videojs.browser.IS_ANDROID = false;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IS_IOS = false;
|
|
videojs.browser.IS_ANDROID = true;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IS_IOS = false;
|
|
videojs.browser.IS_ANDROID = false;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), true);
|
|
|
|
this.player.duration = function() {
|
|
return 5;
|
|
};
|
|
videojs.browser.IS_IOS = true;
|
|
videojs.browser.IS_ANDROID = true;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return 5;
|
|
};
|
|
videojs.browser.IS_IOS = true;
|
|
videojs.browser.IS_ANDROID = false;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return 5;
|
|
};
|
|
videojs.browser.IS_IOS = false;
|
|
videojs.browser.IS_ANDROID = true;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return 5;
|
|
};
|
|
videojs.browser.IS_IOS = false;
|
|
videojs.browser.IS_ANDROID = false;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IS_IOS = false;
|
|
videojs.browser.IS_ANDROID = false;
|
|
try {
|
|
this.player.ads.shouldPlayContentBehindAd();
|
|
} catch (error) {
|
|
assert.strictEqual(
|
|
error.message,
|
|
'shouldPlayContentBehindAd requires a player as a param'
|
|
);
|
|
}
|
|
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
videojs.browser.IS_IOS = false;
|
|
videojs.browser.IS_ANDROID = false;
|
|
this.player.ads.settings.liveCuePoints = false;
|
|
assert.strictEqual(this.player.ads.shouldPlayContentBehindAd(this.player), false);
|
|
});
|
|
|
|
QUnit.test('Check incorrect addition of vjs-live during ad-playback', function(assert) {
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(this.player.hasClass('vjs-live'), false, 'We have the correct class');
|
|
|
|
});
|
|
|
|
QUnit.test(
|
|
'Check for existence of vjs-live after ad-end for LIVE videos',
|
|
function(assert) {
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.ads.startLinearAdMode();
|
|
this.player.duration = function() {
|
|
return Infinity;
|
|
};
|
|
this.player.ads.endLinearAdMode();
|
|
this.player.trigger('playing');
|
|
assert.strictEqual(this.player.ads.isLive(this.player), true, 'Content is LIVE');
|
|
assert.ok(this.player.hasClass('vjs-live'), 'We should be having vjs-live class here');
|
|
}
|
|
);
|
|
|
|
QUnit.test('Plugin state resets after contentchanged', function(assert) {
|
|
|
|
assert.equal(this.player.ads.disableNextSnapshotRestore, false);
|
|
assert.equal(this.player.ads._contentHasEnded, false);
|
|
assert.equal(this.player.ads.snapshot, null);
|
|
assert.equal(this.player.ads.snapshot, null);
|
|
assert.equal(this.player.ads.nopreroll_, null);
|
|
assert.equal(this.player.ads.nopostroll_, null);
|
|
|
|
this.player.ads.disableNextSnapshotRestore = true;
|
|
this.player.ads._contentHasEnded = true;
|
|
this.player.ads.snapshot = {};
|
|
this.player.ads.nopreroll_ = true;
|
|
this.player.ads.nopostroll_ = true;
|
|
|
|
this.player.trigger('contentchanged');
|
|
|
|
assert.equal(this.player.ads.disableNextSnapshotRestore, false);
|
|
assert.equal(this.player.ads._contentHasEnded, false);
|
|
assert.equal(this.player.ads.snapshot, null);
|
|
assert.equal(this.player.ads.nopreroll_, false);
|
|
assert.equal(this.player.ads.nopostroll_, false);
|
|
|
|
});
|
|
|
|
QUnit.test('Plugin sets adType as expected', function(assert) {
|
|
|
|
// adType is unset originally
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
|
|
// before preroll
|
|
this.player.trigger('loadstart');
|
|
this.player.trigger('adsready');
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
this.player.trigger('play');
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
|
|
// preroll starts and finishes
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(this.player.ads.adType, 'preroll');
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
|
|
// content is playing, midroll starts
|
|
this.player.trigger('playing');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(this.player.ads.adType, 'midroll');
|
|
|
|
// midroll ends, content is playing
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
this.player.trigger('playing');
|
|
|
|
// postroll starts
|
|
this.player.trigger('readyforpostroll');
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(this.player.ads.adType, 'postroll');
|
|
|
|
// postroll ends
|
|
this.player.ads.endLinearAdMode();
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
|
|
// reset values
|
|
this.player.trigger('contentchanged');
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
|
|
// check preroll case where play is observed
|
|
this.player.trigger('play');
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
this.player.trigger('adsready');
|
|
assert.strictEqual(this.player.ads.adType, null);
|
|
this.player.ads.startLinearAdMode();
|
|
assert.strictEqual(this.player.ads.adType, 'preroll');
|
|
});
|
|
|
|
if (videojs.browser.IS_IOS) {
|
|
QUnit.test('Check the textTrackChangeHandler takes effect on iOS', function(assert) {
|
|
const tracks = this.player.textTracks();
|
|
|
|
// Since addTextTrack is async, wait for the addtrack event
|
|
tracks.on('addtrack', function() {
|
|
|
|
// Confirm the track is added, set the mode to showing
|
|
assert.equal(tracks.length, 1);
|
|
tracks[0].mode = 'showing';
|
|
assert.equal(tracks[0].mode, 'showing', 'Initial state is showing');
|
|
|
|
// Start the ad, confirm the track is disabled
|
|
this.player.ads.startLinearAdMode();
|
|
assert.equal(tracks[0].mode, 'disabled', 'Snapshot sets tracks to disabled');
|
|
|
|
// Force the mode to showing
|
|
tracks[0].mode = 'showing';
|
|
|
|
}.bind(this));
|
|
|
|
// The mode should go back to disabled when the change event happens as
|
|
// during ad playback we do not want the content captions to be visible on iOS
|
|
tracks.on('change', function() {
|
|
assert.equal(tracks[0].mode, 'disabled', 'Mode is reset to disabled');
|
|
|
|
// End the ad, check the track mode is showing again
|
|
this.player.ads.endLinearAdMode();
|
|
assert.equal(tracks[0].mode, 'showing', 'Mode is restored after ad');
|
|
}.bind(this));
|
|
|
|
this.player.trigger('play');
|
|
this.player.trigger('adsready');
|
|
this.player.addTextTrack('captions', 'English', 'en');
|
|
});
|
|
}
|
|
|
|
QUnit.test('playback rate is always x1 during an ad break and the previous value when ad completes', function(assert) {
|
|
const preAdPlaybackRate = 4;
|
|
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
this.player.playbackRate(preAdPlaybackRate);
|
|
this.player.tech_.trigger('ratechange');
|
|
assert.strictEqual(this.player.playbackRate(), preAdPlaybackRate, `Playback rate is x${preAdPlaybackRate} before ad`);
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
this.player.tech_.trigger('ratechange');
|
|
assert.strictEqual(this.player.playbackRate(), 1, 'Playback rate is x1 during ad playback');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
this.player.tech_.trigger('ratechange');
|
|
assert.strictEqual(this.player.playbackRate(), preAdPlaybackRate, 'Playback rate reset to previous value when ad finishes');
|
|
});
|
|
|
|
QUnit.test('playback rate menu is hidden during ad playback if playbackrate supported', function(assert) {
|
|
this.player.playbackRates([1, 2]);
|
|
assert.ok(this.player.controlBar.playbackRateMenuButton.playbackRateSupported());
|
|
this.player.trigger('adsready');
|
|
this.player.trigger('play');
|
|
|
|
this.player.ads.startLinearAdMode();
|
|
assert.ok(this.player.controlBar.playbackRateMenuButton.hasClass('vjs-hidden'), 'Playback rate menu is hidden during an ad');
|
|
|
|
this.player.ads.endLinearAdMode();
|
|
assert.notOk(this.player.controlBar.playbackRateMenuButton.hasClass('vjs-hidden'), 'Playback rate menu is shown when ad finishes');
|
|
});
|
|
|
|
QUnit.test('error() - returns the current error when no params are passed in', function(assert) {
|
|
const expectedError = { errorType: 'test-error' };
|
|
|
|
this.player.ads._error = expectedError;
|
|
|
|
assert.equal(this.player.ads.error(), expectedError);
|
|
});
|
|
|
|
QUnit.test('error() - resets the current error when null is passed in', function(assert) {
|
|
const previousError = { errorType: 'test-error' };
|
|
|
|
this.player.ads._error = previousError;
|
|
this.player.ads.error(null);
|
|
|
|
assert.equal(this.player.ads._error, null);
|
|
});
|
|
|
|
QUnit.test('error() - resets the current error when an invalid error is passed in', function(assert) {
|
|
const previousError = { errorType: 'test-error' };
|
|
|
|
this.player.ads._error = previousError;
|
|
// A valid error is not passed into the function, so it should be reset
|
|
this.player.ads.error(2);
|
|
|
|
assert.equal(this.player.ads._error, null);
|
|
});
|
|
|
|
QUnit.test('error() - when a valid error is passed in, set the error', function(assert) {
|
|
const previousError = { errorType: 'test-error' };
|
|
const newError = { errorType: 'new-test-error'};
|
|
|
|
this.player.ads._error = previousError;
|
|
this.player.ads.error(newError);
|
|
|
|
assert.equal(this.player.ads._error, newError);
|
|
});
|