summaryrefslogtreecommitdiff
path: root/javascript/videojs/test/unit/player-fullscreen.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'javascript/videojs/test/unit/player-fullscreen.test.js')
-rw-r--r--javascript/videojs/test/unit/player-fullscreen.test.js422
1 files changed, 422 insertions, 0 deletions
diff --git a/javascript/videojs/test/unit/player-fullscreen.test.js b/javascript/videojs/test/unit/player-fullscreen.test.js
new file mode 100644
index 0000000..5b1f1dd
--- /dev/null
+++ b/javascript/videojs/test/unit/player-fullscreen.test.js
@@ -0,0 +1,422 @@
+/* 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();
+});