diff options
Diffstat (limited to 'javascript/videojs/test/unit/player-fullscreen.test.js')
| -rw-r--r-- | javascript/videojs/test/unit/player-fullscreen.test.js | 422 |
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(); +}); |
