2016-08-16 00:20:47 +02:00
|
|
|
/* eslint-env qunit, browser */
|
2016-08-03 21:27:03 +02:00
|
|
|
let player;
|
|
|
|
let tech;
|
2014-05-17 00:48:05 +03:00
|
|
|
|
2015-05-04 01:12:38 +02:00
|
|
|
import Html5 from '../../../src/js/tech/html5.js';
|
|
|
|
import * as browser from '../../../src/js/utils/browser.js';
|
2015-03-26 06:43:41 +02:00
|
|
|
import document from 'global/document';
|
2020-04-22 18:40:26 +02:00
|
|
|
import sinon from 'sinon';
|
2015-03-11 03:01:11 +02:00
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
QUnit.module('HTML5', {
|
2016-08-12 19:51:31 +02:00
|
|
|
beforeEach(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const el = document.createElement('div');
|
2014-05-17 00:48:05 +03:00
|
|
|
|
|
|
|
el.innerHTML = '<div />';
|
|
|
|
player = {
|
2016-08-03 21:27:03 +02:00
|
|
|
id() {
|
|
|
|
return 'id';
|
|
|
|
},
|
|
|
|
el() {
|
|
|
|
return el;
|
|
|
|
},
|
2014-05-17 00:48:05 +03:00
|
|
|
options_: {},
|
2016-08-03 21:27:03 +02:00
|
|
|
options() {
|
|
|
|
return this.options_;
|
|
|
|
},
|
|
|
|
bufferedPercent() {
|
|
|
|
return 0;
|
|
|
|
},
|
|
|
|
controls() {
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
usingNativeControls() {
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
on() {
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
off() {
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
ready() {},
|
|
|
|
addChild() {},
|
|
|
|
trigger() {}
|
2014-05-17 00:48:05 +03:00
|
|
|
};
|
2015-05-06 20:01:52 +02:00
|
|
|
tech = new Html5({});
|
2014-05-17 00:48:05 +03:00
|
|
|
},
|
2016-08-12 19:51:31 +02:00
|
|
|
afterEach(assert) {
|
2014-05-17 00:48:05 +03:00
|
|
|
tech.dispose();
|
|
|
|
player = null;
|
|
|
|
tech = null;
|
|
|
|
}
|
|
|
|
});
|
2013-03-02 01:11:20 +03:00
|
|
|
|
2020-07-13 18:00:17 +02:00
|
|
|
QUnit[browser.IS_ANY_SAFARI ? 'test' : 'skip']('if setScrubbing is true and fastSeek is available, use it', function(assert) {
|
2020-04-22 18:40:26 +02:00
|
|
|
Object.defineProperty(tech.el(), 'currentTime', {
|
|
|
|
get: () => {},
|
|
|
|
set: () => {},
|
|
|
|
|
|
|
|
writeable: true,
|
|
|
|
enumerable: false,
|
|
|
|
configurable: true
|
|
|
|
});
|
|
|
|
|
|
|
|
const currentTimeSpy = sinon.spy(tech.el(), 'currentTime', ['set']);
|
|
|
|
|
|
|
|
tech.setCurrentTime(5);
|
|
|
|
assert.ok(currentTimeSpy.set.called, 'currentTime setter was called');
|
|
|
|
assert.ok(currentTimeSpy.set.calledWith(5), 'currentTime setter was called with 5');
|
|
|
|
|
|
|
|
tech.setScrubbing(true);
|
|
|
|
|
|
|
|
// when scrubbing is set but fastSeek isn't available, currentTime should still be called
|
|
|
|
tech.el().fastSeek = null;
|
|
|
|
tech.setCurrentTime(10);
|
|
|
|
assert.ok(currentTimeSpy.set.called, 'currentTime setter was called');
|
|
|
|
assert.ok(currentTimeSpy.set.calledWith(10), 'currentTime setter was called with 10');
|
|
|
|
|
|
|
|
const fastSeekSpy = tech.el().fastSeek = sinon.spy();
|
|
|
|
|
|
|
|
tech.setCurrentTime(15);
|
|
|
|
assert.ok(currentTimeSpy.set.calledTwice, 'currentTime setter was only called twice and not a 3rd time for fastSeek');
|
|
|
|
assert.ok(fastSeekSpy.called, 'fastSeek called');
|
|
|
|
assert.ok(fastSeekSpy.calledWith(15), 'fastSeek called with 15');
|
|
|
|
});
|
|
|
|
|
2017-05-12 22:39:37 +02:00
|
|
|
QUnit.test('should be able to set playsinline attribute', function(assert) {
|
|
|
|
assert.expect(2);
|
|
|
|
|
|
|
|
tech.createEl();
|
|
|
|
tech.setPlaysinline(true);
|
|
|
|
|
|
|
|
assert.ok(tech.el().hasAttribute('playsinline'), 'playsinline attribute was added');
|
|
|
|
|
|
|
|
tech.setPlaysinline(false);
|
|
|
|
|
|
|
|
assert.ok(!tech.el().hasAttribute('playsinline'), 'playsinline attribute was removed');
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should detect whether the volume can be changed', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
|
|
|
|
if (!{}.__defineSetter__) {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'your browser does not support this test, skipping it');
|
2013-03-06 02:07:35 +03:00
|
|
|
return;
|
|
|
|
}
|
2016-08-03 21:27:03 +02:00
|
|
|
const testVid = Html5.TEST_VID;
|
|
|
|
const ConstVolumeVideo = function() {
|
2013-03-05 21:38:47 +03:00
|
|
|
this.volume = 1;
|
2016-08-03 21:27:03 +02:00
|
|
|
this.__defineSetter__('volume', function() {});
|
2013-03-05 21:38:47 +03:00
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
|
2015-05-04 01:12:38 +02:00
|
|
|
Html5.TEST_VID = new ConstVolumeVideo();
|
2013-03-02 01:11:20 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!Html5.canControlVolume());
|
2015-05-04 01:12:38 +02:00
|
|
|
Html5.TEST_VID = testVid;
|
2013-03-02 01:11:20 +03:00
|
|
|
});
|
2013-03-08 04:57:52 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('test playbackRate', function(assert) {
|
2014-09-03 03:38:11 +03:00
|
|
|
// Android 2.3 always returns 0 for playback rate
|
2015-03-11 03:01:11 +02:00
|
|
|
if (!Html5.canControlPlaybackRate()) {
|
2017-01-18 21:59:15 +02:00
|
|
|
assert.ok(true, 'Playback rate is not supported');
|
2014-09-03 03:38:11 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-17 00:48:05 +03:00
|
|
|
tech.createEl();
|
|
|
|
|
|
|
|
tech.el().playbackRate = 1.25;
|
2017-01-18 21:59:15 +02:00
|
|
|
assert.strictEqual(tech.playbackRate(), 1.25, 'can be changed from the element');
|
2014-05-17 00:48:05 +03:00
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
tech.setPlaybackRate(0.75);
|
2017-01-18 21:59:15 +02:00
|
|
|
assert.strictEqual(tech.playbackRate(), 0.75, 'can be changed from the API');
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('test defaultPlaybackRate', function(assert) {
|
|
|
|
// Android 2.3 always returns 0 for playback rate
|
|
|
|
if (!Html5.canControlPlaybackRate()) {
|
|
|
|
assert.ok(true, 'Playback rate is not supported');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tech.createEl();
|
|
|
|
|
|
|
|
tech.el().defaultPlaybackRate = 1.25;
|
|
|
|
assert.strictEqual(tech.defaultPlaybackRate(), 1.25, 'can be changed from the element');
|
|
|
|
|
|
|
|
tech.setDefaultPlaybackRate(0.75);
|
|
|
|
assert.strictEqual(tech.defaultPlaybackRate(), 0.75, 'can be changed from the API');
|
|
|
|
});
|
|
|
|
|
2017-05-11 22:59:22 +02:00
|
|
|
QUnit.test('blacklist playbackRate support on older verisons of Chrome on Android', function(assert) {
|
|
|
|
if (!Html5.canControlPlaybackRate()) {
|
|
|
|
assert.ok(true, 'playbackRate is not supported');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset playbackrate - Firefox's rounding of playbackRate causes the rate not to change in canControlPlaybackRate() after a few instances
|
|
|
|
Html5.TEST_VID.playbackRate = 1;
|
|
|
|
|
|
|
|
const oldIsAndroid = browser.IS_ANDROID;
|
|
|
|
const oldIsChrome = browser.IS_CHROME;
|
|
|
|
const oldChromeVersion = browser.CHROME_VERSION;
|
|
|
|
|
2019-08-30 20:56:41 +02:00
|
|
|
browser.stub_IS_ANDROID(true);
|
|
|
|
browser.stub_IS_CHROME(true);
|
|
|
|
browser.stub_CHROME_VERSION(50);
|
2017-05-11 22:59:22 +02:00
|
|
|
assert.strictEqual(Html5.canControlPlaybackRate(), false, 'canControlPlaybackRate should return false on older Chrome');
|
|
|
|
|
2019-08-30 20:56:41 +02:00
|
|
|
browser.stub_CHROME_VERSION(58);
|
2017-05-11 22:59:22 +02:00
|
|
|
assert.strictEqual(Html5.canControlPlaybackRate(), true, 'canControlPlaybackRate should return true on newer Chrome');
|
|
|
|
|
2019-08-30 20:56:41 +02:00
|
|
|
browser.stub_IS_ANDROID(oldIsAndroid);
|
|
|
|
browser.stub_IS_CHROME(oldIsChrome);
|
|
|
|
browser.stub_CHROME_VERSION(oldChromeVersion);
|
2017-05-11 22:59:22 +02:00
|
|
|
});
|
|
|
|
|
2017-01-18 21:59:15 +02:00
|
|
|
QUnit.test('test volume', function(assert) {
|
|
|
|
if (!Html5.canControlVolume()) {
|
|
|
|
assert.ok(true, 'Volume is not supported');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tech.createEl();
|
|
|
|
|
2017-01-19 18:17:46 +02:00
|
|
|
tech.el().volume = 0.5;
|
|
|
|
assert.strictEqual(tech.volume(), 0.5, 'can be changed from the element');
|
2017-01-18 21:59:15 +02:00
|
|
|
|
2017-01-19 18:17:46 +02:00
|
|
|
tech.setVolume(1);
|
|
|
|
assert.strictEqual(tech.volume(), 1, 'can be changed from the API');
|
2017-01-18 21:59:15 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('test defaultMuted', function(assert) {
|
|
|
|
tech.createEl();
|
|
|
|
|
|
|
|
tech.el().defaultMuted = true;
|
|
|
|
assert.strictEqual(tech.defaultMuted(), true, 'can be changed from the element');
|
|
|
|
|
|
|
|
tech.setDefaultMuted(false);
|
|
|
|
assert.strictEqual(tech.defaultMuted(), false, 'can be changed from the API');
|
2014-05-17 00:48:05 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should export played', function(assert) {
|
2015-07-21 22:56:23 +02:00
|
|
|
tech.createEl();
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.deepEqual(tech.played(), tech.el().played, 'returns the played attribute');
|
2015-07-21 22:56:23 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should remove the controls attribute when recreating the element', function(assert) {
|
2014-10-04 01:24:22 +03:00
|
|
|
player.tagAttributes = {
|
|
|
|
controls: true
|
|
|
|
};
|
|
|
|
// force custom controls so the test environment is equivalent on iOS
|
2016-08-03 21:27:03 +02:00
|
|
|
player.options_.nativeControlsForTouch = false;
|
|
|
|
const el = tech.createEl();
|
2014-10-04 01:24:22 +03:00
|
|
|
|
2015-02-17 23:49:32 +02:00
|
|
|
// On the iPhone controls are always true
|
2015-05-04 01:12:38 +02:00
|
|
|
if (!browser.IS_IPHONE) {
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!el.controls, 'controls attribute is absent');
|
2015-02-17 23:49:32 +02:00
|
|
|
}
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(player.tagAttributes.controls, 'tag attribute is still present');
|
2014-10-04 01:24:22 +03:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('error events may not set the errors property', function(assert) {
|
|
|
|
assert.equal(tech.error(), undefined, 'no tech-level error');
|
2014-09-04 19:12:36 +03:00
|
|
|
tech.trigger('error');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(true, 'no error was thrown');
|
2014-09-04 19:12:36 +03:00
|
|
|
});
|
2014-12-03 00:22:34 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should have the source handler interface', function(assert) {
|
|
|
|
assert.ok(Html5.registerSourceHandler, 'has the registerSourceHandler function');
|
2014-12-03 00:22:34 +02:00
|
|
|
});
|
2015-01-16 21:42:27 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('native source handler canPlayType', function(assert) {
|
2015-10-27 19:46:05 +02:00
|
|
|
// Stub the test video canPlayType (used in canPlayType) to control results
|
2016-08-03 21:27:03 +02:00
|
|
|
const origCPT = Html5.TEST_VID.canPlayType;
|
|
|
|
|
|
|
|
Html5.TEST_VID.canPlayType = function(type) {
|
2015-10-27 19:46:05 +02:00
|
|
|
if (type === 'video/mp4') {
|
|
|
|
return 'maybe';
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
};
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const canPlayType = Html5.nativeSourceHandler.canPlayType;
|
2015-10-27 19:46:05 +02:00
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
canPlayType('video/mp4'),
|
|
|
|
'maybe',
|
|
|
|
'Native source handler reported type support'
|
|
|
|
);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(canPlayType('foo'), '', 'Native source handler handled bad type');
|
2015-10-27 19:46:05 +02:00
|
|
|
|
|
|
|
// Reset test video canPlayType
|
|
|
|
Html5.TEST_VID.canPlayType = origCPT;
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('native source handler canHandleSource', function(assert) {
|
2015-01-16 21:42:27 +02:00
|
|
|
// Stub the test video canPlayType (used in canHandleSource) to control results
|
2016-08-03 21:27:03 +02:00
|
|
|
const origCPT = Html5.TEST_VID.canPlayType;
|
|
|
|
|
|
|
|
Html5.TEST_VID.canPlayType = function(type) {
|
2015-01-16 21:42:27 +02:00
|
|
|
if (type === 'video/mp4') {
|
|
|
|
return 'maybe';
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
};
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const canHandleSource = Html5.nativeSourceHandler.canHandleSource;
|
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
canHandleSource({ type: 'video/mp4', src: 'video.flv' }, {}),
|
|
|
|
'maybe',
|
|
|
|
'Native source handler reported type support'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
canHandleSource({ src: 'http://www.example.com/video.mp4' }, {}),
|
|
|
|
'maybe',
|
|
|
|
'Native source handler reported extension support'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
canHandleSource({ src: 'https://example.com/video.sd.mp4?s=foo&token=bar' }, {}),
|
|
|
|
'maybe',
|
|
|
|
'Native source handler reported extension support'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
canHandleSource({ src: 'https://example.com/video.sd.mp4?s=foo' }, {}),
|
|
|
|
'maybe',
|
|
|
|
'Native source handler reported extension support'
|
|
|
|
);
|
2015-01-22 03:55:35 +02:00
|
|
|
|
2015-01-16 21:42:27 +02:00
|
|
|
// Test for issue videojs/video.js#1785 and other potential failures
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
canHandleSource({ src: '' }, {}),
|
|
|
|
'',
|
|
|
|
'Native source handler handled empty src'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
canHandleSource({}, {}),
|
|
|
|
'',
|
|
|
|
'Native source handler handled empty object'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
canHandleSource({ src: 'foo' }, {}),
|
|
|
|
'',
|
|
|
|
'Native source handler handled bad src'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
canHandleSource({ type: 'foo' }, {}),
|
|
|
|
'',
|
|
|
|
'Native source handler handled bad type'
|
|
|
|
);
|
2015-01-16 21:42:27 +02:00
|
|
|
|
|
|
|
// Reset test video canPlayType
|
2015-05-04 01:12:38 +02:00
|
|
|
Html5.TEST_VID.canPlayType = origCPT;
|
2015-01-16 21:42:27 +02:00
|
|
|
});
|
2015-08-03 21:19:36 +02:00
|
|
|
|
|
|
|
if (Html5.supportsNativeTextTracks()) {
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('add native textTrack listeners on startup', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const tt = {
|
2015-08-03 21:19:36 +02:00
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => adds.push([type, fn]),
|
2016-08-03 21:27:03 +02:00
|
|
|
removeEventListener: (type, fn) => rems.push([type, fn])
|
2015-08-03 21:19:36 +02:00
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
const el = document.createElement('div');
|
|
|
|
|
2015-08-03 21:19:36 +02:00
|
|
|
el.textTracks = tt;
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const htmlTech = new Html5({el});
|
2015-08-03 21:19:36 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(adds[0][0], 'change', 'change event handler added');
|
|
|
|
assert.equal(adds[1][0], 'addtrack', 'addtrack event handler added');
|
|
|
|
assert.equal(adds[2][0], 'removetrack', 'removetrack event handler added');
|
2019-03-18 21:49:48 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
2015-08-03 21:19:36 +02:00
|
|
|
});
|
|
|
|
|
2016-11-23 21:09:32 +02:00
|
|
|
QUnit.test('does not add native textTrack listeners when disabled', function(assert) {
|
|
|
|
const events = [];
|
|
|
|
const tt = {
|
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => events.push([type, fn]),
|
|
|
|
removeEventListener: (type, fn) => events.push([type, fn])
|
|
|
|
};
|
2018-03-07 21:28:37 +02:00
|
|
|
const el = document.createElement('video');
|
2016-11-23 21:09:32 +02:00
|
|
|
|
2018-03-07 21:28:37 +02:00
|
|
|
Object.defineProperty(el, 'textTracks', {
|
|
|
|
get: () => tt
|
|
|
|
});
|
2016-11-23 21:09:32 +02:00
|
|
|
|
|
|
|
const htmlTech = new Html5({el, nativeTextTracks: false});
|
|
|
|
|
|
|
|
assert.equal(events.length, 0, 'no listeners added');
|
|
|
|
|
|
|
|
const htmlTechAlternate = new Html5({el, nativeCaptions: false});
|
|
|
|
|
|
|
|
assert.equal(events.length, 0, 'no listeners added');
|
2019-03-18 21:49:48 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
|
|
|
htmlTechAlternate.dispose();
|
2016-11-23 21:09:32 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('remove all tracks from emulated list on dispose', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const tt = {
|
2015-08-03 21:19:36 +02:00
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => adds.push([type, fn]),
|
2016-08-03 21:27:03 +02:00
|
|
|
removeEventListener: (type, fn) => rems.push([type, fn])
|
2015-08-03 21:19:36 +02:00
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
const el = document.createElement('div');
|
|
|
|
|
2015-08-03 21:19:36 +02:00
|
|
|
el.textTracks = tt;
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const htmlTech = new Html5({el});
|
|
|
|
|
2015-08-03 21:19:36 +02:00
|
|
|
htmlTech.dispose();
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(adds[0][0], 'change', 'change event handler added');
|
|
|
|
assert.equal(adds[1][0], 'addtrack', 'addtrack event handler added');
|
|
|
|
assert.equal(adds[2][0], 'removetrack', 'removetrack event handler added');
|
|
|
|
assert.equal(rems[0][0], 'change', 'change event handler removed');
|
|
|
|
assert.equal(rems[1][0], 'addtrack', 'addtrack event handler removed');
|
|
|
|
assert.equal(rems[2][0], 'removetrack', 'removetrack event handler removed');
|
|
|
|
assert.equal(adds[0][0], rems[0][0], 'change event handler removed');
|
|
|
|
assert.equal(adds[1][0], rems[1][0], 'addtrack event handler removed');
|
|
|
|
assert.equal(adds[2][0], rems[2][0], 'removetrack event handler removed');
|
2015-08-03 21:19:36 +02:00
|
|
|
});
|
|
|
|
}
|
2016-04-22 20:31:12 +02:00
|
|
|
|
|
|
|
if (Html5.supportsNativeAudioTracks()) {
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('add native audioTrack listeners on startup', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const at = {
|
2016-04-22 20:31:12 +02:00
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => adds.push([type, fn]),
|
2016-08-03 21:27:03 +02:00
|
|
|
removeEventListener: (type, fn) => rems.push([type, fn])
|
2016-04-22 20:31:12 +02:00
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
const el = document.createElement('div');
|
|
|
|
|
2016-04-22 20:31:12 +02:00
|
|
|
el.audioTracks = at;
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const htmlTech = new Html5({el});
|
2016-04-22 20:31:12 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(adds[0][0], 'change', 'change event handler added');
|
|
|
|
assert.equal(adds[1][0], 'addtrack', 'addtrack event handler added');
|
|
|
|
assert.equal(adds[2][0], 'removetrack', 'removetrack event handler added');
|
2019-03-18 21:49:48 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
2016-04-22 20:31:12 +02:00
|
|
|
});
|
|
|
|
|
2016-11-23 21:09:32 +02:00
|
|
|
QUnit.test('does not add native audioTrack listeners when disabled', function(assert) {
|
|
|
|
const events = [];
|
|
|
|
const at = {
|
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => events.push([type, fn]),
|
|
|
|
removeEventListener: (type, fn) => events.push([type, fn])
|
|
|
|
};
|
|
|
|
const el = document.createElement('div');
|
|
|
|
|
|
|
|
el.audioTracks = at;
|
|
|
|
|
|
|
|
const htmlTech = new Html5({el, nativeAudioTracks: false});
|
|
|
|
|
|
|
|
assert.equal(events.length, 0, 'no listeners added');
|
2019-03-18 21:49:48 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
2016-11-23 21:09:32 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('remove all tracks from emulated list on dispose', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const at = {
|
2016-04-22 20:31:12 +02:00
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => adds.push([type, fn]),
|
2016-08-03 21:27:03 +02:00
|
|
|
removeEventListener: (type, fn) => rems.push([type, fn])
|
2016-04-22 20:31:12 +02:00
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
const el = document.createElement('div');
|
|
|
|
|
2016-04-22 20:31:12 +02:00
|
|
|
el.audioTracks = at;
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const htmlTech = new Html5({el});
|
|
|
|
|
2016-04-22 20:31:12 +02:00
|
|
|
htmlTech.dispose();
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(adds[0][0], 'change', 'change event handler added');
|
|
|
|
assert.equal(adds[1][0], 'addtrack', 'addtrack event handler added');
|
|
|
|
assert.equal(adds[2][0], 'removetrack', 'removetrack event handler added');
|
|
|
|
assert.equal(rems[0][0], 'change', 'change event handler removed');
|
|
|
|
assert.equal(rems[1][0], 'addtrack', 'addtrack event handler removed');
|
|
|
|
assert.equal(rems[2][0], 'removetrack', 'removetrack event handler removed');
|
|
|
|
assert.equal(adds[0][0], rems[0][0], 'change event handler removed');
|
|
|
|
assert.equal(adds[1][0], rems[1][0], 'addtrack event handler removed');
|
|
|
|
assert.equal(adds[2][0], rems[2][0], 'removetrack event handler removed');
|
2016-04-22 20:31:12 +02:00
|
|
|
});
|
2018-04-19 19:16:01 +02:00
|
|
|
|
|
|
|
QUnit.test('should use overrideNativeTracks on audio correctly', function(assert) {
|
|
|
|
assert.expect(8);
|
|
|
|
|
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const at = {
|
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => {
|
|
|
|
adds.push({ type, fn });
|
|
|
|
},
|
|
|
|
removeEventListener: (type, fn) => {
|
|
|
|
rems.push({ type, fn });
|
|
|
|
}
|
|
|
|
};
|
2018-04-20 02:11:11 +02:00
|
|
|
|
2018-04-19 19:16:01 +02:00
|
|
|
const el = document.createElement('div');
|
|
|
|
|
|
|
|
el.audioTracks = at;
|
|
|
|
|
|
|
|
const htmlTech = new Html5({el});
|
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 3,
|
|
|
|
'should have added change, remove, add listeners'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 0,
|
|
|
|
'no listeners should be removed'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-04-20 02:11:11 +02:00
|
|
|
htmlTech.overrideNativeAudioTracks(true);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 3,
|
|
|
|
'should not have added additional listeners'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 3,
|
|
|
|
'should have removed previous three listeners'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-04-20 02:11:11 +02:00
|
|
|
htmlTech.overrideNativeAudioTracks(true);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 3,
|
|
|
|
'no state change so do not add listeners'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 3,
|
|
|
|
'no state change so do not remove listeners'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-04-20 02:11:11 +02:00
|
|
|
htmlTech.overrideNativeAudioTracks(false);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 6,
|
|
|
|
'should add listeners because native tracks should be proxied'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 3,
|
|
|
|
'should not remove listeners because there where none added on previous state'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
|
|
|
});
|
2016-04-22 20:31:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Html5.supportsNativeVideoTracks()) {
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('add native videoTrack listeners on startup', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const vt = {
|
2016-04-22 20:31:12 +02:00
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => adds.push([type, fn]),
|
2016-08-03 21:27:03 +02:00
|
|
|
removeEventListener: (type, fn) => rems.push([type, fn])
|
2016-04-22 20:31:12 +02:00
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
const el = document.createElement('div');
|
|
|
|
|
2016-04-22 20:31:12 +02:00
|
|
|
el.videoTracks = vt;
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const htmlTech = new Html5({el});
|
2016-04-22 20:31:12 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(adds[0][0], 'change', 'change event handler added');
|
|
|
|
assert.equal(adds[1][0], 'addtrack', 'addtrack event handler added');
|
|
|
|
assert.equal(adds[2][0], 'removetrack', 'removetrack event handler added');
|
2019-03-18 21:49:48 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
2016-04-22 20:31:12 +02:00
|
|
|
});
|
|
|
|
|
2016-11-23 21:09:32 +02:00
|
|
|
QUnit.test('does not add native audioTrack listeners when disabled', function(assert) {
|
|
|
|
const events = [];
|
|
|
|
const vt = {
|
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => events.push([type, fn]),
|
|
|
|
removeEventListener: (type, fn) => events.push([type, fn])
|
|
|
|
};
|
|
|
|
const el = document.createElement('div');
|
|
|
|
|
|
|
|
el.videoTracks = vt;
|
|
|
|
|
|
|
|
const htmlTech = new Html5({el, nativeVideoTracks: false});
|
|
|
|
|
|
|
|
assert.equal(events.length, 0, 'no listeners added');
|
2019-03-18 21:49:48 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
2016-11-23 21:09:32 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('remove all tracks from emulated list on dispose', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const vt = {
|
2016-04-22 20:31:12 +02:00
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => adds.push([type, fn]),
|
2016-08-03 21:27:03 +02:00
|
|
|
removeEventListener: (type, fn) => rems.push([type, fn])
|
2016-04-22 20:31:12 +02:00
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
const el = document.createElement('div');
|
|
|
|
|
2016-04-22 20:31:12 +02:00
|
|
|
el.videoTracks = vt;
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
const htmlTech = new Html5({el});
|
|
|
|
|
2016-04-22 20:31:12 +02:00
|
|
|
htmlTech.dispose();
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(adds[0][0], 'change', 'change event handler added');
|
|
|
|
assert.equal(adds[1][0], 'addtrack', 'addtrack event handler added');
|
|
|
|
assert.equal(adds[2][0], 'removetrack', 'removetrack event handler added');
|
|
|
|
assert.equal(rems[0][0], 'change', 'change event handler removed');
|
|
|
|
assert.equal(rems[1][0], 'addtrack', 'addtrack event handler removed');
|
|
|
|
assert.equal(rems[2][0], 'removetrack', 'removetrack event handler removed');
|
|
|
|
assert.equal(adds[0][0], rems[0][0], 'change event handler removed');
|
|
|
|
assert.equal(adds[1][0], rems[1][0], 'addtrack event handler removed');
|
|
|
|
assert.equal(adds[2][0], rems[2][0], 'removetrack event handler removed');
|
2016-04-22 20:31:12 +02:00
|
|
|
});
|
2018-04-19 19:16:01 +02:00
|
|
|
|
|
|
|
QUnit.test('should use overrideNativeTracks on video correctly', function(assert) {
|
|
|
|
assert.expect(8);
|
|
|
|
|
|
|
|
const adds = [];
|
|
|
|
const rems = [];
|
|
|
|
const vt = {
|
|
|
|
length: 0,
|
|
|
|
addEventListener: (type, fn) => {
|
|
|
|
adds.push({ type, fn });
|
|
|
|
},
|
|
|
|
removeEventListener: (type, fn) => {
|
|
|
|
rems.push({ type, fn });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const el = document.createElement('div');
|
|
|
|
|
|
|
|
el.videoTracks = vt;
|
|
|
|
|
|
|
|
const htmlTech = new Html5({el});
|
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 3,
|
|
|
|
'should have added change, remove, add listeners'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 0,
|
|
|
|
'no listeners should be removed'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-04-20 02:11:11 +02:00
|
|
|
htmlTech.overrideNativeVideoTracks(true);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 3,
|
|
|
|
'should not have added additional listeners'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 3,
|
|
|
|
'should have removed previous three listeners'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-04-20 02:11:11 +02:00
|
|
|
htmlTech.overrideNativeVideoTracks(true);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 3,
|
|
|
|
'no state change so do not add listeners'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 3,
|
|
|
|
'no state change so do not remove listeners'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-04-20 02:11:11 +02:00
|
|
|
htmlTech.overrideNativeVideoTracks(false);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
adds.length, 6,
|
|
|
|
'should add listeners because native tracks should be proxied'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
rems.length, 3,
|
|
|
|
'should not remove listeners because there where none added on previous state'
|
|
|
|
);
|
2018-04-19 19:16:01 +02:00
|
|
|
|
|
|
|
htmlTech.dispose();
|
|
|
|
});
|
2016-04-22 20:31:12 +02:00
|
|
|
}
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should always return currentSource_ if set', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const currentSrc = Html5.prototype.currentSrc;
|
|
|
|
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.equal(
|
|
|
|
currentSrc.call({el_: {currentSrc: 'test1'}}),
|
|
|
|
'test1',
|
|
|
|
'sould return source from element if nothing else set'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
currentSrc.call({currentSource_: {src: 'test2'}}),
|
|
|
|
'test2',
|
|
|
|
'sould return source from currentSource_, if nothing else set'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
currentSrc.call({currentSource_: {src: 'test2'},
|
|
|
|
el_: {currentSrc: 'test1'}}),
|
|
|
|
'test2',
|
|
|
|
'sould return source from source set, not from element'
|
|
|
|
);
|
2015-11-23 19:04:31 +02:00
|
|
|
});
|
2015-09-15 01:37:39 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should fire makeup events when a video tag is initialized late', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const lateInit = Html5.prototype.handleLateInit_;
|
2015-09-15 01:37:39 +02:00
|
|
|
let triggeredEvents = [];
|
2016-08-03 21:27:03 +02:00
|
|
|
const mockHtml5 = {
|
2015-09-15 01:37:39 +02:00
|
|
|
readyListeners: [],
|
2016-08-03 21:27:03 +02:00
|
|
|
ready(listener) {
|
2015-09-15 01:37:39 +02:00
|
|
|
this.readyListeners.push(listener);
|
|
|
|
},
|
2016-08-03 21:27:03 +02:00
|
|
|
triggerReady() {
|
|
|
|
this.readyListeners.forEach(function(listener) {
|
2015-09-15 01:37:39 +02:00
|
|
|
listener.call(this);
|
|
|
|
}, this);
|
|
|
|
},
|
2016-08-03 21:27:03 +02:00
|
|
|
trigger(type) {
|
2015-09-15 01:37:39 +02:00
|
|
|
triggeredEvents.push(type);
|
|
|
|
},
|
2016-08-03 21:27:03 +02:00
|
|
|
on() {},
|
|
|
|
off() {}
|
2015-09-15 01:37:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
function testStates(statesObject, expectedEvents) {
|
|
|
|
lateInit.call(mockHtml5, statesObject);
|
|
|
|
mockHtml5.triggerReady();
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.deepEqual(
|
|
|
|
triggeredEvents,
|
|
|
|
expectedEvents,
|
|
|
|
'wrong events triggered for ' +
|
2016-08-03 21:27:03 +02:00
|
|
|
`networkState:${statesObject.networkState} ` +
|
2018-09-28 20:58:15 +02:00
|
|
|
`and readyState:${statesObject.readyState || 'no readyState'}`
|
|
|
|
);
|
2015-09-15 01:37:39 +02:00
|
|
|
|
|
|
|
// reset mock
|
|
|
|
triggeredEvents = [];
|
|
|
|
mockHtml5.readyListeners = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Network States
|
|
|
|
testStates({ networkState: 0, readyState: 0 }, []);
|
|
|
|
testStates({ networkState: 1, readyState: 0 }, ['loadstart']);
|
|
|
|
testStates({ networkState: 2, readyState: 0 }, ['loadstart']);
|
|
|
|
testStates({ networkState: 3, readyState: 0 }, []);
|
|
|
|
|
|
|
|
// Ready States
|
|
|
|
testStates({ networkState: 1, readyState: 0 }, ['loadstart']);
|
|
|
|
testStates({ networkState: 1, readyState: 1 }, ['loadstart', 'loadedmetadata']);
|
2018-09-28 20:58:15 +02:00
|
|
|
testStates(
|
|
|
|
{ networkState: 1, readyState: 2 },
|
|
|
|
['loadstart', 'loadedmetadata', 'loadeddata']
|
|
|
|
);
|
|
|
|
testStates(
|
|
|
|
{ networkState: 1, readyState: 3 },
|
|
|
|
['loadstart', 'loadedmetadata', 'loadeddata', 'canplay']
|
|
|
|
);
|
|
|
|
testStates(
|
|
|
|
{ networkState: 1, readyState: 4 },
|
|
|
|
['loadstart', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough']
|
|
|
|
);
|
2015-09-15 01:37:39 +02:00
|
|
|
});
|
2015-12-08 00:45:50 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('Html5.resetMediaElement should remove sources and call load', function(assert) {
|
2015-12-08 00:45:50 +02:00
|
|
|
let selector;
|
2016-08-03 21:27:03 +02:00
|
|
|
const removedChildren = [];
|
2015-12-08 00:45:50 +02:00
|
|
|
let removedAttribute;
|
|
|
|
let loaded;
|
2016-08-03 21:27:03 +02:00
|
|
|
const children = ['source1', 'source2', 'source3'];
|
|
|
|
const testEl = {
|
2015-12-08 00:45:50 +02:00
|
|
|
querySelectorAll(input) {
|
|
|
|
selector = input;
|
|
|
|
return children;
|
|
|
|
},
|
|
|
|
|
|
|
|
removeChild(child) {
|
|
|
|
removedChildren.push(child);
|
|
|
|
},
|
|
|
|
|
|
|
|
removeAttribute(attr) {
|
|
|
|
removedAttribute = attr;
|
|
|
|
},
|
|
|
|
|
|
|
|
load() {
|
|
|
|
loaded = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Html5.resetMediaElement(testEl);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(selector, 'source', 'we got the source elements from the test el');
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.deepEqual(
|
|
|
|
removedChildren,
|
|
|
|
children.reverse(),
|
|
|
|
'we removed the children that were present'
|
|
|
|
);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(removedAttribute, 'src', 'we removed the src attribute');
|
|
|
|
assert.ok(loaded, 'we called load on the element');
|
2015-12-08 00:45:50 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('Html5#reset calls Html5.resetMediaElement when called', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const oldResetMedia = Html5.resetMediaElement;
|
2015-12-08 00:45:50 +02:00
|
|
|
let resetEl;
|
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
Html5.resetMediaElement = (el) => {
|
|
|
|
resetEl = el;
|
|
|
|
};
|
|
|
|
|
|
|
|
const el = {};
|
2015-12-08 00:45:50 +02:00
|
|
|
|
|
|
|
Html5.prototype.reset.call({el_: el});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(resetEl, el, 'we called resetMediaElement with the tech\'s el');
|
2015-12-08 00:45:50 +02:00
|
|
|
|
|
|
|
Html5.resetMediaElement = oldResetMedia;
|
|
|
|
});
|
2016-08-15 23:49:52 +02:00
|
|
|
|
2017-11-17 01:12:09 +02:00
|
|
|
QUnit.test('When Android Chrome reports Infinity duration with currentTime 0, return NaN', function(assert) {
|
2016-11-03 21:39:09 +02:00
|
|
|
const oldIsAndroid = browser.IS_ANDROID;
|
|
|
|
const oldIsChrome = browser.IS_CHROME;
|
|
|
|
const oldEl = tech.el_;
|
|
|
|
|
2019-08-30 20:56:41 +02:00
|
|
|
browser.stub_IS_ANDROID(true);
|
|
|
|
browser.stub_IS_CHROME(true);
|
2016-11-03 21:39:09 +02:00
|
|
|
|
|
|
|
tech.el_ = {
|
|
|
|
duration: Infinity,
|
|
|
|
currentTime: 0
|
|
|
|
};
|
2017-11-17 01:12:09 +02:00
|
|
|
assert.ok(Number.isNaN(tech.duration()), 'returned NaN with currentTime 0');
|
2016-11-03 21:39:09 +02:00
|
|
|
|
2019-08-30 20:56:41 +02:00
|
|
|
browser.stub_IS_ANDROID(oldIsAndroid);
|
|
|
|
browser.stub_IS_CHROME(oldIsChrome);
|
2016-11-03 21:39:09 +02:00
|
|
|
tech.el_ = oldEl;
|
|
|
|
});
|
2017-05-12 21:22:02 +02:00
|
|
|
|
|
|
|
QUnit.test('supports getting available media playback quality metrics', function(assert) {
|
|
|
|
const origPerformance = window.performance;
|
|
|
|
const oldEl = tech.el_;
|
|
|
|
const videoPlaybackQuality = {
|
|
|
|
creationTime: 1,
|
|
|
|
corruptedVideoFrames: 2,
|
|
|
|
droppedVideoFrames: 3,
|
|
|
|
totalVideoFrames: 5
|
|
|
|
};
|
|
|
|
|
|
|
|
tech.el_ = {
|
|
|
|
getVideoPlaybackQuality: () => videoPlaybackQuality
|
|
|
|
};
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.deepEqual(
|
|
|
|
tech.getVideoPlaybackQuality(),
|
|
|
|
videoPlaybackQuality,
|
|
|
|
'uses native implementation when supported'
|
|
|
|
);
|
2017-05-12 21:22:02 +02:00
|
|
|
tech.el_ = {
|
|
|
|
webkitDroppedFrameCount: 1,
|
|
|
|
webkitDecodedFrameCount: 2
|
|
|
|
};
|
|
|
|
window.performance = {
|
|
|
|
now: () => 4
|
|
|
|
};
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.deepEqual(
|
|
|
|
tech.getVideoPlaybackQuality(),
|
|
|
|
{ droppedVideoFrames: 1, totalVideoFrames: 2, creationTime: 4 },
|
|
|
|
'uses webkit prefixed metrics and performance.now when supported'
|
|
|
|
);
|
2017-05-12 21:22:02 +02:00
|
|
|
|
|
|
|
tech.el_ = {};
|
|
|
|
window.performance = void 0;
|
|
|
|
assert.deepEqual(tech.getVideoPlaybackQuality(), {}, 'empty object when not supported');
|
|
|
|
|
|
|
|
window.performance = {
|
2022-06-02 18:05:57 +02:00
|
|
|
now: () => 7
|
2017-05-12 21:22:02 +02:00
|
|
|
};
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.deepEqual(
|
|
|
|
tech.getVideoPlaybackQuality(),
|
|
|
|
{ creationTime: 7 },
|
|
|
|
'only creation time when it\'s the only piece available'
|
|
|
|
);
|
2017-05-12 21:22:02 +02:00
|
|
|
|
|
|
|
tech.el_ = {
|
|
|
|
getVideoPlaybackQuality: () => videoPlaybackQuality,
|
|
|
|
webkitDroppedFrameCount: 1,
|
|
|
|
webkitDecodedFrameCount: 2
|
|
|
|
};
|
2018-09-28 20:58:15 +02:00
|
|
|
assert.deepEqual(
|
|
|
|
tech.getVideoPlaybackQuality(),
|
|
|
|
videoPlaybackQuality,
|
|
|
|
'prefers native implementation when supported'
|
|
|
|
);
|
2017-05-12 21:22:02 +02:00
|
|
|
|
|
|
|
tech.el_ = oldEl;
|
|
|
|
window.performance = origPerformance;
|
|
|
|
});
|
2022-05-31 21:50:51 +02:00
|
|
|
|
|
|
|
QUnit.test('featuresVideoFrameCallback is false for audio elements', function(assert) {
|
|
|
|
const el = document.createElement('audio');
|
2022-06-28 22:01:00 +02:00
|
|
|
const audioTech = new Html5({
|
|
|
|
el,
|
|
|
|
source: [{src: 'https://example.org/stream.m3u8'}]
|
|
|
|
});
|
2022-05-31 21:50:51 +02:00
|
|
|
|
|
|
|
assert.strictEqual(audioTech.featuresVideoFrameCallback, false, 'Html5 with audio element should not support rvf');
|
|
|
|
|
|
|
|
audioTech.dispose();
|
|
|
|
});
|
2022-07-28 20:20:46 +02:00
|
|
|
|
|
|
|
QUnit.test('featuresVideoFrameCallback is false for Safari DRM', function(assert) {
|
|
|
|
// Looking for `super.requestVideoFrameCallback()` being called
|
|
|
|
const spy = sinon.spy(Object.getPrototypeOf(Object.getPrototypeOf(tech)), 'requestVideoFrameCallback');
|
|
|
|
|
|
|
|
tech.featuresVideoFrameCallback = true;
|
|
|
|
|
|
|
|
try {
|
|
|
|
tech.el_.webkitKeys = {};
|
|
|
|
tech.requestVideoFrameCallback(function() {});
|
|
|
|
|
|
|
|
assert.ok(spy.calledOnce, false, 'rvf fallback used');
|
|
|
|
} catch (e) {
|
|
|
|
// video.webkitKeys isn't writable on Safari, so relying on the mocked property on other browsers
|
|
|
|
assert.ok(true, 'skipped because webkitKeys not writable');
|
|
|
|
}
|
|
|
|
});
|
2023-01-24 12:45:49 +02:00
|
|
|
|
|
|
|
QUnit.test('supportsFullScreen is always with `webkitEnterFullScreen`', function(assert) {
|
|
|
|
const oldEl = tech.el_;
|
|
|
|
|
|
|
|
tech.el_ = {
|
|
|
|
webkitEnterFullScreen: () => {}
|
|
|
|
};
|
|
|
|
|
|
|
|
assert.ok(tech.supportsFullScreen(), 'supportsFullScreen() true with webkitEnterFullScreen');
|
|
|
|
|
|
|
|
tech.el_ = oldEl;
|
|
|
|
});
|