diff options
Diffstat (limited to 'javascript/videojs/test/unit/play.test.js')
| -rw-r--r-- | javascript/videojs/test/unit/play.test.js | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/javascript/videojs/test/unit/play.test.js b/javascript/videojs/test/unit/play.test.js new file mode 100644 index 0000000..be5e8ad --- /dev/null +++ b/javascript/videojs/test/unit/play.test.js @@ -0,0 +1,448 @@ +/* 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'; +import {merge} from '../../src/js/utils/obj'; + +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 = {}) => { + const expectedState = merge({ + 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 + // turn off autoReady to prevent synchronous ready from the tech + 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 + }); + } + + this.clock.tick(1000); + + this.finish(assert); + }); + + // without enableSourceset this test will fail. + QUnit.test('Player#play() resolves correctly on tech el src', function(assert) { + this.player = TestHelpers.makePlayer({techOrder: ['html5'], enableSourceset: true}); + + 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 + }); + + this.finish(assert); + }); + }); +}; + +QUnit.module('Player#play()', (hooks) => { + playReturnValues.forEach((playReturnValue) => { + middleWareTerminations.forEach((middlewareTermination) => { + QUnit.module(`tech#play() => ${playReturnValue}, middleware ${middlewareTermination}`, (subhooks) => { + mainModule(playReturnValue, middlewareTermination, subhooks); + }); + }); + }); +}); |
