1
0
mirror of https://github.com/videojs/video.js.git synced 2024-12-23 02:04:34 +02:00
video.js/test/unit/menu.test.js
2023-06-12 13:31:06 -05:00

268 lines
9.4 KiB
JavaScript

/* eslint-env qunit */
import DomData from '../../src/js/utils/dom-data';
import MenuButton from '../../src/js/menu/menu-button.js';
import Menu from '../../src/js/menu/menu.js';
import CaptionSettingsMenuItem from '../../src/js/control-bar/text-track-controls/caption-settings-menu-item';
import MenuItem from '../../src/js/menu/menu-item.js';
import TestHelpers from './test-helpers.js';
import * as Events from '../../src/js/utils/events.js';
import sinon from 'sinon';
import window from 'global/window';
import document from 'global/document';
QUnit.module('MenuButton');
QUnit.test('should not throw an error when there is no children', function(assert) {
assert.expect(0);
const player = TestHelpers.makePlayer();
const menuButton = new MenuButton(player);
const el = menuButton.el();
try {
Events.trigger(el, 'click');
} catch (error) {
assert.ok(!error, 'click should not throw anything');
}
player.dispose();
menuButton.dispose();
});
QUnit.test('should place title list item into ul', function(assert) {
const player = TestHelpers.makePlayer();
const menuButton = new MenuButton(player, {
title: 'testTitle'
});
const menuContentElement = menuButton.el().getElementsByTagName('UL')[0];
const titleElement = menuContentElement.children[0];
assert.ok(titleElement.innerHTML === 'TestTitle', 'title element placed in ul');
menuButton.dispose();
player.dispose();
});
QUnit.test('should not include menu title in hide threshold', function(assert) {
const player = TestHelpers.makePlayer();
const menuButton = new MenuButton(player, {
title: 'testTitle'
});
assert.strictEqual(menuButton.hideThreshold_, 0, 'title should not increment hideThreshold_');
menuButton.createItems = () => [new MenuItem(player, { label: 'menu-item1' })];
menuButton.update();
assert.strictEqual(menuButton.hasClass('vjs-hidden'), false, 'menu button with single (non-title) item is not hidden');
menuButton.dispose();
player.dispose();
});
QUnit.test('clicking should display the menu', function(assert) {
assert.expect(6);
const player = TestHelpers.makePlayer();
// Make sure there's some content in the menu, even if it's just a title!
const menuButton = new MenuButton(player, {
title: 'testTitle'
});
const el = menuButton.menuButton_.el();
assert.ok(menuButton.menu !== undefined, 'menu is created');
assert.equal(menuButton.menu.hasClass('vjs-lock-showing'), false, 'menu defaults to hidden');
Events.trigger(el, 'click');
assert.equal(menuButton.menu.hasClass('vjs-lock-showing'), true, 'clicking on the menu button shows the menu');
Events.trigger(el, 'click');
assert.equal(menuButton.menu.hasClass('vjs-lock-showing'), false, 'clicking again on the menu button hides the menu');
menuButton.disable();
Events.trigger(el, 'click');
assert.equal(menuButton.menu.hasClass('vjs-lock-showing'), false, 'disable() prevents clicking from showing the menu');
menuButton.enable();
Events.trigger(el, 'click');
assert.equal(menuButton.menu.hasClass('vjs-lock-showing'), true, 'enable() allows clicking to show the menu');
menuButton.dispose();
player.dispose();
});
QUnit.test('should keep all the added menu items', function(assert) {
const player = TestHelpers.makePlayer();
const menuItems = [];
const menuItem1 = new MenuItem(player, { label: 'menu-item1' });
const menuItem2 = new MenuItem(player, { label: 'menu-item2' });
const oldCreateItems = MenuButton.prototype.createItems;
MenuButton.prototype.createItems = function() {
return menuItems;
};
const menuButton = new MenuButton(player, {});
menuItems.push(menuItem1);
menuButton.update();
assert.strictEqual(menuButton.children()[1].children().length, 1, 'the children number of the menu is 1 ');
assert.strictEqual(menuButton.children()[1].children()[0], menuItem1, 'the first child of the menu is `menuItem1`');
assert.ok(menuButton.el().contains(menuItem1.el()), 'the menu button contains the DOM element of `menuItem1`');
menuItems.push(menuItem2);
menuButton.update();
assert.strictEqual(menuButton.children()[1].children().length, 2, 'the children number of the menu is 2 after second update');
assert.strictEqual(menuButton.children()[1].children()[0], menuItem1, 'the first child of the menu is `menuItem1` after second update');
assert.strictEqual(menuButton.children()[1].children()[1], menuItem2, 'the second child of the menu is `menuItem2` after second update');
assert.ok(menuButton.el().contains(menuItem1.el()), 'the menu button contains the DOM element of `menuItem1` after second update');
assert.ok(menuButton.el().contains(menuItem2.el()), 'the menu button contains the DOM element of `menuItem2` after second update');
menuButton.dispose();
menuItem1.dispose();
menuItem2.dispose();
player.dispose();
MenuButton.prototype.createItems = oldCreateItems;
});
QUnit.test('should add or remove role menu for accessibility purpose', function(assert) {
const player = TestHelpers.makePlayer();
const menuButton = new MenuButton(player);
menuButton.createItems = () => [];
menuButton.update();
assert.equal(menuButton.menu.contentEl_.hasAttribute('role'), false, 'the menu does not have a role attribute when it contains no menu items');
menuButton.createItems = () => [new MenuItem(player, { label: 'menu-item' })];
menuButton.update();
assert.equal(menuButton.menu.contentEl_.hasAttribute('role'), true, 'the menu has a role attribute when it contains menu items');
assert.strictEqual(menuButton.menu.contentEl_.getAttribute('role'), 'menu', 'the menu role is `menu`');
menuButton.dispose();
player.dispose();
});
QUnit.test('setIcon should apply a child to the Button component', function(assert) {
// Stub a successful parsing of the SVG sprite.
sinon.stub(window.DOMParser.prototype, 'parseFromString').returns({
querySelector: () => false,
documentElement: document.createElement('span')
});
const player = TestHelpers.makePlayer({experimentalSvgIcons: true});
const menuButton = new MenuButton(player);
menuButton.createItems = () => [];
menuButton.update();
menuButton.setIcon('test');
const buttonEl = menuButton.menuButton_.el_;
const spanEl = buttonEl.getElementsByClassName('vjs-svg-icon')[0];
const svgEl = spanEl.childNodes[0];
const useEl = svgEl.childNodes[0];
assert.equal(useEl.getAttribute('href'), '#vjs-icon-test', 'use should have an href set with the correct icon url');
window.DOMParser.prototype.parseFromString.restore();
menuButton.dispose();
player.dispose();
});
QUnit.test('should remove old event listeners when the menu item adds to the new menu', function(assert) {
const player = TestHelpers.makePlayer();
const menuButton = new MenuButton(player, {});
const oldMenu = new Menu(player, { menuButton });
const newMenu = new Menu(player, { menuButton });
oldMenu.addItem('MenuItem');
const menuItem = oldMenu.children()[0];
assert.ok(menuItem instanceof MenuItem, '`menuItem` should be the instanceof of `MenuItem`');
/**
* A reusable collection of assertions.
*/
function validateMenuEventListeners(watchedMenu) {
const eventData = DomData.get(menuItem.eventBusEl_);
// `MenuButton`.`unpressButton` will be called when triggering click event on the menu item.
const unpressButtonSpy = sinon.spy(menuButton, 'unpressButton');
// `MenuButton`.`focus` will be called when triggering click event on the menu item.
const focusSpy = sinon.spy(menuButton, 'focus');
// `Menu`.`children` will be called when triggering blur event on the menu item.
const menuChildrenSpy = sinon.spy(watchedMenu, 'children');
assert.strictEqual(eventData.handlers.blur.length, 1, 'the number of blur listeners is one');
// The number of click listeners is two because `ClickableComponent`
// adds the click event listener during the construction and
// `MenuItem` inherits from `ClickableComponent`.
assert.strictEqual(eventData.handlers.click.length, 2, 'the number of click listeners is two');
const clickListenerAddedByMenu = eventData.handlers.click[1];
assert.strictEqual(
typeof clickListenerAddedByMenu.calledOnce,
'undefined',
'previous click listener wrapped in the spy should be removed'
);
const clickListenerSpy = eventData.handlers.click[1] = sinon.spy(clickListenerAddedByMenu);
TestHelpers.triggerDomEvent(menuItem.el(), 'blur');
assert.ok(menuChildrenSpy.calledOnce, '`watchedMenu`.`children` has been called');
TestHelpers.triggerDomEvent(menuItem.el(), 'click');
assert.ok(clickListenerSpy.calledOnce, 'click event listener should be called');
assert.strictEqual(clickListenerSpy.getCall(0).args[0].target, menuItem.el(), 'event target should be the `menuItem`');
assert.ok(unpressButtonSpy.calledOnce, '`menuButton`.`unpressButtion` has been called');
assert.ok(focusSpy.calledOnce, '`menuButton`.`focus` has been called');
unpressButtonSpy.restore();
focusSpy.restore();
menuChildrenSpy.restore();
}
validateMenuEventListeners(oldMenu);
newMenu.addItem(menuItem);
validateMenuEventListeners(newMenu);
const focusSpy = sinon.spy(menuButton, 'focus');
const captionMenuItem = new CaptionSettingsMenuItem(player, {
kind: 'subtitles'
});
newMenu.addItem(captionMenuItem);
TestHelpers.triggerDomEvent(captionMenuItem.el(), 'click');
assert.ok(!focusSpy.called, '`menuButton`.`focus` should never be called');
focusSpy.restore();
player.dispose();
newMenu.dispose();
oldMenu.dispose();
menuButton.dispose();
});