2016-08-04 17:49:32 +02:00
|
|
|
/* eslint-env qunit */
|
2017-01-18 08:52:23 +02:00
|
|
|
import Plugin from '../../src/js/plugin';
|
2015-03-26 06:43:41 +02:00
|
|
|
import Player from '../../src/js/player.js';
|
2015-05-04 01:12:38 +02:00
|
|
|
import videojs from '../../src/js/video.js';
|
|
|
|
import * as Dom from '../../src/js/utils/dom.js';
|
|
|
|
import * as browser from '../../src/js/utils/browser.js';
|
|
|
|
import log from '../../src/js/utils/log.js';
|
2015-03-26 06:43:41 +02:00
|
|
|
import MediaError from '../../src/js/media-error.js';
|
2015-04-14 22:08:32 +02:00
|
|
|
import Html5 from '../../src/js/tech/html5.js';
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
import Tech from '../../src/js/tech/tech.js';
|
2015-03-26 06:43:41 +02:00
|
|
|
import TestHelpers from './test-helpers.js';
|
|
|
|
import document from 'global/document';
|
2016-08-04 17:49:32 +02:00
|
|
|
import sinon from 'sinon';
|
2015-12-07 23:27:33 +02:00
|
|
|
import window from 'global/window';
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
import * as middleware from '../../src/js/tech/middleware.js';
|
2015-03-26 06:43:41 +02:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.module('Player', {
|
2016-08-12 19:51:31 +02:00
|
|
|
beforeEach() {
|
2014-12-03 21:31:39 +02:00
|
|
|
this.clock = sinon.useFakeTimers();
|
2016-11-23 20:52:54 +02:00
|
|
|
// reset players storage
|
|
|
|
for (const playerId in Player.players) {
|
|
|
|
if (Player.players[playerId] !== null) {
|
|
|
|
Player.players[playerId].dispose();
|
|
|
|
}
|
|
|
|
delete Player.players[playerId];
|
|
|
|
}
|
2014-09-02 22:39:08 +03:00
|
|
|
},
|
2016-08-12 19:51:31 +02:00
|
|
|
afterEach() {
|
2014-12-03 21:31:39 +02:00
|
|
|
this.clock.restore();
|
2014-09-02 22:39:08 +03:00
|
|
|
}
|
|
|
|
});
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should create player instance that inherits from component and dispose it', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().nodeName === 'DIV');
|
|
|
|
assert.ok(player.on, 'component function exists');
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
player.dispose();
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el() === null, 'element disposed');
|
2013-01-11 00:06:12 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('dispose should not throw if styleEl is missing', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
2016-01-14 21:01:30 +02:00
|
|
|
|
|
|
|
player.styleEl_.parentNode.removeChild(player.styleEl_);
|
|
|
|
|
|
|
|
player.dispose();
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el() === null, 'element disposed');
|
2016-01-14 21:01:30 +02:00
|
|
|
});
|
|
|
|
|
2015-08-12 22:51:43 +02:00
|
|
|
// technically, all uses of videojs.options should be replaced with
|
|
|
|
// Player.prototype.options_ in this file and a equivalent test using
|
|
|
|
// videojs.options should be made in video.test.js. Keeping this here
|
|
|
|
// until we make that move.
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should accept options from multiple sources and override in correct order', function(assert) {
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
// Set a global option
|
2015-08-12 22:51:43 +02:00
|
|
|
videojs.options.attr = 1;
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag0 = TestHelpers.makeTag();
|
|
|
|
const player0 = new Player(tag0, { techOrder: ['techFaker'] });
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player0.options_.attr, 1, 'global option was set');
|
2013-01-11 00:06:12 +03:00
|
|
|
player0.dispose();
|
|
|
|
|
|
|
|
// Set a tag level option
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag2 = TestHelpers.makeTag();
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
// Attributes must be set as strings
|
|
|
|
tag2.setAttribute('attr', 'asdf');
|
|
|
|
|
|
|
|
const player2 = new Player(tag2, { techOrder: ['techFaker'] });
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player2.options_.attr, 'asdf', 'Tag options overrode global options');
|
2015-08-12 22:51:43 +02:00
|
|
|
player2.dispose();
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
// Set a tag level option
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag3 = TestHelpers.makeTag();
|
|
|
|
|
2015-08-12 22:51:43 +02:00
|
|
|
tag3.setAttribute('attr', 'asdf');
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player3 = new Player(tag3, { techOrder: ['techFaker'], attr: 'fdsa' });
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player3.options_.attr, 'fdsa', 'Init options overrode tag and global options');
|
2015-08-12 22:51:43 +02:00
|
|
|
player3.dispose();
|
2013-01-11 00:06:12 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should get tag, source, and track settings', function(assert) {
|
2017-01-19 23:01:56 +02:00
|
|
|
// Partially tested in lib->getAttributes
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
let html = '<video id="example_1" class="video-js" autoplay preload="none">';
|
|
|
|
|
|
|
|
html += '<source src="http://google.com" type="video/mp4">';
|
|
|
|
html += '<source src="http://google.com" type="video/webm">';
|
|
|
|
html += '<track kind="captions" attrtest>';
|
|
|
|
html += '</video>';
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
fixture.innerHTML += html;
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag = document.getElementById('example_1');
|
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.options_.autoplay, true, 'autoplay is set to true');
|
|
|
|
assert.equal(player.options_.preload, 'none', 'preload is set to none');
|
|
|
|
assert.equal(player.options_.id, 'example_1', 'id is set to example_1');
|
|
|
|
assert.equal(player.options_.sources.length, 2, 'we have two sources');
|
|
|
|
assert.equal(player.options_.sources[0].src, 'http://google.com', 'first source is google.com');
|
|
|
|
assert.equal(player.options_.sources[0].type, 'video/mp4', 'first time is video/mp4');
|
|
|
|
assert.equal(player.options_.sources[1].type, 'video/webm', 'second type is video/webm');
|
|
|
|
assert.equal(player.options_.tracks.length, 1, 'we have one text track');
|
|
|
|
assert.equal(player.options_.tracks[0].kind, 'captions', 'the text track is a captions file');
|
|
|
|
assert.equal(player.options_.tracks[0].attrtest, '', 'we have an empty attribute called attrtest');
|
2016-04-19 23:09:53 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.notEqual(player.el().className.indexOf('video-js'), -1, 'transferred class from tag to player div');
|
|
|
|
assert.equal(player.el().id, 'example_1', 'transferred id from tag to player div');
|
2016-04-19 23:09:53 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(Player.players[player.id()], player, 'player referenceable from global list');
|
|
|
|
assert.notEqual(tag.id, player.id, 'tag ID no longer is the same as player ID');
|
|
|
|
assert.notEqual(tag.className, player.el().className, 'tag classname updated');
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.notEqual(tag.player, player, 'tag player ref killed');
|
|
|
|
assert.ok(!Player.players.example_1, 'global player ref killed');
|
|
|
|
assert.equal(player.el(), null, 'player el killed');
|
2012-12-11 03:40:12 +03:00
|
|
|
});
|
|
|
|
|
2016-11-03 21:50:55 +02:00
|
|
|
QUnit.test('should get current source from source tag', function(assert) {
|
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
|
|
|
|
|
|
|
const html = [
|
|
|
|
'<video id="example_1" class="video-js" preload="none">',
|
|
|
|
'<source src="http://google.com" type="video/mp4">',
|
|
|
|
'<source src="http://hugo.com" type="video/webm">',
|
|
|
|
'</video>'
|
|
|
|
].join('');
|
|
|
|
|
|
|
|
fixture.innerHTML += html;
|
|
|
|
|
|
|
|
const tag = document.getElementById('example_1');
|
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
|
|
|
|
|
|
|
assert.ok(player.currentSource().src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSource().type === 'video/mp4');
|
2016-12-02 21:17:36 +02:00
|
|
|
|
|
|
|
player.dispose();
|
2016-11-03 21:50:55 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('should get current sources from source tag', function(assert) {
|
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
|
|
|
|
|
|
|
const html = [
|
|
|
|
'<video id="example_1" class="video-js" preload="none">',
|
|
|
|
'<source src="http://google.com" type="video/mp4">',
|
|
|
|
'<source src="http://hugo.com" type="video/webm">',
|
|
|
|
'</video>'
|
|
|
|
].join('');
|
|
|
|
|
|
|
|
fixture.innerHTML += html;
|
|
|
|
|
|
|
|
const tag = document.getElementById('example_1');
|
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
|
|
|
|
|
|
|
assert.ok(player.currentSources()[0].src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSources()[0].type === 'video/mp4');
|
|
|
|
assert.ok(player.currentSources()[1].src === 'http://hugo.com');
|
|
|
|
assert.ok(player.currentSources()[1].type === 'video/webm');
|
|
|
|
|
|
|
|
// when redefining src expect sources to update accordingly
|
|
|
|
player.src('http://google.com');
|
|
|
|
|
|
|
|
assert.ok(player.currentSources()[0].src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSources()[0].type === undefined);
|
|
|
|
assert.ok(player.currentSources()[1] === undefined);
|
2016-12-02 21:17:36 +02:00
|
|
|
|
|
|
|
player.dispose();
|
2016-11-03 21:50:55 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('should get current source from src set', function(assert) {
|
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
|
|
|
|
|
|
|
const html = '<video id="example_1" class="video-js" preload="none"></video>';
|
|
|
|
|
|
|
|
fixture.innerHTML += html;
|
|
|
|
|
|
|
|
const tag = document.getElementById('example_1');
|
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
|
|
|
|
|
|
|
player.loadTech_('Html5');
|
|
|
|
|
|
|
|
// check for matching undefined src
|
|
|
|
assert.deepEqual(player.currentSource(), {});
|
2017-11-01 17:12:48 +02:00
|
|
|
assert.equal(player.src(), '');
|
2016-11-03 21:50:55 +02:00
|
|
|
|
|
|
|
player.src('http://google.com');
|
|
|
|
|
|
|
|
assert.ok(player.currentSource().src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSource().type === undefined);
|
|
|
|
|
|
|
|
player.src({
|
|
|
|
src: 'http://google.com'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.ok(player.currentSource().src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSource().type === undefined);
|
|
|
|
|
|
|
|
player.src({
|
|
|
|
src: 'http://google.com',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.ok(player.currentSource().src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSource().type === 'video/mp4');
|
2016-12-02 21:17:36 +02:00
|
|
|
player.dispose();
|
2016-11-03 21:50:55 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('should get current sources from src set', function(assert) {
|
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
|
|
|
|
|
|
|
const html = '<video id="example_1" class="video-js" preload="none"></video>';
|
|
|
|
|
|
|
|
fixture.innerHTML += html;
|
|
|
|
|
|
|
|
const tag = document.getElementById('example_1');
|
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
|
|
|
|
|
|
|
player.loadTech_('Html5');
|
|
|
|
|
|
|
|
// check for matching undefined src
|
|
|
|
assert.ok(player.currentSources(), []);
|
|
|
|
|
|
|
|
player.src([{
|
|
|
|
src: 'http://google.com'
|
|
|
|
}, {
|
|
|
|
src: 'http://hugo.com'
|
|
|
|
}]);
|
|
|
|
|
|
|
|
assert.ok(player.currentSources()[0].src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSources()[0].type === undefined);
|
|
|
|
assert.ok(player.currentSources()[1].src === 'http://hugo.com');
|
|
|
|
assert.ok(player.currentSources()[1].type === undefined);
|
|
|
|
|
|
|
|
player.src([{
|
|
|
|
src: 'http://google.com',
|
|
|
|
type: 'video/mp4'
|
|
|
|
}, {
|
|
|
|
src: 'http://hugo.com',
|
|
|
|
type: 'video/webm'
|
|
|
|
}]);
|
|
|
|
|
|
|
|
assert.ok(player.currentSources()[0].src === 'http://google.com');
|
|
|
|
assert.ok(player.currentSources()[0].type === 'video/mp4');
|
|
|
|
assert.ok(player.currentSources()[1].src === 'http://hugo.com');
|
|
|
|
assert.ok(player.currentSources()[1].type === 'video/webm');
|
|
|
|
|
|
|
|
// when redefining src expect sources to update accordingly
|
|
|
|
player.src('http://hugo.com');
|
|
|
|
|
|
|
|
assert.ok(player.currentSources()[0].src === 'http://hugo.com');
|
|
|
|
assert.ok(player.currentSources()[0].type === undefined);
|
|
|
|
assert.ok(player.currentSources()[1] === undefined);
|
2016-12-02 21:17:36 +02:00
|
|
|
|
|
|
|
player.dispose();
|
2016-11-03 21:50:55 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should asynchronously fire error events during source selection', function(assert) {
|
|
|
|
assert.expect(2);
|
2014-09-02 22:39:08 +03:00
|
|
|
|
2015-05-04 01:12:38 +02:00
|
|
|
sinon.stub(log, 'error');
|
2014-09-02 22:39:08 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({
|
|
|
|
techOrder: ['foo'],
|
|
|
|
sources: [
|
|
|
|
{ src: 'http://vjs.zencdn.net/v/oceans.mp4', type: 'video/mp4' }
|
2014-09-02 22:39:08 +03:00
|
|
|
]
|
|
|
|
});
|
2016-08-04 17:49:32 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.options_.techOrder[0] === 'foo', 'Foo listed as the only tech');
|
2014-09-02 22:39:08 +03:00
|
|
|
|
|
|
|
player.on('error', function(e) {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.error().code === 4, 'Source could not be played error thrown');
|
2014-09-02 22:39:08 +03:00
|
|
|
});
|
|
|
|
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
// The first one is for player initialization
|
|
|
|
// The second one is the setTimeout for triggering the error
|
|
|
|
this.clock.tick(1);
|
2014-12-03 21:31:39 +02:00
|
|
|
this.clock.tick(1);
|
2014-09-02 22:39:08 +03:00
|
|
|
|
|
|
|
player.dispose();
|
2015-05-04 01:12:38 +02:00
|
|
|
log.error.restore();
|
2014-09-02 22:39:08 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should set the width, height, and aspect ratio via a css class', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const getStyleText = function(styleEl) {
|
2015-05-14 07:45:01 +02:00
|
|
|
return (styleEl.styleSheet && styleEl.styleSheet.cssText) || styleEl.innerHTML;
|
|
|
|
};
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2015-07-23 21:45:41 +02:00
|
|
|
// NOTE: was using npm/css to parse the actual CSS ast
|
|
|
|
// but the css module doesn't support ie8
|
2016-08-04 17:49:32 +02:00
|
|
|
const confirmSetting = function(prop, val) {
|
2015-07-23 21:45:41 +02:00
|
|
|
let styleText = getStyleText(player.styleEl_);
|
2016-08-04 17:49:32 +02:00
|
|
|
const re = new RegExp(prop + ':\\s?' + val);
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2015-07-23 21:45:41 +02:00
|
|
|
// Lowercase string for IE8
|
|
|
|
styleText = styleText.toLowerCase();
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2015-07-23 21:45:41 +02:00
|
|
|
return !!re.test(styleText);
|
|
|
|
};
|
2013-04-09 02:23:41 +03:00
|
|
|
|
2015-07-23 21:45:41 +02:00
|
|
|
// Initial state
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!getStyleText(player.styleEl_), 'style element should be empty when the player is given no dimensions');
|
2015-05-14 07:45:01 +02:00
|
|
|
|
|
|
|
// Set only the width
|
|
|
|
player.width(100);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(confirmSetting('width', '100px'), 'style width should equal the supplied width in pixels');
|
|
|
|
assert.ok(confirmSetting('height', '56.25px'), 'style height should match the default aspect ratio of the width');
|
2015-05-14 07:45:01 +02:00
|
|
|
|
|
|
|
// Set the height
|
|
|
|
player.height(200);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(confirmSetting('height', '200px'), 'style height should match the supplied height in pixels');
|
2015-05-14 07:45:01 +02:00
|
|
|
|
|
|
|
// Reset the width and height to defaults
|
|
|
|
player.width('');
|
|
|
|
player.height('');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(confirmSetting('width', '300px'), 'supplying an empty string should reset the width');
|
|
|
|
assert.ok(confirmSetting('height', '168.75px'), 'supplying an empty string should reset the height');
|
2015-05-14 07:45:01 +02:00
|
|
|
|
|
|
|
// Switch to fluid mode
|
|
|
|
player.fluid(true);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.hasClass('vjs-fluid'), 'the vjs-fluid class should be added to the player');
|
|
|
|
assert.ok(confirmSetting('padding-top', '56.25%'), 'fluid aspect ratio should match the default aspect ratio');
|
2015-05-14 07:45:01 +02:00
|
|
|
|
|
|
|
// Change the aspect ratio
|
|
|
|
player.aspectRatio('4:1');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(confirmSetting('padding-top', '25%'), 'aspect ratio percent should match the newly set aspect ratio');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2013-03-09 11:39:28 +03:00
|
|
|
});
|
|
|
|
|
2016-11-03 21:37:30 +02:00
|
|
|
QUnit.test('should default to 16:9 when fluid', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer({fluid: true});
|
2016-11-04 00:40:14 +02:00
|
|
|
const ratio = player.currentHeight() / player.currentWidth();
|
2016-11-03 21:37:30 +02:00
|
|
|
|
2016-11-04 00:40:14 +02:00
|
|
|
// IE8 rounds 0.5625 up to 0.563
|
|
|
|
assert.ok(((ratio >= 0.562) && (ratio <= 0.563)), 'fluid player without dimensions defaults to 16:9');
|
2016-12-02 21:17:36 +02:00
|
|
|
|
|
|
|
player.dispose();
|
2016-11-03 21:37:30 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('should set fluid to true if element has vjs-fluid class', function(assert) {
|
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
|
|
|
|
tag.className += ' vjs-fluid';
|
|
|
|
|
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
|
|
|
|
|
|
|
assert.ok(player.fluid(), 'fluid is true with vjs-fluid class');
|
2016-12-02 21:17:36 +02:00
|
|
|
|
|
|
|
player.dispose();
|
2016-11-03 21:37:30 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should use an class name that begins with an alpha character', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const alphaPlayer = TestHelpers.makePlayer({ id: 'alpha1' });
|
|
|
|
const numericPlayer = TestHelpers.makePlayer({ id: '1numeric' });
|
2015-11-21 00:38:05 +02:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const getStyleText = function(styleEl) {
|
2015-11-21 00:38:05 +02:00
|
|
|
return (styleEl.styleSheet && styleEl.styleSheet.cssText) || styleEl.innerHTML;
|
|
|
|
};
|
|
|
|
|
|
|
|
alphaPlayer.width(100);
|
|
|
|
numericPlayer.width(100);
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(/\s*\.alpha1-dimensions\s*\{/.test(getStyleText(alphaPlayer.styleEl_)), 'appends -dimensions to an alpha player ID');
|
|
|
|
assert.ok(/\s*\.dimensions-1numeric\s*\{/.test(getStyleText(numericPlayer.styleEl_)), 'prepends dimensions- to a numeric player ID');
|
2016-08-25 16:58:42 +02:00
|
|
|
alphaPlayer.dispose();
|
|
|
|
numericPlayer.dispose();
|
2015-11-21 00:38:05 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should wrap the original tag in the player div', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
const container = document.createElement('div');
|
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
container.appendChild(tag);
|
|
|
|
fixture.appendChild(container);
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = new Player(tag, { techOrder: ['techFaker'] });
|
|
|
|
const el = player.el();
|
2013-01-11 00:06:12 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(el.parentNode === container, 'player placed at same level as tag');
|
2013-01-11 00:06:12 +03:00
|
|
|
// Tag may be placed inside the player element or it may be removed from the DOM
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(tag.parentNode !== container, 'tag removed from original place');
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should set and update the poster value', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const poster = '#';
|
|
|
|
const updatedPoster = 'http://example.com/updated-poster.jpg';
|
2013-08-25 02:34:26 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag = TestHelpers.makeTag();
|
2013-08-25 02:34:26 +03:00
|
|
|
|
2013-11-27 03:53:23 +03:00
|
|
|
tag.setAttribute('poster', poster);
|
2013-08-25 02:34:26 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.poster(), poster, 'the poster property should equal the tag attribute');
|
2013-08-25 02:34:26 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
let pcEmitted = false;
|
|
|
|
|
|
|
|
player.on('posterchange', function() {
|
2013-11-27 03:53:23 +03:00
|
|
|
pcEmitted = true;
|
|
|
|
});
|
2013-08-25 02:34:26 +03:00
|
|
|
|
|
|
|
player.poster(updatedPoster);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(pcEmitted, 'posterchange event was emitted');
|
|
|
|
assert.equal(player.poster(), updatedPoster, 'the updated poster is returned');
|
2013-08-25 02:34:26 +03:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2015-02-09 19:11:00 +02:00
|
|
|
// hasStarted() is equivalent to the "show poster flag" in the
|
|
|
|
// standard, for the purpose of displaying the poster image
|
|
|
|
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should hide the poster when play is called', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({
|
2015-02-09 19:11:00 +02:00
|
|
|
poster: 'https://example.com/poster.jpg'
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.hasStarted(), false, 'the show poster flag is true before play');
|
2016-06-28 05:07:00 +02:00
|
|
|
player.tech_.trigger('play');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.hasStarted(), true, 'the show poster flag is false after play');
|
2015-02-09 19:11:00 +02:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.hasStarted(), false, 'the resource selection algorithm sets the show poster flag to true');
|
2015-02-09 19:11:00 +02:00
|
|
|
|
2016-06-28 05:07:00 +02:00
|
|
|
player.tech_.trigger('play');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.hasStarted(), true, 'the show poster flag is false after play');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-02-09 19:11:00 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should load a media controller', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({
|
2013-01-11 00:06:12 +03:00
|
|
|
preload: 'none',
|
|
|
|
sources: [
|
2013-02-09 01:29:04 +03:00
|
|
|
{ src: 'http://google.com', type: 'video/mp4' },
|
|
|
|
{ src: 'http://google.com', type: 'video/webm' }
|
2013-01-11 00:06:12 +03:00
|
|
|
]
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().children[0].className.indexOf('vjs-tech') !== -1, 'media controller loaded');
|
2013-01-11 00:06:12 +03:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
2013-01-18 04:33:53 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should be able to initialize player twice on the same tag using string reference', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
let videoTag = TestHelpers.makeTag();
|
|
|
|
const id = videoTag.id;
|
|
|
|
|
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
2013-03-06 00:23:01 +03:00
|
|
|
|
|
|
|
fixture.appendChild(videoTag);
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
let player = videojs(videoTag.id, { techOrder: ['techFaker'] });
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player, 'player is created');
|
2013-03-06 00:23:01 +03:00
|
|
|
player.dispose();
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!document.getElementById(id), 'element is removed');
|
2015-03-26 06:43:41 +02:00
|
|
|
videoTag = TestHelpers.makeTag();
|
2013-03-06 00:23:01 +03:00
|
|
|
fixture.appendChild(videoTag);
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
// here we receive cached version instead of real
|
2015-09-28 20:23:25 +02:00
|
|
|
player = videojs(videoTag.id, { techOrder: ['techFaker'] });
|
2016-08-04 17:49:32 +02:00
|
|
|
// here it triggers error, because player was destroyed already after first dispose
|
2013-03-06 00:23:01 +03:00
|
|
|
player.dispose();
|
|
|
|
});
|
2013-05-03 03:15:37 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should set controls and trigger events', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({ controls: false });
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.controls() === false, 'controls set through options');
|
2016-08-04 17:49:32 +02:00
|
|
|
const hasDisabledClass = player.el().className.indexOf('vjs-controls-disabled');
|
2013-05-03 03:15:37 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(hasDisabledClass !== -1, 'Disabled class added to player');
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2013-05-03 03:15:37 +03:00
|
|
|
player.controls(true);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.controls() === true, 'controls updated');
|
2016-08-04 17:49:32 +02:00
|
|
|
const hasEnabledClass = player.el().className.indexOf('vjs-controls-enabled');
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(hasEnabledClass !== -1, 'Disabled class added to player');
|
2013-05-03 03:15:37 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
player.on('controlsenabled', function() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'enabled fired once');
|
2013-08-10 00:29:22 +03:00
|
|
|
});
|
2016-08-04 17:49:32 +02:00
|
|
|
player.on('controlsdisabled', function() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'disabled fired once');
|
2013-05-03 03:15:37 +03:00
|
|
|
});
|
|
|
|
player.controls(false);
|
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should toggle user the user state between active and inactive', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.expect(9);
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.userActive(), 'User should be active at player init');
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
player.on('userinactive', function() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'userinactive event triggered');
|
2013-08-10 00:29:22 +03:00
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
player.on('useractive', function() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'useractive event triggered');
|
2013-08-10 00:29:22 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
player.userActive(false);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.userActive() === false, 'Player state changed to inactive');
|
|
|
|
assert.ok(player.el().className.indexOf('vjs-user-active') === -1, 'Active class removed');
|
|
|
|
assert.ok(player.el().className.indexOf('vjs-user-inactive') !== -1, 'Inactive class added');
|
2013-08-10 00:29:22 +03:00
|
|
|
|
|
|
|
player.userActive(true);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.userActive() === true, 'Player state changed to active');
|
|
|
|
assert.ok(player.el().className.indexOf('vjs-user-inactive') === -1, 'Inactive class removed');
|
|
|
|
assert.ok(player.el().className.indexOf('vjs-user-active') !== -1, 'Active class added');
|
2013-08-10 00:29:22 +03:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should add a touch-enabled classname when touch is supported', function(assert) {
|
|
|
|
assert.expect(1);
|
2013-08-10 00:29:22 +03:00
|
|
|
|
|
|
|
// Fake touch support. Real touch support isn't needed for this test.
|
2016-08-04 17:49:32 +02:00
|
|
|
const origTouch = browser.TOUCH_ENABLED;
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
browser.TOUCH_ENABLED = true;
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-touch-enabled'), 'touch-enabled classname added');
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2015-05-04 01:12:38 +02:00
|
|
|
browser.TOUCH_ENABLED = origTouch;
|
2013-08-10 00:29:22 +03:00
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should allow for tracking when native controls are used', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
2013-08-10 00:29:22 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.expect(6);
|
2013-08-10 00:29:22 +03:00
|
|
|
|
|
|
|
// Make sure native controls is false before starting test
|
|
|
|
player.usingNativeControls(false);
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
player.on('usingnativecontrols', function() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'usingnativecontrols event triggered');
|
2013-08-10 00:29:22 +03:00
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
player.on('usingcustomcontrols', function() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'usingcustomcontrols event triggered');
|
2013-08-10 00:29:22 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
player.usingNativeControls(true);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.usingNativeControls() === true, 'Using native controls is true');
|
|
|
|
assert.ok(player.el().className.indexOf('vjs-using-native-controls') !== -1, 'Native controls class added');
|
2013-08-10 00:29:22 +03:00
|
|
|
|
|
|
|
player.usingNativeControls(false);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.usingNativeControls() === false, 'Using native controls is false');
|
|
|
|
assert.ok(player.el().className.indexOf('vjs-using-native-controls') === -1, 'Native controls class removed');
|
2013-08-10 00:29:22 +03:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('make sure that controls listeners do not get added too many times', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
|
|
|
let listeners = 0;
|
2015-08-25 22:17:35 +02:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.addTechControlsListeners_ = function() {
|
2015-08-25 22:17:35 +02:00
|
|
|
listeners++;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Make sure native controls is false before starting test
|
|
|
|
player.usingNativeControls(false);
|
|
|
|
|
|
|
|
player.usingNativeControls(true);
|
|
|
|
|
|
|
|
player.controls(true);
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(listeners, 0, 'addTechControlsListeners_ should not have gotten called yet');
|
2015-08-25 22:17:35 +02:00
|
|
|
|
|
|
|
player.usingNativeControls(false);
|
|
|
|
player.controls(false);
|
|
|
|
|
|
|
|
player.controls(true);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(listeners, 1, 'addTechControlsListeners_ should have gotten called once');
|
2015-08-25 22:17:35 +02:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should register players with generated ids', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
|
|
|
|
|
|
|
const video = document.createElement('video');
|
2013-12-03 02:29:41 +03:00
|
|
|
|
|
|
|
video.className = 'vjs-default-skin video-js';
|
|
|
|
fixture.appendChild(video);
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = new Player(video, { techOrder: ['techFaker'] });
|
|
|
|
const id = player.el().id;
|
2013-12-03 02:29:41 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.el().id, player.id(), 'the player and element ids are equal');
|
|
|
|
assert.ok(Player.players[id], 'the generated id is registered');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2013-12-03 02:29:41 +03:00
|
|
|
});
|
2014-04-03 20:41:02 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should not add multiple first play events despite subsequent loads', function(assert) {
|
|
|
|
assert.expect(1);
|
2014-04-03 20:41:02 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
2014-04-03 20:41:02 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
player.on('firstplay', function() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'First play should fire once.');
|
2014-04-03 20:41:02 +03:00
|
|
|
});
|
|
|
|
|
2015-05-06 20:01:52 +02:00
|
|
|
// Checking to make sure onLoadStart removes first play listener before adding a new one.
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
|
|
|
player.tech_.trigger('loadstart');
|
|
|
|
player.tech_.trigger('play');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-04-03 20:41:02 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should fire firstplay after resetting the player', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
2014-06-11 02:55:08 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
let fpFired = false;
|
|
|
|
|
|
|
|
player.on('firstplay', function() {
|
2014-06-11 02:55:08 +03:00
|
|
|
fpFired = true;
|
|
|
|
});
|
|
|
|
|
|
|
|
// init firstplay listeners
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
|
|
|
player.tech_.trigger('play');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(fpFired, 'First firstplay fired');
|
2014-06-11 02:55:08 +03:00
|
|
|
|
|
|
|
// reset the player
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
2014-06-11 02:55:08 +03:00
|
|
|
fpFired = false;
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('play');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(fpFired, 'Second firstplay fired');
|
2014-06-11 02:55:08 +03:00
|
|
|
|
|
|
|
// the play event can fire before the loadstart event.
|
|
|
|
// in that case we still want the firstplay even to fire.
|
2016-08-04 17:49:32 +02:00
|
|
|
player.tech_.paused = function() {
|
|
|
|
return false;
|
|
|
|
};
|
2014-06-11 02:55:08 +03:00
|
|
|
fpFired = false;
|
|
|
|
// reset the player
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
|
|
|
// player.tech_.trigger('play');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(fpFired, 'Third firstplay fired');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-06-11 02:55:08 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should remove vjs-has-started class', function(assert) {
|
|
|
|
assert.expect(3);
|
2014-04-03 20:41:02 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
2014-04-03 20:41:02 +03:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
|
|
|
player.tech_.trigger('play');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-has-started') !== -1, 'vjs-has-started class added');
|
2014-04-03 20:41:02 +03:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-has-started') === -1, 'vjs-has-started class removed');
|
2014-04-03 20:41:02 +03:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('play');
|
2016-08-25 16:58:42 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-has-started') !== -1, 'vjs-has-started class added again');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-04-03 20:41:02 +03:00
|
|
|
});
|
2014-05-13 03:08:48 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should add and remove vjs-ended class', function(assert) {
|
|
|
|
assert.expect(4);
|
2015-02-13 01:15:44 +02:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
2015-02-13 01:15:44 +02:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
|
|
|
player.tech_.trigger('play');
|
|
|
|
player.tech_.trigger('ended');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-ended') !== -1, 'vjs-ended class added');
|
2015-02-13 01:15:44 +02:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('play');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-ended') === -1, 'vjs-ended class removed');
|
2015-02-13 01:15:44 +02:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('ended');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-ended') !== -1, 'vjs-ended class re-added');
|
2015-02-13 01:15:44 +02:00
|
|
|
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('loadstart');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-ended') === -1, 'vjs-ended class removed');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-02-13 01:15:44 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('player should handle different error types', function(assert) {
|
|
|
|
assert.expect(8);
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({});
|
|
|
|
const testMsg = 'test message';
|
2014-05-13 03:08:48 +03:00
|
|
|
|
|
|
|
// prevent error log messages in the console
|
2015-05-04 01:12:38 +02:00
|
|
|
sinon.stub(log, 'error');
|
2014-05-13 03:08:48 +03:00
|
|
|
|
|
|
|
// error code supplied
|
2016-08-04 17:49:32 +02:00
|
|
|
function errCode() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.error().code, 1, 'error code is correct');
|
2014-05-13 03:08:48 +03:00
|
|
|
}
|
|
|
|
player.on('error', errCode);
|
|
|
|
player.error(1);
|
|
|
|
player.off('error', errCode);
|
|
|
|
|
|
|
|
// error instance supplied
|
2016-08-04 17:49:32 +02:00
|
|
|
function errInst() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.error().code, 2, 'MediaError code is correct');
|
|
|
|
assert.equal(player.error().message, testMsg, 'MediaError message is correct');
|
2014-05-13 03:08:48 +03:00
|
|
|
}
|
|
|
|
player.on('error', errInst);
|
2015-03-26 06:43:41 +02:00
|
|
|
player.error(new MediaError({ code: 2, message: testMsg }));
|
2014-05-13 03:08:48 +03:00
|
|
|
player.off('error', errInst);
|
|
|
|
|
|
|
|
// error message supplied
|
2016-08-04 17:49:32 +02:00
|
|
|
function errMsg() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.error().code, 0, 'error message code is correct');
|
|
|
|
assert.equal(player.error().message, testMsg, 'error message is correct');
|
2014-05-13 03:08:48 +03:00
|
|
|
}
|
|
|
|
player.on('error', errMsg);
|
|
|
|
player.error(testMsg);
|
|
|
|
player.off('error', errMsg);
|
|
|
|
|
|
|
|
// error config supplied
|
2016-08-04 17:49:32 +02:00
|
|
|
function errConfig() {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.error().code, 3, 'error config code is correct');
|
|
|
|
assert.equal(player.error().message, testMsg, 'error config message is correct');
|
2014-05-13 03:08:48 +03:00
|
|
|
}
|
|
|
|
player.on('error', errConfig);
|
|
|
|
player.error({ code: 3, message: testMsg });
|
|
|
|
player.off('error', errConfig);
|
|
|
|
|
|
|
|
// check for vjs-error classname
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf('vjs-error') >= 0, 'player does not have vjs-error classname');
|
2014-05-13 03:08:48 +03:00
|
|
|
|
|
|
|
// restore error logging
|
2015-05-04 01:12:38 +02:00
|
|
|
log.error.restore();
|
2016-08-25 16:58:42 +02:00
|
|
|
|
|
|
|
player.dispose();
|
2014-05-13 03:08:48 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('Data attributes on the video element should persist in the new wrapper element', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const dataId = 123;
|
2014-07-01 22:10:45 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag = TestHelpers.makeTag();
|
2014-07-01 22:10:45 +03:00
|
|
|
|
|
|
|
tag.setAttribute('data-id', dataId);
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
2014-07-01 22:10:45 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.el().getAttribute('data-id'), dataId, 'data-id should be available on the new player element after creation');
|
2016-08-25 16:58:42 +02:00
|
|
|
|
|
|
|
player.dispose();
|
2014-07-01 22:10:45 +03:00
|
|
|
});
|
2014-08-05 01:12:17 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should restore attributes from the original video tag when creating a new element', function(assert) {
|
2014-08-05 01:04:39 +03:00
|
|
|
// simulate attributes stored from the original tag
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag = Dom.createEl('video');
|
|
|
|
|
2015-05-06 20:01:52 +02:00
|
|
|
tag.setAttribute('preload', 'auto');
|
|
|
|
tag.setAttribute('autoplay', '');
|
|
|
|
tag.setAttribute('webkit-playsinline', '');
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const html5Mock = { options_: {tag} };
|
2014-08-05 01:12:17 +03:00
|
|
|
|
2014-08-05 01:04:39 +03:00
|
|
|
// set options that should override tag attributes
|
2015-05-06 20:01:52 +02:00
|
|
|
html5Mock.options_.preload = 'none';
|
2014-08-05 01:12:17 +03:00
|
|
|
|
2014-08-05 01:04:39 +03:00
|
|
|
// create the element
|
2016-08-04 17:49:32 +02:00
|
|
|
const el = Html5.prototype.createEl.call(html5Mock);
|
2014-08-05 01:12:17 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(el.getAttribute('preload'), 'none', 'attribute was successful overridden by an option');
|
|
|
|
assert.equal(el.getAttribute('autoplay'), '', 'autoplay attribute was set properly');
|
|
|
|
assert.equal(el.getAttribute('webkit-playsinline'), '', 'webkit-playsinline attribute was set properly');
|
2014-08-05 01:12:17 +03:00
|
|
|
});
|
2014-08-25 12:28:52 +03:00
|
|
|
|
2017-05-12 22:39:37 +02:00
|
|
|
if (Html5.isSupported()) {
|
|
|
|
QUnit.test('player.playsinline() should be able to get/set playsinline attribute', function(assert) {
|
|
|
|
assert.expect(5);
|
|
|
|
|
|
|
|
const video = document.createElement('video');
|
|
|
|
const player = TestHelpers.makePlayer({techOrder: ['html5']}, video);
|
|
|
|
|
|
|
|
// test setter
|
|
|
|
assert.ok(!player.tech_.el().hasAttribute('playsinline'), 'playsinline has not yet been added');
|
|
|
|
|
|
|
|
player.playsinline(true);
|
|
|
|
|
|
|
|
assert.ok(player.tech_.el().hasAttribute('playsinline'), 'playsinline attribute added');
|
|
|
|
|
|
|
|
player.playsinline(false);
|
|
|
|
|
|
|
|
assert.ok(!player.tech_.el().hasAttribute('playsinline'), 'playsinline attribute removed');
|
|
|
|
|
|
|
|
// test getter
|
|
|
|
player.tech_.el().setAttribute('playsinline', 'playsinline');
|
|
|
|
|
|
|
|
assert.ok(player.playsinline(), 'correctly detects playsinline attribute');
|
|
|
|
|
|
|
|
player.tech_.el().removeAttribute('playsinline');
|
|
|
|
|
|
|
|
assert.ok(!player.playsinline(), 'correctly detects absence of playsinline attribute');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-12-19 18:51:42 +02:00
|
|
|
QUnit.test('if tag exists and movingMediaElementInDOM, re-use the tag', function(assert) {
|
|
|
|
// simulate attributes stored from the original tag
|
|
|
|
const tag = Dom.createEl('video');
|
|
|
|
|
|
|
|
tag.setAttribute('preload', 'auto');
|
|
|
|
tag.setAttribute('autoplay', '');
|
|
|
|
tag.setAttribute('webkit-playsinline', '');
|
|
|
|
|
|
|
|
const html5Mock = {
|
|
|
|
options_: {
|
|
|
|
tag,
|
|
|
|
playerElIngest: false
|
|
|
|
},
|
|
|
|
movingMediaElementInDOM: true
|
|
|
|
};
|
|
|
|
|
|
|
|
// set options that should override tag attributes
|
|
|
|
html5Mock.options_.preload = 'none';
|
|
|
|
|
|
|
|
// create the element
|
|
|
|
const el = Html5.prototype.createEl.call(html5Mock);
|
|
|
|
|
|
|
|
assert.equal(el.getAttribute('preload'), 'none', 'attribute was successful overridden by an option');
|
|
|
|
assert.equal(el.getAttribute('autoplay'), '', 'autoplay attribute was set properly');
|
|
|
|
assert.equal(el.getAttribute('webkit-playsinline'), '', 'webkit-playsinline attribute was set properly');
|
|
|
|
|
|
|
|
assert.equal(el, tag, 'we have re-used the tag as expected');
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('if tag exists and *not* movingMediaElementInDOM, create a new tag', function(assert) {
|
|
|
|
// simulate attributes stored from the original tag
|
|
|
|
const tag = Dom.createEl('video');
|
|
|
|
|
|
|
|
tag.setAttribute('preload', 'auto');
|
|
|
|
tag.setAttribute('autoplay', '');
|
|
|
|
tag.setAttribute('webkit-playsinline', '');
|
|
|
|
|
|
|
|
const html5Mock = {
|
|
|
|
options_: {
|
|
|
|
tag,
|
|
|
|
playerElIngest: false
|
|
|
|
},
|
|
|
|
movingMediaElementInDOM: false
|
|
|
|
};
|
|
|
|
|
|
|
|
// set options that should override tag attributes
|
|
|
|
html5Mock.options_.preload = 'none';
|
|
|
|
|
|
|
|
// create the element
|
|
|
|
const el = Html5.prototype.createEl.call(html5Mock);
|
|
|
|
|
|
|
|
assert.equal(el.getAttribute('preload'), 'none', 'attribute was successful overridden by an option');
|
|
|
|
assert.equal(el.getAttribute('autoplay'), '', 'autoplay attribute was set properly');
|
|
|
|
assert.equal(el.getAttribute('webkit-playsinline'), '', 'webkit-playsinline attribute was set properly');
|
|
|
|
|
|
|
|
assert.notEqual(el, tag, 'we have not re-used the tag as expected');
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('if tag exists and *not* movingMediaElementInDOM, but playerElIngest re-use tag', function(assert) {
|
|
|
|
// simulate attributes stored from the original tag
|
|
|
|
const tag = Dom.createEl('video');
|
|
|
|
|
|
|
|
tag.setAttribute('preload', 'auto');
|
|
|
|
tag.setAttribute('autoplay', '');
|
|
|
|
tag.setAttribute('webkit-playsinline', '');
|
|
|
|
|
|
|
|
const html5Mock = {
|
|
|
|
options_: {
|
|
|
|
tag,
|
|
|
|
playerElIngest: true
|
|
|
|
},
|
|
|
|
movingMediaElementInDOM: false
|
|
|
|
};
|
|
|
|
|
|
|
|
// set options that should override tag attributes
|
|
|
|
html5Mock.options_.preload = 'none';
|
|
|
|
|
|
|
|
// create the element
|
|
|
|
const el = Html5.prototype.createEl.call(html5Mock);
|
|
|
|
|
|
|
|
assert.equal(el.getAttribute('preload'), 'none', 'attribute was successful overridden by an option');
|
|
|
|
assert.equal(el.getAttribute('autoplay'), '', 'autoplay attribute was set properly');
|
|
|
|
assert.equal(el.getAttribute('webkit-playsinline'), '', 'webkit-playsinline attribute was set properly');
|
|
|
|
|
|
|
|
assert.equal(el, tag, 'we have re-used the tag as expected');
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should honor default inactivity timeout', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const clock = sinon.useFakeTimers();
|
2014-08-25 12:35:06 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
// default timeout is 2000ms
|
|
|
|
const player = TestHelpers.makePlayer({});
|
2014-08-25 12:35:06 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), true, 'User is active on creation');
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.tick(1800);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), true, 'User is still active');
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.tick(500);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), false, 'User is inactive after timeout expired');
|
2014-08-25 12:35:06 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.restore();
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-08-25 12:35:06 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should honor configured inactivity timeout', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const clock = sinon.useFakeTimers();
|
2014-08-25 12:28:52 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
// default timeout is 2000ms, set to shorter 200ms
|
|
|
|
const player = TestHelpers.makePlayer({
|
|
|
|
inactivityTimeout: 200
|
|
|
|
});
|
2014-08-25 12:28:52 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), true, 'User is active on creation');
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.tick(150);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), true, 'User is still active');
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.tick(350);
|
|
|
|
// make sure user is now inactive after 500ms
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), false, 'User is inactive after timeout expired');
|
2014-08-25 17:42:58 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.restore();
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-08-25 12:28:52 +03:00
|
|
|
});
|
2014-08-25 12:35:06 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should honor disabled inactivity timeout', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const clock = sinon.useFakeTimers();
|
2014-08-25 12:35:06 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
// default timeout is 2000ms, disable by setting to zero
|
|
|
|
const player = TestHelpers.makePlayer({
|
|
|
|
inactivityTimeout: 0
|
|
|
|
});
|
2014-08-25 12:35:06 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), true, 'User is active on creation');
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.tick(5000);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.userActive(), true, 'User is still active');
|
2014-08-25 12:35:06 +03:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
clock.restore();
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-08-25 12:35:06 +03:00
|
|
|
});
|
2014-09-04 18:51:05 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should clear pending errors on disposal', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const clock = sinon.useFakeTimers();
|
|
|
|
|
|
|
|
const player = TestHelpers.makePlayer();
|
2014-09-04 18:51:05 +03:00
|
|
|
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
clock.tick(1);
|
|
|
|
|
2014-09-04 18:51:05 +03:00
|
|
|
player.src({
|
|
|
|
src: 'http://example.com/movie.unsupported-format',
|
|
|
|
type: 'video/unsupported-format'
|
|
|
|
});
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
|
|
|
clock.tick(1);
|
|
|
|
|
2014-09-04 18:51:05 +03:00
|
|
|
player.dispose();
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
2014-09-04 18:51:05 +03:00
|
|
|
try {
|
|
|
|
clock.tick(5000);
|
|
|
|
} catch (e) {
|
2016-08-12 19:51:31 +02:00
|
|
|
return assert.ok(!e, 'threw an error: ' + e.message);
|
2014-09-04 18:51:05 +03:00
|
|
|
}
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'did not throw an error after disposal');
|
2014-09-04 18:51:05 +03:00
|
|
|
});
|
2014-09-16 20:55:55 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('pause is called when player ended event is fired and player is not paused', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const video = document.createElement('video');
|
|
|
|
const player = TestHelpers.makePlayer({}, video);
|
|
|
|
let pauses = 0;
|
|
|
|
|
2014-09-16 20:55:55 +03:00
|
|
|
player.paused = function() {
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
player.pause = function() {
|
|
|
|
pauses++;
|
|
|
|
};
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('ended');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(pauses, 1, 'pause was called');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-09-16 20:55:55 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('pause is not called if the player is paused and ended is fired', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const video = document.createElement('video');
|
|
|
|
const player = TestHelpers.makePlayer({}, video);
|
|
|
|
let pauses = 0;
|
|
|
|
|
2014-09-16 20:55:55 +03:00
|
|
|
player.paused = function() {
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
player.pause = function() {
|
|
|
|
pauses++;
|
|
|
|
};
|
2015-09-15 02:45:14 +02:00
|
|
|
player.tech_.trigger('ended');
|
2016-08-25 16:58:42 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(pauses, 0, 'pause was not called when ended fired');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-09-16 20:55:55 +03:00
|
|
|
});
|
2014-10-01 04:34:51 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should add an audio class if an audio el is used', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const audio = document.createElement('audio');
|
|
|
|
const player = TestHelpers.makePlayer({}, audio);
|
|
|
|
const audioClass = 'vjs-audio';
|
2014-10-01 04:34:51 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().className.indexOf(audioClass) !== -1, 'added ' + audioClass + ' css class');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2014-10-01 04:34:51 +03:00
|
|
|
});
|
2015-04-28 22:33:20 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should add a video player region if a video el is used', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const video = document.createElement('video');
|
|
|
|
const player = TestHelpers.makePlayer({}, video);
|
2016-04-05 19:47:58 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().getAttribute('role') === 'region', 'region role is present');
|
2017-02-09 00:29:32 +02:00
|
|
|
assert.ok(player.el().getAttribute('aria-label') === 'Video Player', 'Video Player label present');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2016-04-05 19:47:58 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should add an audio player region if an audio el is used', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const audio = document.createElement('audio');
|
|
|
|
const player = TestHelpers.makePlayer({}, audio);
|
2016-04-05 19:47:58 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.el().getAttribute('role') === 'region', 'region role is present');
|
2017-02-09 00:29:32 +02:00
|
|
|
assert.ok(player.el().getAttribute('aria-label') === 'Audio Player', 'Audio Player label present');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2016-04-05 19:47:58 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should not be scrubbing while not seeking', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.scrubbing(), false, 'player is not scrubbing');
|
|
|
|
assert.ok(player.el().className.indexOf('scrubbing') === -1, 'scrubbing class is not present');
|
2015-04-28 22:33:20 +02:00
|
|
|
player.scrubbing(false);
|
2016-08-25 16:58:42 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.scrubbing(), false, 'player is not scrubbing');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-04-28 22:33:20 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should be scrubbing while seeking', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
2015-04-28 22:33:20 +02:00
|
|
|
player.scrubbing(true);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.scrubbing(), true, 'player is scrubbing');
|
|
|
|
assert.ok(player.el().className.indexOf('scrubbing') !== -1, 'scrubbing class is present');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-04-28 22:33:20 +02:00
|
|
|
});
|
2015-04-29 23:05:22 +02:00
|
|
|
|
2017-01-18 07:53:11 +02:00
|
|
|
if (window.Promise) {
|
|
|
|
QUnit.test('play promise should resolve to native promise if returned', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer({});
|
|
|
|
const done = assert.async();
|
|
|
|
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
player.src({
|
|
|
|
src: 'http://example.com/video.mp4',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
2017-01-18 07:53:11 +02:00
|
|
|
player.tech_.play = () => window.Promise.resolve('foo');
|
|
|
|
const p = player.play();
|
|
|
|
|
|
|
|
assert.ok(p, 'play returns something');
|
|
|
|
assert.equal(typeof p.then, 'function', 'play returns a promise');
|
|
|
|
p.then(function(val) {
|
|
|
|
assert.equal(val, 'foo', 'should resolve to native promise value');
|
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
QUnit.test('play promise should resolve to native value if returned', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer({});
|
|
|
|
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
player.src({
|
|
|
|
src: 'http://example.com/video.mp4',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
2017-01-18 07:53:11 +02:00
|
|
|
player.tech_.play = () => 'foo';
|
|
|
|
const p = player.play();
|
|
|
|
|
|
|
|
assert.equal(p, 'foo', 'play returns foo');
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should throw on startup no techs are specified', function(assert) {
|
2015-08-12 22:51:43 +02:00
|
|
|
const techOrder = videojs.options.techOrder;
|
2015-04-29 23:05:22 +02:00
|
|
|
|
2015-08-12 22:51:43 +02:00
|
|
|
videojs.options.techOrder = null;
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.throws(function() {
|
2015-04-29 23:05:22 +02:00
|
|
|
videojs(TestHelpers.makeTag());
|
|
|
|
}, 'a falsey techOrder should throw');
|
|
|
|
|
2015-08-12 22:51:43 +02:00
|
|
|
videojs.options.techOrder = techOrder;
|
2015-04-29 23:05:22 +02:00
|
|
|
});
|
2015-05-01 23:16:19 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should have a sensible toJSON that is equivalent to player.options', function(assert) {
|
2015-05-01 23:16:19 +02:00
|
|
|
const playerOptions = {
|
|
|
|
html5: {
|
|
|
|
nativeTextTracks: false
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const player = TestHelpers.makePlayer(playerOptions);
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.deepEqual(player.toJSON(), player.options_, 'simple player options toJSON produces output equivalent to player.options_');
|
2015-05-01 23:16:19 +02:00
|
|
|
|
|
|
|
const playerOptions2 = {
|
|
|
|
tracks: [{
|
|
|
|
label: 'English',
|
|
|
|
srclang: 'en',
|
|
|
|
src: '../docs/examples/shared/example-captions.vtt',
|
|
|
|
kind: 'captions'
|
|
|
|
}]
|
|
|
|
};
|
|
|
|
|
|
|
|
const player2 = TestHelpers.makePlayer(playerOptions2);
|
|
|
|
|
|
|
|
playerOptions2.tracks[0].player = player2;
|
|
|
|
|
2015-06-05 02:33:34 +02:00
|
|
|
const popts = player2.options_;
|
2016-08-04 17:49:32 +02:00
|
|
|
|
2015-05-01 23:16:19 +02:00
|
|
|
popts.tracks[0].player = undefined;
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.deepEqual(player2.toJSON(), popts, 'no circular references');
|
2016-08-25 16:58:42 +02:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
player2.dispose();
|
2015-05-01 23:16:19 +02:00
|
|
|
});
|
2015-05-20 00:33:52 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should ignore case in language codes and try primary code', function(assert) {
|
|
|
|
assert.expect(3);
|
2015-05-20 00:33:52 +02:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({
|
|
|
|
languages: {
|
2015-05-20 00:33:52 +02:00
|
|
|
'en-gb': {
|
2016-08-04 17:49:32 +02:00
|
|
|
Good: 'Brilliant'
|
2015-05-20 00:33:52 +02:00
|
|
|
},
|
|
|
|
'EN': {
|
2016-08-04 17:49:32 +02:00
|
|
|
Good: 'Awesome',
|
|
|
|
Error: 'Problem'
|
2015-05-20 00:33:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
player.language('en-gb');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.strictEqual(player.localize('Good'), 'Brilliant', 'Used subcode specific localisation');
|
|
|
|
assert.strictEqual(player.localize('Error'), 'Problem', 'Used primary code localisation');
|
2015-05-20 00:33:52 +02:00
|
|
|
player.language('en-GB');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.strictEqual(player.localize('Good'), 'Brilliant', 'Ignored case');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-05-20 00:33:52 +02:00
|
|
|
});
|
2015-10-27 19:46:05 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('inherits language from parent element', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
|
|
|
const oldLang = fixture.getAttribute('lang');
|
2016-07-18 20:53:31 +02:00
|
|
|
|
|
|
|
fixture.setAttribute('lang', 'x-test');
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
2016-07-18 20:53:31 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.language(), 'x-test', 'player inherits parent element language');
|
2016-07-18 20:53:31 +02:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
if (oldLang) {
|
|
|
|
fixture.setAttribute('lang', oldLang);
|
|
|
|
} else {
|
|
|
|
fixture.removeAttribute('lang');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-02-15 22:22:10 +02:00
|
|
|
QUnit.test('sets lang attribute on player el', function(assert) {
|
|
|
|
const fixture = document.getElementById('qunit-fixture');
|
|
|
|
const oldLang = fixture.getAttribute('lang');
|
|
|
|
|
|
|
|
fixture.setAttribute('lang', 'x-attr-test');
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
|
|
|
assert.equal(player.el().getAttribute('lang'), 'x-attr-test', 'player sets lang attribute on self');
|
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
if (oldLang) {
|
|
|
|
fixture.setAttribute('lang', oldLang);
|
|
|
|
} else {
|
|
|
|
fixture.removeAttribute('lang');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should return correct values for canPlayType', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
2015-10-27 19:46:05 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.canPlayType('video/mp4'), 'maybe', 'player can play mp4 files');
|
|
|
|
assert.equal(player.canPlayType('video/unsupported-format'), '', 'player can not play unsupported files');
|
2015-10-27 19:46:05 +02:00
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
2015-10-28 19:28:15 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('createModal()', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const modal = player.createModal('foo');
|
|
|
|
const spy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
modal.on('dispose', spy);
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.expect(5);
|
|
|
|
assert.strictEqual(modal.el().parentNode, player.el(), 'the modal is injected into the player');
|
|
|
|
assert.strictEqual(modal.content(), 'foo', 'content is set properly');
|
|
|
|
assert.ok(modal.opened(), 'modal is opened by default');
|
2015-10-28 19:28:15 +02:00
|
|
|
modal.close();
|
2016-08-25 16:58:42 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(spy.called, 'modal was disposed when closed');
|
|
|
|
assert.strictEqual(player.children().indexOf(modal), -1, 'modal was removed from player\'s children');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-10-28 19:28:15 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('createModal() options object', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const modal = player.createModal('foo', {content: 'bar', label: 'boo'});
|
2015-10-28 19:28:15 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.expect(2);
|
|
|
|
assert.strictEqual(modal.content(), 'foo', 'content argument takes precedence');
|
|
|
|
assert.strictEqual(modal.options_.label, 'boo', 'modal options are set properly');
|
2015-10-28 19:28:15 +02:00
|
|
|
modal.close();
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-10-28 19:28:15 +02:00
|
|
|
});
|
2015-11-24 22:37:34 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('you can clear error in the error event', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
2015-11-24 22:37:34 +02:00
|
|
|
|
|
|
|
sinon.stub(log, 'error');
|
|
|
|
|
|
|
|
player.error({code: 4});
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.error(), 'we have an error');
|
2015-11-24 22:37:34 +02:00
|
|
|
player.error(null);
|
|
|
|
|
|
|
|
player.one('error', function() {
|
|
|
|
player.error(null);
|
|
|
|
});
|
|
|
|
player.error({code: 4});
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!player.error(), 'we no longer have an error');
|
2015-11-24 22:37:34 +02:00
|
|
|
|
|
|
|
log.error.restore();
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2015-11-24 22:37:34 +02:00
|
|
|
});
|
2015-12-07 23:27:33 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('Player#tech will return tech given the appropriate input', function(assert) {
|
2017-01-18 07:40:24 +02:00
|
|
|
const oldLogWarn = log.warn;
|
|
|
|
let warning;
|
|
|
|
|
|
|
|
log.warn = function(_warning) {
|
|
|
|
warning = _warning;
|
|
|
|
};
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const tech_ = {};
|
2017-01-18 07:40:24 +02:00
|
|
|
const returnedTech = Player.prototype.tech.call({tech_}, true);
|
2015-12-07 23:27:33 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(returnedTech, tech_, 'We got back the tech we wanted');
|
2017-01-18 07:40:24 +02:00
|
|
|
assert.notOk(warning, 'no warning was logged');
|
|
|
|
|
|
|
|
log.warn = oldLogWarn;
|
2015-12-07 23:27:33 +02:00
|
|
|
});
|
|
|
|
|
2017-01-18 07:40:24 +02:00
|
|
|
QUnit.test('Player#tech logs a warning when called without a safety argument', function(assert) {
|
|
|
|
const oldLogWarn = log.warn;
|
|
|
|
const warningRegex = new RegExp('https://github.com/videojs/video.js/issues/2617');
|
|
|
|
let warning;
|
2016-08-04 17:49:32 +02:00
|
|
|
|
2017-01-18 07:40:24 +02:00
|
|
|
log.warn = function(_warning) {
|
|
|
|
warning = _warning;
|
2016-08-04 17:49:32 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const tech_ = {};
|
2015-12-07 23:27:33 +02:00
|
|
|
|
2017-01-18 07:40:24 +02:00
|
|
|
Player.prototype.tech.call({tech_});
|
|
|
|
|
|
|
|
assert.ok(warningRegex.test(warning), 'we logged a warning');
|
2015-12-07 23:27:33 +02:00
|
|
|
|
2017-01-18 07:40:24 +02:00
|
|
|
log.warn = oldLogWarn;
|
2015-12-07 23:27:33 +02:00
|
|
|
});
|
2015-12-08 00:45:50 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('player#reset loads the Html5 tech and then techCalls reset', function(assert) {
|
2015-12-08 00:45:50 +02:00
|
|
|
let loadedTech;
|
|
|
|
let loadedSource;
|
|
|
|
let techCallMethod;
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const testPlayer = {
|
2015-12-08 00:45:50 +02:00
|
|
|
options_: {
|
2016-08-04 17:49:32 +02:00
|
|
|
techOrder: ['html5', 'flash']
|
2015-12-08 00:45:50 +02:00
|
|
|
},
|
|
|
|
loadTech_(tech, source) {
|
|
|
|
loadedTech = tech;
|
|
|
|
loadedSource = source;
|
|
|
|
},
|
|
|
|
techCall_(method) {
|
|
|
|
techCallMethod = method;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Player.prototype.reset.call(testPlayer);
|
|
|
|
|
2017-02-02 21:34:33 +02:00
|
|
|
assert.equal(loadedTech, 'html5', 'we loaded the html5 tech');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(loadedSource, null, 'with a null source');
|
|
|
|
assert.equal(techCallMethod, 'reset', 'we then reset the tech');
|
2015-12-08 00:45:50 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('player#reset loads the first item in the techOrder and then techCalls reset', function(assert) {
|
2015-12-08 00:45:50 +02:00
|
|
|
let loadedTech;
|
|
|
|
let loadedSource;
|
|
|
|
let techCallMethod;
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const testPlayer = {
|
2015-12-08 00:45:50 +02:00
|
|
|
options_: {
|
2016-08-04 17:49:32 +02:00
|
|
|
techOrder: ['flash', 'html5']
|
2015-12-08 00:45:50 +02:00
|
|
|
},
|
|
|
|
loadTech_(tech, source) {
|
|
|
|
loadedTech = tech;
|
|
|
|
loadedSource = source;
|
|
|
|
},
|
|
|
|
techCall_(method) {
|
|
|
|
techCallMethod = method;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Player.prototype.reset.call(testPlayer);
|
|
|
|
|
2017-02-02 21:34:33 +02:00
|
|
|
assert.equal(loadedTech, 'flash', 'we loaded the Flash tech');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(loadedSource, null, 'with a null source');
|
|
|
|
assert.equal(techCallMethod, 'reset', 'we then reset the tech');
|
2015-12-08 00:45:50 +02:00
|
|
|
});
|
2016-03-07 21:48:15 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('Remove waiting class on timeupdate after tech waiting', function(assert) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
2016-03-07 21:48:15 +02:00
|
|
|
player.tech_.trigger('waiting');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(/vjs-waiting/.test(player.el().className), 'vjs-waiting is added to the player el on tech waiting');
|
2016-03-07 21:48:15 +02:00
|
|
|
player.trigger('timeupdate');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!(/vjs-waiting/).test(player.el().className), 'vjs-waiting is removed from the player el on timeupdate');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2016-03-07 21:48:15 +02:00
|
|
|
});
|
2016-03-25 20:06:39 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('Make sure that player\'s style el respects VIDEOJS_NO_DYNAMIC_STYLE option', function(assert) {
|
2016-03-25 20:06:39 +02:00
|
|
|
// clear the HEAD before running this test
|
|
|
|
let styles = document.querySelectorAll('style');
|
|
|
|
let i = styles.length;
|
2016-08-04 17:49:32 +02:00
|
|
|
|
2016-03-25 20:06:39 +02:00
|
|
|
while (i--) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const style = styles[i];
|
|
|
|
|
2016-03-25 20:06:39 +02:00
|
|
|
style.parentNode.removeChild(style);
|
|
|
|
}
|
|
|
|
|
|
|
|
let tag = TestHelpers.makeTag();
|
2016-08-04 17:49:32 +02:00
|
|
|
|
2016-03-25 20:06:39 +02:00
|
|
|
tag.id = 'vjs-no-base-theme-tag';
|
|
|
|
tag.width = 600;
|
|
|
|
tag.height = 300;
|
|
|
|
|
|
|
|
window.VIDEOJS_NO_DYNAMIC_STYLE = true;
|
2016-08-04 17:49:32 +02:00
|
|
|
TestHelpers.makePlayer({}, tag);
|
|
|
|
|
2016-03-25 20:06:39 +02:00
|
|
|
styles = document.querySelectorAll('style');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(styles.length, 0, 'we should not get any style elements included in the DOM');
|
2016-03-25 20:06:39 +02:00
|
|
|
|
|
|
|
window.VIDEOJS_NO_DYNAMIC_STYLE = false;
|
2016-03-28 18:08:00 +02:00
|
|
|
tag = TestHelpers.makeTag();
|
2016-08-04 17:49:32 +02:00
|
|
|
TestHelpers.makePlayer({}, tag);
|
2016-03-25 20:06:39 +02:00
|
|
|
styles = document.querySelectorAll('style');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(styles.length, 1, 'we should have one style element in the DOM');
|
|
|
|
assert.equal(styles[0].className, 'vjs-styles-dimensions', 'the class name is the one we expected');
|
2016-03-25 20:06:39 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('When VIDEOJS_NO_DYNAMIC_STYLE is set, apply sizing directly to the tech el', function(assert) {
|
2016-03-25 20:06:39 +02:00
|
|
|
// clear the HEAD before running this test
|
2016-08-04 17:49:32 +02:00
|
|
|
const styles = document.querySelectorAll('style');
|
2016-03-25 20:06:39 +02:00
|
|
|
let i = styles.length;
|
2016-08-04 17:49:32 +02:00
|
|
|
|
2016-03-25 20:06:39 +02:00
|
|
|
while (i--) {
|
2016-08-04 17:49:32 +02:00
|
|
|
const style = styles[i];
|
|
|
|
|
2016-03-25 20:06:39 +02:00
|
|
|
style.parentNode.removeChild(style);
|
|
|
|
}
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
|
2016-03-25 20:06:39 +02:00
|
|
|
tag.id = 'vjs-no-base-theme-tag';
|
|
|
|
tag.width = 600;
|
|
|
|
tag.height = 300;
|
|
|
|
|
|
|
|
window.VIDEOJS_NO_DYNAMIC_STYLE = true;
|
2016-08-04 17:49:32 +02:00
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
2016-03-25 20:06:39 +02:00
|
|
|
|
|
|
|
player.width(300);
|
|
|
|
player.height(600);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.tech_.el().width, 300, 'the width is equal to 300');
|
|
|
|
assert.equal(player.tech_.el().height, 600, 'the height is equal 600');
|
2016-03-25 20:06:39 +02:00
|
|
|
|
|
|
|
player.width(600);
|
|
|
|
player.height(300);
|
2016-08-25 16:58:42 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(player.tech_.el().width, 600, 'the width is equal to 600');
|
|
|
|
assert.equal(player.tech_.el().height, 300, 'the height is equal 300');
|
2016-08-25 16:58:42 +02:00
|
|
|
player.dispose();
|
2016-03-25 20:06:39 +02:00
|
|
|
});
|
2016-11-23 20:52:54 +02:00
|
|
|
|
|
|
|
QUnit.test('should allow to register custom player when any player has not been created', function(assert) {
|
|
|
|
class CustomPlayer extends Player {}
|
|
|
|
videojs.registerComponent('Player', CustomPlayer);
|
|
|
|
|
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
const player = videojs(tag);
|
|
|
|
|
|
|
|
assert.equal(player instanceof CustomPlayer, true, 'player is custom');
|
|
|
|
player.dispose();
|
2016-12-02 21:17:36 +02:00
|
|
|
|
|
|
|
// reset the Player to the original value;
|
|
|
|
videojs.registerComponent('Player', Player);
|
2016-11-23 20:52:54 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('should not allow to register custom player when any player has been created', function(assert) {
|
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
const player = videojs(tag);
|
|
|
|
|
|
|
|
class CustomPlayer extends Player {}
|
2016-12-02 21:17:36 +02:00
|
|
|
|
|
|
|
assert.throws(function() {
|
2016-11-23 20:52:54 +02:00
|
|
|
videojs.registerComponent('Player', CustomPlayer);
|
2016-12-02 21:17:36 +02:00
|
|
|
}, 'Can not register Player component after player has been created');
|
|
|
|
|
|
|
|
player.dispose();
|
2016-11-23 20:52:54 +02:00
|
|
|
|
2016-12-02 21:17:36 +02:00
|
|
|
// reset the Player to the original value;
|
|
|
|
videojs.registerComponent('Player', Player);
|
2016-11-23 20:52:54 +02:00
|
|
|
});
|
2017-01-18 08:52:23 +02:00
|
|
|
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
QUnit.test('techGet runs through middleware if allowedGetter', function(assert) {
|
|
|
|
let cts = 0;
|
|
|
|
let durs = 0;
|
|
|
|
let ps = 0;
|
|
|
|
|
2017-01-27 22:09:27 +02:00
|
|
|
videojs.use('video/foo', () => ({
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
currentTime() {
|
|
|
|
cts++;
|
|
|
|
},
|
|
|
|
duration() {
|
|
|
|
durs++;
|
|
|
|
},
|
|
|
|
paused() {
|
|
|
|
ps++;
|
|
|
|
}
|
2017-01-27 22:09:27 +02:00
|
|
|
}));
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
const player = videojs(tag, {
|
|
|
|
techOrder: ['techFaker']
|
|
|
|
});
|
|
|
|
|
2017-01-27 22:09:27 +02:00
|
|
|
player.middleware_ = [middleware.getMiddleware('video/foo')[0](player)];
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
|
|
|
player.techGet_('currentTime');
|
|
|
|
player.techGet_('duration');
|
|
|
|
player.techGet_('paused');
|
|
|
|
|
|
|
|
assert.equal(cts, 1, 'currentTime is allowed');
|
|
|
|
assert.equal(durs, 1, 'duration is allowed');
|
|
|
|
assert.equal(ps, 0, 'paused is not allowed');
|
|
|
|
|
|
|
|
middleware.getMiddleware('video/foo').pop();
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('techCall runs through middleware if allowedSetter', function(assert) {
|
|
|
|
let cts = 0;
|
|
|
|
let vols = 0;
|
|
|
|
|
2017-01-27 22:09:27 +02:00
|
|
|
videojs.use('video/foo', () => ({
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
setCurrentTime(ct) {
|
|
|
|
cts++;
|
|
|
|
return ct;
|
|
|
|
},
|
|
|
|
setVolume() {
|
|
|
|
vols++;
|
|
|
|
}
|
2017-01-27 22:09:27 +02:00
|
|
|
}));
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
const player = videojs(tag, {
|
|
|
|
techOrder: ['techFaker']
|
|
|
|
});
|
|
|
|
|
2017-01-27 22:09:27 +02:00
|
|
|
player.middleware_ = [middleware.getMiddleware('video/foo')[0](player)];
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
player.techCall_('setCurrentTime', 10);
|
|
|
|
player.techCall_('setVolume', 0.5);
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
assert.equal(cts, 1, 'setCurrentTime is allowed');
|
|
|
|
assert.equal(vols, 0, 'setVolume is not allowed');
|
|
|
|
|
|
|
|
middleware.getMiddleware('video/foo').pop();
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('src selects tech based on middleware', function(assert) {
|
2017-02-02 21:34:33 +02:00
|
|
|
const oldTechs = Tech.techs_;
|
|
|
|
const oldDefaultTechOrder = Tech.defaultTechOrder_;
|
|
|
|
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
class FooTech extends Html5 {}
|
|
|
|
class BarTech extends Html5 {}
|
|
|
|
|
|
|
|
FooTech.isSupported = () => true;
|
|
|
|
FooTech.canPlayType = (type) => type === 'video/mp4';
|
|
|
|
FooTech.canPlaySource = (src) => FooTech.canPlayType(src.type);
|
|
|
|
|
|
|
|
BarTech.isSupported = () => true;
|
|
|
|
BarTech.canPlayType = (type) => type === 'video/flv';
|
|
|
|
BarTech.canPlaySource = (src) => BarTech.canPlayType(src.type);
|
|
|
|
|
|
|
|
videojs.registerTech('FooTech', FooTech);
|
|
|
|
videojs.registerTech('BarTech', BarTech);
|
|
|
|
|
2017-01-27 22:09:27 +02:00
|
|
|
videojs.use('video/foo', () => ({
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
setSource(src, next) {
|
|
|
|
next(null, {
|
|
|
|
src: 'http://example.com/video.mp4',
|
|
|
|
type: 'video/mp4'
|
|
|
|
});
|
|
|
|
}
|
2017-01-27 22:09:27 +02:00
|
|
|
}));
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
2017-01-27 22:09:27 +02:00
|
|
|
videojs.use('video/bar', () => ({
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
setSource(src, next) {
|
|
|
|
next(null, {
|
|
|
|
src: 'http://example.com/video.flv',
|
|
|
|
type: 'video/flv'
|
|
|
|
});
|
|
|
|
}
|
2017-01-27 22:09:27 +02:00
|
|
|
}));
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
|
|
|
|
const tag = TestHelpers.makeTag();
|
|
|
|
const player = videojs(tag, {
|
|
|
|
techOrder: ['fooTech', 'barTech']
|
|
|
|
});
|
|
|
|
|
|
|
|
player.src({
|
|
|
|
src: 'foo',
|
|
|
|
type: 'video/foo'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
assert.equal(player.techName_, 'FooTech', 'the FooTech (html5) tech is chosen');
|
|
|
|
|
|
|
|
player.src({
|
|
|
|
src: 'bar',
|
|
|
|
type: 'video/bar'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
assert.equal(player.techName_, 'BarTech', 'the BarTech (Flash) tech is chosen');
|
|
|
|
|
|
|
|
middleware.getMiddleware('video/foo').pop();
|
|
|
|
middleware.getMiddleware('video/bar').pop();
|
|
|
|
player.dispose();
|
|
|
|
delete Tech.techs_.FooTech;
|
|
|
|
delete Tech.techs_.BarTech;
|
2017-02-02 21:34:33 +02:00
|
|
|
|
|
|
|
Tech.defaultTechOrder_ = oldDefaultTechOrder;
|
|
|
|
Tech.techs_ = oldTechs;
|
|
|
|
|
feat: middleware (#3788)
Add middleware support. Middleware can function as go-between between the player and the tech. For example, it can modify the duration that the tech returns to the player. In addition, middleware allow for supporting custom video sources and types.
Currently, middleware can only intercept timeline methods like duration, currentTime, and setCurrentTime.
For example,
```js
videojs.use('video/foo', {
setSource(src, next) {
next(null, {
src: 'http://example.com/video.mp4',
type: 'video/mp4'
});
}
});
```
Will allow you to set a source with type `video/foo` which will play back `video.mp4`.
This makes setting the source asynchronous, which aligns it with the spec a bit more. Methods like play can still be called synchronously on the player after setting the source and the player will play once the source has loaded.
`sourceOrder` option was removed as well and it will now always use source ordering.
BREAKING CHANGE: setting the source is now asynchronous. `sourceOrder` option removed and made the default.
2017-01-20 00:29:09 +02:00
|
|
|
});
|
|
|
|
|
2017-04-12 23:17:33 +02:00
|
|
|
QUnit.test('src_ does not call loadTech is name is titleCaseEquals', function(assert) {
|
|
|
|
let loadTechCalled = 0;
|
|
|
|
const playerProxy = {
|
|
|
|
selectSource() {
|
|
|
|
return {
|
|
|
|
tech: 'html5'
|
|
|
|
};
|
|
|
|
},
|
|
|
|
techName_: 'Html5',
|
|
|
|
ready() {},
|
|
|
|
loadTech_() {
|
|
|
|
loadTechCalled++;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Player.prototype.src_.call(playerProxy);
|
|
|
|
|
|
|
|
assert.equal(loadTechCalled, 0, 'loadTech was not called');
|
|
|
|
});
|
|
|
|
|
2017-01-18 08:52:23 +02:00
|
|
|
QUnit.test('options: plugins', function(assert) {
|
|
|
|
const optionsSpy = sinon.spy();
|
|
|
|
|
|
|
|
Plugin.registerPlugin('foo', (options) => {
|
|
|
|
optionsSpy(options);
|
|
|
|
});
|
|
|
|
|
|
|
|
const player = TestHelpers.makePlayer({
|
|
|
|
plugins: {
|
|
|
|
foo: {
|
|
|
|
bar: 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.strictEqual(optionsSpy.callCount, 1, 'the plugin was set up');
|
|
|
|
assert.deepEqual(optionsSpy.getCall(0).args[0], {bar: 1}, 'the plugin got the expected options');
|
|
|
|
|
|
|
|
assert.throws(
|
|
|
|
() => {
|
|
|
|
TestHelpers.makePlayer({
|
|
|
|
plugins: {
|
|
|
|
nope: {}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
new Error('plugin "nope" does not exist'),
|
|
|
|
'plugins that do not exist cause the player to throw'
|
|
|
|
);
|
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
Plugin.deregisterPlugin('foo');
|
|
|
|
});
|
2017-05-11 23:15:12 +02:00
|
|
|
|
|
|
|
QUnit.test('should add a class with major version', function(assert) {
|
|
|
|
const majorVersion = require('../../package.json').version.split('.')[0];
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
|
|
|
assert.ok(player.hasClass('vjs-v' + majorVersion), 'the version class should be added to the player');
|
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
2017-07-14 20:20:37 +02:00
|
|
|
|
|
|
|
QUnit.test('player.duration() returns NaN if player.cache_.duration is undefined', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
|
|
|
player.cache_.duration = undefined;
|
|
|
|
assert.ok(Number.isNaN(player.duration()), 'returned NaN for unkown duration');
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('player.duration() returns player.cache_.duration if it is defined', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
|
|
|
player.cache_.duration = 200;
|
|
|
|
assert.equal(player.duration(), 200, 'returned correct integer duration');
|
|
|
|
player.cache_.duration = 942;
|
|
|
|
assert.equal(player.duration(), 942, 'returned correct integer duration');
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('player.duration() sets the value of player.cache_.duration', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
|
|
|
|
// set an arbitrary initial cached duration value for testing the setter functionality
|
|
|
|
player.cache_.duration = 1;
|
|
|
|
|
|
|
|
player.duration(NaN);
|
|
|
|
assert.ok(Number.isNaN(player.duration()), 'duration() set and get NaN duration value');
|
|
|
|
player.duration(200);
|
|
|
|
assert.equal(player.duration(), 200, 'duration() set and get integer duration value');
|
|
|
|
});
|