mirror of
https://github.com/videojs/video.js.git
synced 2024-12-23 02:04:34 +02:00
35de64ceb0
refactor: Replace keycode dependency with event.key
423 lines
12 KiB
JavaScript
423 lines
12 KiB
JavaScript
/* eslint-env qunit */
|
|
import Player from '../../src/js/player.js';
|
|
import Html5 from '../../src/js/tech/html5.js'; // eslint-disable-line no-unused-vars
|
|
import TestHelpers from './test-helpers.js';
|
|
import sinon from 'sinon';
|
|
import window from 'global/window';
|
|
import document from 'global/document';
|
|
|
|
const FullscreenTestHelpers = {
|
|
makePlayer(prefixed, playerOptions, videoTag) {
|
|
const player = TestHelpers.makePlayer(playerOptions, videoTag);
|
|
|
|
player.fsApi_ = {
|
|
prefixed,
|
|
requestFullscreen: 'vjsRequestFullscreen',
|
|
exitFullscreen: 'vjsExitFullscreen',
|
|
fullscreenElement: 'vjsFullscreenElement',
|
|
fullscreenEnabled: 'vjsFullscreenEnabled',
|
|
fullscreenchange: 'vjsfullscreenchange',
|
|
fullscreenerror: 'vjsfullscreenerror',
|
|
fullscreen: 'vjsfullscreen'
|
|
};
|
|
|
|
return player;
|
|
},
|
|
fakeSafariVideoEl() {
|
|
const testEl = document.createElement('video');
|
|
|
|
if (!('webkitPresentationMode' in testEl)) {
|
|
testEl.webkitPresentationMode = 'test';
|
|
}
|
|
|
|
if (!('webkitDisplayingFullscreen' in testEl)) {
|
|
testEl.webkitDisplayingFullscreen = false;
|
|
}
|
|
|
|
return testEl;
|
|
}
|
|
};
|
|
|
|
QUnit.module('Player Fullscreen', {
|
|
beforeEach(assert) {
|
|
this.clock = sinon.useFakeTimers();
|
|
// reset players storage
|
|
for (const playerId in Player.players) {
|
|
if (Player.players[playerId] !== null) {
|
|
Player.players[playerId].dispose();
|
|
}
|
|
delete Player.players[playerId];
|
|
}
|
|
|
|
window.Element.prototype.vjsRequestFullscreen = function() {
|
|
assert.ok(false, 'vjsRequestFullscreen should not be called');
|
|
};
|
|
window.Element.prototype.vjsExitFullscreen = function() {
|
|
assert.ok(false, 'vjsExitFullscreen should not be called');
|
|
};
|
|
window.Element.prototype.vjsFullscreenElement = function() {
|
|
assert.ok(false, 'vjsFullscreenElement should not be called');
|
|
};
|
|
window.Element.prototype.vjsFullscreenEnabled = function() {
|
|
assert.ok(false, 'vjsFullscreenEnabled should not be called');
|
|
};
|
|
window.Element.prototype.vjsfullscreenchange = function() {
|
|
assert.ok(false, 'vjsfullscreenchange should not be called');
|
|
};
|
|
window.Element.prototype.vjsfullscreenerror = function() {
|
|
assert.ok(false, 'vjsfullscreenerror should not be called');
|
|
};
|
|
},
|
|
afterEach() {
|
|
this.clock.restore();
|
|
|
|
delete window.Element.prototype.vjsRequestFullscreen;
|
|
delete window.Element.prototype.vjsExitFullscreen;
|
|
delete window.Element.prototype.vjsFullscreenElement;
|
|
delete window.Element.prototype.vjsFullscreenEnabled;
|
|
delete window.Element.prototype.vjsfullscreenchange;
|
|
delete window.Element.prototype.vjsfullscreenerror;
|
|
}
|
|
});
|
|
|
|
QUnit.test('fullscreenOptions should not be passed from player options on prefixed api', function(assert) {
|
|
|
|
const fullscreenOptions = {
|
|
navigationUI: 'test',
|
|
foo: 'bar'
|
|
};
|
|
|
|
const player = FullscreenTestHelpers.makePlayer(true, {
|
|
fullscreen: {
|
|
options: fullscreenOptions
|
|
}
|
|
});
|
|
|
|
let requestFullscreenCalled = false;
|
|
let fsOpts;
|
|
|
|
window.Element.prototype.vjsRequestFullscreen = function(opts) {
|
|
requestFullscreenCalled = true;
|
|
fsOpts = opts;
|
|
};
|
|
|
|
player.requestFullscreen();
|
|
|
|
assert.ok(requestFullscreenCalled, 'vjsRequestFullscreen should be called');
|
|
assert.strictEqual(fsOpts, undefined, 'fullscreenOptions should not be passed');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreenOptions should be passed from player options on unprefixed api', function(assert) {
|
|
|
|
const fullscreenOptions = {
|
|
navigationUI: 'test',
|
|
foo: 'bar'
|
|
};
|
|
|
|
const player = FullscreenTestHelpers.makePlayer(false, {
|
|
fullscreen: {
|
|
options: fullscreenOptions
|
|
}
|
|
});
|
|
|
|
let requestFullscreenCalled = false;
|
|
let fsOpts;
|
|
|
|
window.Element.prototype.vjsRequestFullscreen = function(opts) {
|
|
requestFullscreenCalled = true;
|
|
fsOpts = opts;
|
|
};
|
|
|
|
player.requestFullscreen();
|
|
|
|
assert.ok(requestFullscreenCalled, 'vjsRequestFullscreen should be called');
|
|
assert.notStrictEqual(fsOpts, undefined, 'fullscreenOptions should be passed');
|
|
assert.deepEqual(fsOpts, fullscreenOptions, 'fullscreenOptions should match player options');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreenOptions should not be passed from function arguments on prefixed api', function(assert) {
|
|
|
|
const fullscreenOptions = {
|
|
navigationUI: 'test',
|
|
foo: 'bar'
|
|
};
|
|
|
|
const player = FullscreenTestHelpers.makePlayer(true);
|
|
|
|
let requestFullscreenCalled = false;
|
|
let fsOpts;
|
|
|
|
window.Element.prototype.vjsRequestFullscreen = function(opts) {
|
|
requestFullscreenCalled = true;
|
|
fsOpts = opts;
|
|
};
|
|
|
|
player.requestFullscreen(fullscreenOptions);
|
|
|
|
assert.ok(requestFullscreenCalled, 'vjsRequestFullscreen should be called');
|
|
assert.strictEqual(fsOpts, undefined, 'fullscreenOptions should not be passed');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreenOptions should be passed from function arguments on unprefixed api', function(assert) {
|
|
|
|
const fullscreenOptions = {
|
|
navigationUI: 'test',
|
|
foo: 'bar'
|
|
};
|
|
|
|
const player = FullscreenTestHelpers.makePlayer(false);
|
|
|
|
let requestFullscreenCalled = false;
|
|
let fsOpts;
|
|
|
|
window.Element.prototype.vjsRequestFullscreen = function(opts) {
|
|
requestFullscreenCalled = true;
|
|
fsOpts = opts;
|
|
};
|
|
|
|
player.requestFullscreen(fullscreenOptions);
|
|
|
|
assert.ok(requestFullscreenCalled, 'vjsRequestFullscreen should be called');
|
|
assert.notStrictEqual(fsOpts, undefined, 'fullscreenOptions should be passed');
|
|
assert.deepEqual(fsOpts, fullscreenOptions, 'fullscreenOptions should match function args');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreenOptions from function args should override player options', function(assert) {
|
|
|
|
const fullscreenOptions = {
|
|
navigationUI: 'args',
|
|
baz: 'bar'
|
|
};
|
|
|
|
const player = FullscreenTestHelpers.makePlayer(false, {
|
|
fullscreen: {
|
|
options: {
|
|
navigationUI: 'playeroptions',
|
|
foo: 'bar'
|
|
}
|
|
}
|
|
});
|
|
|
|
let requestFullscreenCalled = false;
|
|
let fsOpts;
|
|
|
|
window.Element.prototype.vjsRequestFullscreen = function(opts) {
|
|
requestFullscreenCalled = true;
|
|
fsOpts = opts;
|
|
};
|
|
|
|
player.requestFullscreen(fullscreenOptions);
|
|
|
|
assert.ok(requestFullscreenCalled, 'vjsRequestFullscreen should be called');
|
|
assert.notStrictEqual(fsOpts, undefined, 'fullscreenOptions should be passed');
|
|
assert.deepEqual(fsOpts, fullscreenOptions, 'fullscreenOptions should match function args');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('full window can be preferred to fullscreen tech', function(assert) {
|
|
|
|
const player = FullscreenTestHelpers.makePlayer(false, {
|
|
preferFullWindow: true
|
|
});
|
|
|
|
player.fsApi_ = {};
|
|
player.tech_.supportsFullScreen = () => true;
|
|
|
|
player.requestFullscreen();
|
|
|
|
assert.strictEqual(player.isFullscreen(), true, 'player considered fullscreen');
|
|
assert.strictEqual(player.isFullWindow, true, 'player is full window');
|
|
|
|
player.exitFullscreen();
|
|
assert.strictEqual(player.isFullWindow, false, 'full window is exited');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreen mode should exit picture-in-picture if it was enabled', function(assert) {
|
|
const player = FullscreenTestHelpers.makePlayer(false, {
|
|
preferFullWindow: true
|
|
});
|
|
|
|
const fakeExitPictureInPicture = sinon.replace(player, 'exitPictureInPicture', sinon.fake(() => {}));
|
|
|
|
player.fsApi_ = {};
|
|
player.tech_.supportsFullScreen = () => true;
|
|
|
|
assert.strictEqual(player.isFullscreen(), false, 'player should not be fullscreen initially');
|
|
player.isInPictureInPicture(true);
|
|
player.trigger('enterpictureinpicture');
|
|
assert.strictEqual(player.isInPictureInPicture(), true, 'player is in picture-in-picture');
|
|
|
|
assert.strictEqual(fakeExitPictureInPicture.called, false, 'should not have called exitPictureInPicture yet');
|
|
player.requestFullscreen();
|
|
assert.strictEqual(player.isFullscreen(), true, 'player should be fullscreen');
|
|
assert.strictEqual(fakeExitPictureInPicture.called, true, 'should have called exitPictureInPicture');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullwindow mode should exit when ESC event triggered', function(assert) {
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
player.enterFullWindow();
|
|
assert.ok(player.isFullWindow, 'enterFullWindow should be called');
|
|
|
|
const evt = TestHelpers.createEvent('keydown');
|
|
|
|
evt.key = 'Escape';
|
|
evt.keyCode = 27;
|
|
evt.which = 27;
|
|
player.boundFullWindowOnEscKey_(evt);
|
|
// player.fullWindowOnEscKey(evt);
|
|
assert.equal(player.isFullWindow, false, 'exitFullWindow should be called');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreenchange event from Html5 should change player.isFullscreen_', function(assert) {
|
|
const player = FullscreenTestHelpers.makePlayer(false);
|
|
const html5 = player.tech(true);
|
|
|
|
// simulate html5.proxyWebkitFullscreen_
|
|
html5.trigger('fullscreenchange', {
|
|
isFullscreen: true,
|
|
nativeIOSFullscreen: true
|
|
});
|
|
|
|
assert.ok(player.isFullscreen(), 'player.isFullscreen_ should be true');
|
|
|
|
html5.trigger('fullscreenchange', { isFullscreen: false });
|
|
|
|
assert.ok(!player.isFullscreen(), 'player.isFullscreen_ should be false');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreenchange event from Html5 should guard against Safari showing double controls', function(assert) {
|
|
const player = FullscreenTestHelpers.makePlayer(undefined, {techOrder: ['html5']}, FullscreenTestHelpers.fakeSafariVideoEl());
|
|
const html5 = player.tech(true);
|
|
|
|
html5.trigger('webkitbeginfullscreen');
|
|
|
|
assert.ok(player.isFullscreen(), 'player.isFullscreen_ should be true');
|
|
|
|
player.tech_.el_.controls = true;
|
|
|
|
html5.trigger('webkitendfullscreen');
|
|
|
|
assert.ok(!player.tech_.el_.controls, 'el controls should be false');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('Safari leaving fullscreen should retain controls with nativeControlsForTouch', function(assert) {
|
|
const player = FullscreenTestHelpers.makePlayer(undefined, {techOrder: ['html5'], nativeControlsForTouch: true}, FullscreenTestHelpers.fakeSafariVideoEl());
|
|
const html5 = player.tech(true);
|
|
|
|
html5.trigger('webkitbeginfullscreen');
|
|
|
|
assert.ok(player.isFullscreen(), 'player.isFullscreen_ should be true');
|
|
|
|
player.tech_.el_.controls = true;
|
|
|
|
html5.trigger('webkitendfullscreen');
|
|
|
|
assert.ok(player.tech_.el_.controls, 'el controls should be true');
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
QUnit.test('fullscreenerror event from Html5 should pass through player', function(assert) {
|
|
const player = FullscreenTestHelpers.makePlayer(false);
|
|
const html5 = player.tech(true);
|
|
const err = new Error('This is test');
|
|
let fullscreenerror;
|
|
|
|
player.on('fullscreenerror', function(evt, error) {
|
|
fullscreenerror = error;
|
|
});
|
|
|
|
html5.trigger('fullscreenerror', err);
|
|
|
|
assert.strictEqual(fullscreenerror, err);
|
|
|
|
player.dispose();
|
|
});
|
|
|
|
// only run where we have sinon.promise
|
|
const skipOrTest = sinon.promise ? 'test' : 'skip';
|
|
|
|
QUnit[skipOrTest]('requestFullscreen returns a rejected promise if unable to go fullscreen', function(assert) {
|
|
const player = TestHelpers.makePlayer();
|
|
const playerEl = player.el();
|
|
const stub = sinon.stub(playerEl, player.fsApi_.requestFullscreen);
|
|
const promise = sinon.promise();
|
|
|
|
stub.returns(promise);
|
|
promise.reject(new Error('Cannot go fullscreen'));
|
|
|
|
assert.rejects(
|
|
player.requestFullscreen(),
|
|
new Error('Cannot go fullscreen'),
|
|
'our promise was rejected'
|
|
);
|
|
|
|
stub.restore();
|
|
});
|
|
|
|
QUnit[skipOrTest]('requestFullscreen returns a resolved promise if we were fullscreen', function(assert) {
|
|
const player = TestHelpers.makePlayer();
|
|
const playerEl = player.el();
|
|
const stub = sinon.stub(playerEl, player.fsApi_.requestFullscreen);
|
|
const promise = sinon.promise();
|
|
|
|
stub.returns(promise);
|
|
// pretend we successfully went fullscreen.
|
|
promise.resolve();
|
|
|
|
player.requestFullscreen().then(() => assert.ok(true, 'our promise resolved'));
|
|
|
|
stub.restore();
|
|
});
|
|
|
|
QUnit[skipOrTest]('exitFullscreen returns a rejected promise if document is not active', function(assert) {
|
|
const player = TestHelpers.makePlayer();
|
|
const stub = sinon.stub(document, player.fsApi_.exitFullscreen);
|
|
const promise = sinon.promise();
|
|
|
|
stub.returns(promise);
|
|
promise.reject(new Error('Document not active'));
|
|
|
|
assert.rejects(
|
|
player.exitFullscreen(),
|
|
new Error('Document not active'),
|
|
'our promise was rejected'
|
|
);
|
|
|
|
stub.restore();
|
|
});
|
|
|
|
QUnit[skipOrTest]('exitFullscreen returns a resolved promise if we were fullscreen', function(assert) {
|
|
const player = TestHelpers.makePlayer();
|
|
const stub = sinon.stub(document, player.fsApi_.exitFullscreen);
|
|
const promise = sinon.promise();
|
|
|
|
stub.returns(promise);
|
|
// pretend we successfully exited.
|
|
promise.resolve();
|
|
|
|
player.exitFullscreen().then(() => assert.ok(true, 'our promise resolved'));
|
|
|
|
stub.restore();
|
|
});
|