diff options
Diffstat (limited to 'javascript/videojs/test/unit/player-user-actions.test.js')
| -rw-r--r-- | javascript/videojs/test/unit/player-user-actions.test.js | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/javascript/videojs/test/unit/player-user-actions.test.js b/javascript/videojs/test/unit/player-user-actions.test.js new file mode 100644 index 0000000..d639434 --- /dev/null +++ b/javascript/videojs/test/unit/player-user-actions.test.js @@ -0,0 +1,641 @@ +/* eslint-env qunit */ +import document from 'global/document'; +import sinon from 'sinon'; +import TestHelpers from './test-helpers'; +import FullscreenApi from '../../src/js/fullscreen-api.js'; + +QUnit.module('Player: User Actions: Click', { + + beforeEach() { + this.clock = sinon.useFakeTimers(); + this.player = TestHelpers.makePlayer({controls: true}); + }, + + afterEach() { + this.player.dispose(); + this.clock.restore(); + } +}); + +QUnit.test('by default, click toggles play', function(assert) { + let paused = true; + + this.player.paused = () => paused; + this.player.play = sinon.spy(); + this.player.pause = sinon.spy(); + + this.player.handleTechClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.play.callCount, 1, 'has called play'); + assert.strictEqual(this.player.pause.callCount, 0, 'has not called pause'); + + paused = false; + this.player.handleTechClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.play.callCount, 1, 'has called play, previously'); + assert.strictEqual(this.player.pause.callCount, 1, 'has called pause'); +}); + +QUnit.test('when controls are disabled, click does nothing', function(assert) { + let paused = true; + + this.player.controls(false); + + this.player.paused = () => paused; + this.player.play = sinon.spy(); + this.player.pause = sinon.spy(); + + this.player.handleTechClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.play.callCount, 0, 'has not called play'); + assert.strictEqual(this.player.pause.callCount, 0, 'has not called pause'); + + paused = false; + this.player.handleTechClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.play.callCount, 0, 'has not called play, previously'); + assert.strictEqual(this.player.pause.callCount, 0, 'has not called pause'); +}); + +QUnit.test('when userActions.click is false, click does nothing', function(assert) { + let paused = true; + + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + click: false + } + }); + + this.player.paused = () => paused; + this.player.play = sinon.spy(); + this.player.pause = sinon.spy(); + + this.player.handleTechClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.play.callCount, 0, 'has not called play'); + assert.strictEqual(this.player.pause.callCount, 0, 'has not called pause'); + + paused = false; + this.player.handleTechClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.play.callCount, 0, 'has not called play, previously'); + assert.strictEqual(this.player.pause.callCount, 0, 'has not called pause'); +}); + +QUnit.test('when userActions.click is a function, that function is called instead of toggling play', function(assert) { + let paused = true; + const clickSpy = sinon.spy(); + + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + click: clickSpy + } + }); + + this.player.paused = () => paused; + this.player.play = sinon.spy(); + this.player.pause = sinon.spy(); + + let event = {target: this.player.tech_.el_}; + + this.player.handleTechClick_(event); + + assert.strictEqual(this.player.play.callCount, 0, 'has not called play'); + assert.strictEqual(this.player.pause.callCount, 0, 'has not called pause'); + assert.strictEqual(clickSpy.callCount, 1, 'has called the click handler'); + assert.strictEqual(clickSpy.getCall(0).args[0], event, 'has passed the event to the handler'); + + paused = false; + event = {target: this.player.tech_.el_}; + this.player.handleTechClick_(event); + + assert.strictEqual(this.player.play.callCount, 0, 'has not called play, previously'); + assert.strictEqual(this.player.pause.callCount, 0, 'has not called pause'); + assert.strictEqual(clickSpy.callCount, 2, 'has called the click handler'); + assert.strictEqual(clickSpy.getCall(1).args[0], event, 'has passed the event to the handler'); +}); + +QUnit.module('Player: User Actions: Double Click', { + + beforeEach() { + this.clock = sinon.useFakeTimers(); + this.player = TestHelpers.makePlayer({controls: true}); + }, + + afterEach() { + this.player.dispose(); + this.clock.restore(); + } +}); + +QUnit.test('by default, double-click opens fullscreen', function(assert) { + let fullscreen = false; + + this.player.isFullscreen = () => fullscreen; + this.player.requestFullscreen = sinon.spy(); + this.player.exitFullscreen = sinon.spy(); + + this.player.handleTechDoubleClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.requestFullscreen.callCount, 1, 'has gone fullscreen once'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + + fullscreen = true; + this.player.handleTechDoubleClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.requestFullscreen.callCount, 1, 'has gone fullscreen once'); + assert.strictEqual(this.player.exitFullscreen.callCount, 1, 'has exited fullscreen'); +}); + +QUnit.test('in document picture in picture mode, double-click exits pip', function(assert) { + this.player.isInPictureInPicture = () => true; + this.player.exitPictureInPicture = sinon.spy(); + this.player.requestFullscreen = sinon.spy(); + this.player.exitFullscreen = sinon.spy(); + + this.player.handleTechDoubleClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.exitPictureInPicture.callCount, 1, 'has exited pip once'); + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not entered fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); +}); + +QUnit.test('when controls are disabled, double-click does nothing', function(assert) { + let fullscreen = false; + + this.player.controls(false); + + this.player.isFullscreen = () => fullscreen; + this.player.requestFullscreen = sinon.spy(); + this.player.exitFullscreen = sinon.spy(); + + this.player.handleTechDoubleClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + + fullscreen = true; + this.player.handleTechDoubleClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); +}); + +QUnit.test('when userActions.doubleClick is false, double-click does nothing', function(assert) { + let fullscreen = false; + + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + doubleClick: false + } + }); + + this.player.isFullscreen = () => fullscreen; + this.player.requestFullscreen = sinon.spy(); + this.player.exitFullscreen = sinon.spy(); + + this.player.handleTechDoubleClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + + fullscreen = true; + this.player.handleTechDoubleClick_({target: this.player.tech_.el_}); + + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); +}); + +QUnit.test('when userActions.doubleClick is a function, that function is called instead of going fullscreen', function(assert) { + let fullscreen = false; + + const doubleClickSpy = sinon.spy(); + + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + doubleClick: doubleClickSpy + } + }); + + this.player.isFullscreen = () => fullscreen; + this.player.requestFullscreen = sinon.spy(); + this.player.exitFullscreen = sinon.spy(); + + let event = {target: this.player.tech_.el_}; + + this.player.handleTechDoubleClick_(event); + + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + assert.strictEqual(doubleClickSpy.callCount, 1, 'has called the doubleClick handler'); + assert.strictEqual(doubleClickSpy.getCall(0).args[0], event, 'has passed the event to the handler'); + + fullscreen = true; + event = {target: this.player.tech_.el_}; + this.player.handleTechDoubleClick_(event); + + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + assert.strictEqual(doubleClickSpy.callCount, 2, 'has called the doubleClick handler'); + assert.strictEqual(doubleClickSpy.getCall(1).args[0], event, 'has passed the event to the handler'); +}); + +QUnit.module('Player: User Actions: Hotkeys', { + + beforeEach() { + this.clock = sinon.useFakeTimers(); + this.player = TestHelpers.makePlayer(); + }, + + afterEach() { + this.player.dispose(); + this.clock.restore(); + } +}); + +const mockKeyDownEvent = (key) => { + return { + preventDefault() {}, + stopPropagation() {}, + type: 'keydown', + key + }; +}; + +const defaultKeyTests = { + fullscreen(player, assert, positive) { + let fullscreen; + + if (document[FullscreenApi.fullscreenEnabled] === false) { + assert.ok(true, 'skipped fullscreen test because not supported'); + assert.ok(true, 'skipped fullscreen test because not supported'); + assert.ok(true, 'skipped fullscreen test because not supported'); + assert.ok(true, 'skipped fullscreen test because not supported'); + return; + } + + player.isFullscreen = () => fullscreen; + player.requestFullscreen = sinon.spy(); + player.exitFullscreen = sinon.spy(); + + fullscreen = false; + player.handleKeyDown(mockKeyDownEvent('f')); + + if (positive) { + assert.strictEqual(player.requestFullscreen.callCount, 1, 'has gone fullscreen'); + assert.strictEqual(player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + } else { + assert.strictEqual(player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + } + + fullscreen = true; + player.handleKeyDown(mockKeyDownEvent('f')); + + if (positive) { + assert.strictEqual(player.requestFullscreen.callCount, 1, 'has gone fullscreen'); + assert.strictEqual(player.exitFullscreen.callCount, 1, 'has exited fullscreen'); + } else { + assert.strictEqual(player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + } + }, + mute(player, assert, positive) { + let muted = false; + + player.muted = sinon.spy((val) => { + if (val !== undefined) { + muted = val; + } + return muted; + }); + + player.handleKeyDown(mockKeyDownEvent('m')); + + if (positive) { + assert.strictEqual(player.muted.callCount, 2, 'muted was called twice (get and set)'); + assert.strictEqual(player.muted.lastCall.args[0], true, 'most recent call was to mute'); + } else { + assert.strictEqual(player.muted.callCount, 0, 'muted was not called'); + } + + player.handleKeyDown(mockKeyDownEvent('m')); + + if (positive) { + assert.strictEqual(player.muted.callCount, 4, 'muted was called twice (get and set)'); + assert.strictEqual(player.muted.lastCall.args[0], false, 'most recent call was to unmute'); + } else { + assert.strictEqual(player.muted.callCount, 0, 'muted was not called'); + } + }, + playPause(player, assert, positive) { + let paused; + + player.paused = () => paused; + player.pause = sinon.spy(); + player.play = sinon.spy(); + + paused = true; + player.handleKeyDown(mockKeyDownEvent('k')); + + if (positive) { + assert.strictEqual(player.pause.callCount, 0, 'has not paused'); + assert.strictEqual(player.play.callCount, 1, 'has played'); + } else { + assert.strictEqual(player.pause.callCount, 0, 'has not paused'); + assert.strictEqual(player.play.callCount, 0, 'has not played'); + } + + paused = false; + player.handleKeyDown(mockKeyDownEvent('k')); + + if (positive) { + assert.strictEqual(player.pause.callCount, 1, 'has paused'); + assert.strictEqual(player.play.callCount, 1, 'has played'); + } else { + assert.strictEqual(player.pause.callCount, 0, 'has not paused'); + assert.strictEqual(player.play.callCount, 0, 'has not played'); + } + + paused = true; + player.handleKeyDown(mockKeyDownEvent(' ')); + + if (positive) { + assert.strictEqual(player.pause.callCount, 1, 'has paused'); + assert.strictEqual(player.play.callCount, 2, 'has played twice'); + } else { + assert.strictEqual(player.pause.callCount, 0, 'has not paused'); + assert.strictEqual(player.play.callCount, 0, 'has not played'); + } + + paused = false; + player.handleKeyDown(mockKeyDownEvent(' ')); + + if (positive) { + assert.strictEqual(player.pause.callCount, 2, 'has paused twice'); + assert.strictEqual(player.play.callCount, 2, 'has played twice'); + } else { + assert.strictEqual(player.pause.callCount, 0, 'has not paused'); + assert.strictEqual(player.play.callCount, 0, 'has not played'); + } + } +}; + +QUnit.test('by default, hotkeys are disabled', function(assert) { + assert.expect(14); + defaultKeyTests.fullscreen(this.player, assert, false); + defaultKeyTests.mute(this.player, assert, false); + defaultKeyTests.playPause(this.player, assert, false); +}); + +QUnit.test('when userActions.hotkeys is true, hotkeys are enabled', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: true + } + }); + + assert.expect(16); + defaultKeyTests.fullscreen(this.player, assert, true); + defaultKeyTests.mute(this.player, assert, true); + defaultKeyTests.playPause(this.player, assert, true); +}); + +QUnit.test('when userActions.hotkeys is an object, hotkeys are enabled', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: {} + } + }); + + assert.expect(16); + defaultKeyTests.fullscreen(this.player, assert, true); + defaultKeyTests.mute(this.player, assert, true); + defaultKeyTests.playPause(this.player, assert, true); +}); + +QUnit.test('when userActions.hotkeys.fullscreenKey can be a function', function(assert) { + if (document[FullscreenApi.fullscreenEnabled] === false) { + assert.expect(0); + return; + } + + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: { + fullscreenKey: sinon.spy((e) => e.key === 'x') + } + } + }); + + let fullscreen; + + this.player.isFullscreen = () => fullscreen; + this.player.requestFullscreen = sinon.spy(); + this.player.exitFullscreen = sinon.spy(); + + fullscreen = false; + this.player.handleKeyDown(mockKeyDownEvent('f')); + + assert.strictEqual(this.player.requestFullscreen.callCount, 0, 'has not gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + + this.player.handleKeyDown(mockKeyDownEvent('x')); + + assert.strictEqual(this.player.requestFullscreen.callCount, 1, 'has gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 0, 'has not exited fullscreen'); + + fullscreen = true; + this.player.handleKeyDown(mockKeyDownEvent('x')); + + assert.strictEqual(this.player.requestFullscreen.callCount, 1, 'has gone fullscreen'); + assert.strictEqual(this.player.exitFullscreen.callCount, 1, 'has exited fullscreen'); +}); + +QUnit.test('when userActions.hotkeys.muteKey can be a function', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: { + muteKey: sinon.spy((e) => e.key === 'x') + } + } + }); + + let muted = false; + + this.player.muted = sinon.spy((val) => { + if (val !== undefined) { + muted = val; + } + return muted; + }); + + this.player.handleKeyDown(mockKeyDownEvent('m')); + + assert.strictEqual(this.player.muted.callCount, 0, 'muted was not called'); + + this.player.handleKeyDown(mockKeyDownEvent('x')); + + assert.strictEqual(this.player.muted.callCount, 2, 'muted was called twice (get and set)'); + assert.strictEqual(this.player.muted.lastCall.args[0], true, 'most recent call was to mute'); + + this.player.handleKeyDown(mockKeyDownEvent('x')); + + assert.strictEqual(this.player.muted.callCount, 4, 'muted was called twice (get and set)'); + assert.strictEqual(this.player.muted.lastCall.args[0], false, 'most recent call was to unmute'); +}); + +QUnit.test('when userActions.hotkeys.playPauseKey can be a function', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: { + playPauseKey: sinon.spy((e) => e.key === 'x') + } + } + }); + + let paused; + + this.player.paused = () => paused; + this.player.pause = sinon.spy(); + this.player.play = sinon.spy(); + + paused = true; + this.player.handleKeyDown(mockKeyDownEvent('k')); + this.player.handleKeyDown(mockKeyDownEvent(' ')); + + assert.strictEqual(this.player.pause.callCount, 0, 'has not paused'); + assert.strictEqual(this.player.play.callCount, 0, 'has not played'); + + this.player.handleKeyDown(mockKeyDownEvent('x')); + + assert.strictEqual(this.player.pause.callCount, 0, 'has not paused'); + assert.strictEqual(this.player.play.callCount, 1, 'has played'); + + paused = false; + this.player.handleKeyDown(mockKeyDownEvent('x')); + + assert.strictEqual(this.player.pause.callCount, 1, 'has paused'); + assert.strictEqual(this.player.play.callCount, 1, 'has played'); +}); + +QUnit.test('hotkeys are ignored when focus is in a contenteditable element', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: true + } + }); + + const div = document.createElement('div'); + + div.contentEditable = 'true'; + this.player.el_.appendChild(div); + div.focus(); + + assert.expect(14); + defaultKeyTests.fullscreen(this.player, assert, false); + defaultKeyTests.mute(this.player, assert, false); + defaultKeyTests.playPause(this.player, assert, false); +}); + +QUnit.test('hotkeys are ignored when focus is in a textarea', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: true + } + }); + + const textarea = document.createElement('textarea'); + + this.player.el_.appendChild(textarea); + textarea.focus(); + + assert.expect(14); + defaultKeyTests.fullscreen(this.player, assert, false); + defaultKeyTests.mute(this.player, assert, false); + defaultKeyTests.playPause(this.player, assert, false); +}); + +QUnit.test('hotkeys are ignored when focus is in a text input', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: true + } + }); + + const input = document.createElement('input'); + + input.type = 'text'; + this.player.el_.appendChild(input); + input.focus(); + + assert.expect(14); + defaultKeyTests.fullscreen(this.player, assert, false); + defaultKeyTests.mute(this.player, assert, false); + defaultKeyTests.playPause(this.player, assert, false); +}); + +QUnit.test('hotkeys are NOT ignored when focus is on a button element', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: true + } + }); + + const button = document.createElement('button'); + + this.player.el_.appendChild(button); + button.focus(); + + assert.expect(16); + defaultKeyTests.fullscreen(this.player, assert, true); + defaultKeyTests.mute(this.player, assert, true); + defaultKeyTests.playPause(this.player, assert, true); +}); + +QUnit.test('hotkeys are NOT ignored when focus is on a button input', function(assert) { + this.player.dispose(); + this.player = TestHelpers.makePlayer({ + controls: true, + userActions: { + hotkeys: true + } + }); + + const input = document.createElement('input'); + + input.type = 'button'; + this.player.el_.appendChild(input); + input.focus(); + + assert.expect(16); + defaultKeyTests.fullscreen(this.player, assert, true); + defaultKeyTests.mute(this.player, assert, true); + defaultKeyTests.playPause(this.player, assert, true); +}); |
