2019-04-11 20:29:27 +02:00
|
|
|
/* eslint-env qunit */
|
|
|
|
import TestHelpers from './test-helpers.js';
|
|
|
|
import sinon from 'sinon';
|
|
|
|
import window from 'global/window';
|
|
|
|
import * as middleware from '../../src/js/tech/middleware.js';
|
2022-05-23 22:23:13 +02:00
|
|
|
import {merge} from '../../src/js/utils/obj';
|
2019-04-11 20:29:27 +02:00
|
|
|
|
|
|
|
const middleWareTerminations = ['terminates', 'does not-terminate'];
|
|
|
|
const playReturnValues = ['non-promise', 'promise'];
|
|
|
|
|
|
|
|
const mainModule = function(playReturnValue, middlewareTermination, subhooks) {
|
|
|
|
subhooks.beforeEach(function(assert) {
|
|
|
|
this.clock = sinon.useFakeTimers();
|
|
|
|
this.techPlayCalls = 0;
|
|
|
|
this.playsTerminated = 0;
|
|
|
|
this.playTests = [];
|
|
|
|
this.terminate = false;
|
|
|
|
|
|
|
|
if (middlewareTermination === 'terminates') {
|
|
|
|
this.terminate = true;
|
|
|
|
}
|
|
|
|
this.techPlay = () => {
|
|
|
|
this.techPlayCalls++;
|
|
|
|
|
|
|
|
if (playReturnValue === 'promise') {
|
|
|
|
return window.Promise.resolve('foo');
|
|
|
|
}
|
|
|
|
return 'foo';
|
|
|
|
};
|
|
|
|
|
|
|
|
this.finish = function() {
|
|
|
|
const done = assert.async(this.playTests.length);
|
|
|
|
|
|
|
|
const singleFinish = (playValue, assertName) => {
|
|
|
|
assert.equal(playValue, 'foo', `play call from - ${assertName} - is correct`);
|
|
|
|
done();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.playTests.forEach(function(test) {
|
|
|
|
const playRetval = test.playRetval;
|
|
|
|
const testName = test.assertName;
|
|
|
|
|
|
|
|
if (typeof playRetval === 'string') {
|
|
|
|
singleFinish(playRetval, testName);
|
|
|
|
} else {
|
|
|
|
playRetval.then((v) => {
|
|
|
|
singleFinish(v, testName);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
this.checkState = (assertName, options = {}) => {
|
2022-05-23 22:23:13 +02:00
|
|
|
const expectedState = merge({
|
2019-04-11 20:29:27 +02:00
|
|
|
playCalls: 0,
|
|
|
|
techLoaded: false,
|
|
|
|
techReady: false,
|
|
|
|
playerReady: false,
|
|
|
|
changingSrc: false,
|
|
|
|
playsTerminated: 0
|
|
|
|
}, options);
|
|
|
|
|
|
|
|
if (typeof options.techLoaded === 'undefined' && typeof options.techReady !== 'undefined') {
|
|
|
|
expectedState.techLoaded = options.techReady;
|
|
|
|
}
|
|
|
|
|
|
|
|
const currentState = {
|
|
|
|
playCalls: this.techPlayCalls,
|
|
|
|
techLoaded: Boolean(this.player.tech_),
|
|
|
|
techReady: Boolean((this.player.tech_ || {}).isReady_),
|
|
|
|
playerReady: Boolean(this.player.isReady_),
|
|
|
|
changingSrc: Boolean(this.player.changingSrc_),
|
|
|
|
playsTerminated: Number(this.playsTerminated)
|
|
|
|
};
|
|
|
|
|
|
|
|
assert.deepEqual(currentState, expectedState, assertName);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.playTerminatedQueue = () => this.playsTerminated++;
|
|
|
|
|
|
|
|
this.playTest = (assertName, options = {}) => {
|
|
|
|
if (this.player.playTerminatedQueue_ !== this.playTerminatedQueue) {
|
|
|
|
this.player.runPlayTerminatedQueue_ = this.playTerminatedQueue;
|
|
|
|
}
|
|
|
|
if (this.player && this.player.tech_ && this.player.tech_.play !== this.techPlay) {
|
|
|
|
this.player.tech_.play = this.techPlay;
|
|
|
|
}
|
|
|
|
this.playTests.push({assertName, playRetval: this.player.play()});
|
|
|
|
this.checkState(assertName, options);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.middleware = () => {
|
|
|
|
return {
|
|
|
|
// pass along source
|
|
|
|
setSource(srcObj, next) {
|
|
|
|
next(null, srcObj);
|
|
|
|
},
|
|
|
|
callPlay: () => {
|
|
|
|
if (this.terminate) {
|
|
|
|
return middleware.TERMINATOR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
middleware.use('*', this.middleware);
|
|
|
|
});
|
|
|
|
|
|
|
|
subhooks.afterEach(function() {
|
|
|
|
// remove added middleware
|
|
|
|
const middlewareList = middleware.getMiddleware('*');
|
|
|
|
|
|
|
|
for (let i = 0; i < middlewareList.length; i++) {
|
|
|
|
if (middlewareList[i] === this.middleware) {
|
|
|
|
middlewareList.splice(i, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (this.player) {
|
|
|
|
this.player.dispose();
|
|
|
|
}
|
|
|
|
this.clock.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('Player#play() resolves correctly with dom sources and async tech ready', function(assert) {
|
|
|
|
// turn of mediaLoader to prevent setting a tech right away
|
|
|
|
// similar to settings sources in the DOM
|
2023-03-22 16:00:01 +02:00
|
|
|
// turn off autoReady to prevent synchronous ready from the tech
|
2019-04-11 20:29:27 +02:00
|
|
|
this.player = TestHelpers.makePlayer({mediaLoader: false, techFaker: {autoReady: false}});
|
|
|
|
|
|
|
|
this.playTest('before anything is ready');
|
|
|
|
|
|
|
|
this.player.src({
|
|
|
|
src: 'http://example.com/video.mp4',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('only changingSrc', {
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.playTest('still changingSrc, tech loaded', {
|
|
|
|
techLoaded: true,
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.player.tech_.triggerReady();
|
|
|
|
this.playTest('still changingSrc, tech loaded and ready', {
|
|
|
|
techReady: true,
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.playTest('done changingSrc, tech/player ready', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 1,
|
|
|
|
playsTerminated: this.terminate ? 1 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.checkState('state stays the same', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 1,
|
|
|
|
playsTerminated: this.terminate ? 1 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly, unless terminated', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 2,
|
|
|
|
playsTerminated: this.terminate ? 2 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
if (this.terminate) {
|
|
|
|
this.terminate = false;
|
|
|
|
|
|
|
|
this.playTest('play works if not terminated', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 1,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 2,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.finish(assert);
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('Player#play() resolves correctly with dom sources', function(assert) {
|
|
|
|
this.player = TestHelpers.makePlayer({mediaLoader: false});
|
|
|
|
|
|
|
|
this.playTest('before anything is ready');
|
|
|
|
|
|
|
|
this.player.src({
|
|
|
|
src: 'http://example.com/video.mp4',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('only changingSrc', {
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.playTest('still changingSrc, tech/player ready', {
|
|
|
|
techLoaded: true,
|
|
|
|
changingSrc: true,
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.playTest('done changingSrc, tech#play is called', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 1,
|
|
|
|
playsTerminated: this.terminate ? 1 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.checkState('state stays the same', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 1,
|
|
|
|
playsTerminated: this.terminate ? 1 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 2,
|
|
|
|
playsTerminated: this.terminate ? 2 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
if (this.terminate) {
|
|
|
|
this.terminate = false;
|
|
|
|
|
|
|
|
this.playTest('play works if not terminated', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 1,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 2,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.finish(assert);
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('Player#play() resolves correctly with async tech ready', function(assert) {
|
|
|
|
this.player = TestHelpers.makePlayer({techFaker: {autoReady: false}});
|
|
|
|
|
|
|
|
this.playTest('before anything is ready', {
|
|
|
|
techLoaded: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.player.src({
|
|
|
|
src: 'http://example.com/video.mp4',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('tech loaded changingSrc', {
|
|
|
|
techLoaded: true,
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.playTest('still changingSrc, tech loaded', {
|
|
|
|
techLoaded: true,
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
this.playTest('still changingSrc, tech loaded again', {
|
|
|
|
techLoaded: true,
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.player.tech_.triggerReady();
|
|
|
|
this.playTest('still changingSrc, tech loaded and ready', {
|
|
|
|
techReady: true,
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.playTest('still changingSrc tech/player ready', {
|
|
|
|
changingSrc: true,
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true
|
|
|
|
});
|
|
|
|
|
|
|
|
// player ready calls fire now
|
|
|
|
// which sets changingSrc_ to false
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.checkState('play was called on ready', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 1,
|
|
|
|
playsTerminated: this.terminate ? 1 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 2,
|
|
|
|
playsTerminated: this.terminate ? 2 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
if (this.terminate) {
|
|
|
|
this.terminate = false;
|
|
|
|
|
|
|
|
this.playTest('play works if not terminated', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 1,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 2,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.finish(assert);
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('Player#play() resolves correctly', function(assert) {
|
|
|
|
this.player = TestHelpers.makePlayer();
|
|
|
|
|
|
|
|
this.playTest('player/tech start out ready', {
|
|
|
|
techReady: true,
|
|
|
|
playerReady: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.player.src({
|
|
|
|
src: 'http://example.com/video.mp4',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('now changingSrc', {
|
|
|
|
techReady: true,
|
|
|
|
playerReady: true,
|
|
|
|
changingSrc: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
this.playTest('done changingSrc, play called if not terminated', {
|
|
|
|
techReady: true,
|
|
|
|
playerReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 1,
|
|
|
|
playsTerminated: this.terminate ? 1 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(2);
|
|
|
|
|
|
|
|
this.checkState('state stays the same', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 1,
|
|
|
|
playsTerminated: this.terminate ? 1 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: this.terminate ? 0 : 2,
|
|
|
|
playsTerminated: this.terminate ? 2 : 0
|
|
|
|
});
|
|
|
|
|
|
|
|
if (this.terminate) {
|
|
|
|
this.terminate = false;
|
|
|
|
|
|
|
|
this.playTest('play works if not terminated', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 1,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
|
|
|
|
this.playTest('future calls hit tech#play directly', {
|
|
|
|
playerReady: true,
|
|
|
|
techReady: true,
|
|
|
|
playCalls: 2,
|
|
|
|
playsTerminated: 2
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-03-09 18:41:01 +02:00
|
|
|
this.clock.tick(1000);
|
|
|
|
|
2019-04-11 20:29:27 +02:00
|
|
|
this.finish(assert);
|
|
|
|
});
|
|
|
|
|
|
|
|
// without enableSourceset this test will fail.
|
|
|
|
QUnit.test('Player#play() resolves correctly on tech el src', function(assert) {
|
2019-04-23 19:42:52 +02:00
|
|
|
this.player = TestHelpers.makePlayer({techOrder: ['html5'], enableSourceset: true});
|
2019-04-11 20:29:27 +02:00
|
|
|
|
|
|
|
this.playTest('player/tech start out ready', {
|
|
|
|
techReady: true,
|
|
|
|
playerReady: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.player.tech_.el_.src = 'http://vjs.zencdn.net/v/oceans.mp4';
|
|
|
|
|
|
|
|
this.player.on('loadstart', () => {
|
|
|
|
this.checkState('play should have been called', {
|
|
|
|
techReady: true,
|
|
|
|
playerReady: true,
|
|
|
|
playCalls: 1
|
|
|
|
});
|
|
|
|
|
2021-03-09 18:41:01 +02:00
|
|
|
this.finish(assert);
|
|
|
|
});
|
2019-04-11 20:29:27 +02:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
QUnit.module('Player#play()', (hooks) => {
|
|
|
|
playReturnValues.forEach((playReturnValue) => {
|
|
|
|
middleWareTerminations.forEach((middlewareTermination) => {
|
|
|
|
QUnit.module(`tech#play() => ${playReturnValue}, middleware ${middlewareTermination}`, (subhooks) => {
|
|
|
|
mainModule(playReturnValue, middlewareTermination, subhooks);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|