1
0
mirror of https://github.com/videojs/video.js.git synced 2024-12-23 02:04:34 +02:00
video.js/test/unit/player-user-actions.test.js

642 lines
20 KiB
JavaScript
Raw Normal View History

/* 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);
});