summaryrefslogtreecommitdiff
path: root/javascript/videojs/test/unit/player-user-actions.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'javascript/videojs/test/unit/player-user-actions.test.js')
-rw-r--r--javascript/videojs/test/unit/player-user-actions.test.js641
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);
+});