mirror of
https://github.com/videojs/video.js.git
synced 2025-07-05 00:58:52 +02:00
feat: playerresize event in all cases (#4864)
Use ResizeObserver when available for better and more performant resizing information, otherwise, fall back to a throttled resize event on an iframe that's the size of the player.
Allows a video.js user to disable this by setting resizeManager: false as an option since the component will not be initialized.
Add a debounce util.
This reverts #4800 (e0ed0b5
) because we end up getting two playerresize events with the dimension methods now.
This commit is contained in:
@ -18,6 +18,7 @@ The architecture of the Video.js player is centered around components. The `Play
|
|||||||
* [Specific Component Details](#specific-component-details)
|
* [Specific Component Details](#specific-component-details)
|
||||||
* [Volume Panel](#volume-panel)
|
* [Volume Panel](#volume-panel)
|
||||||
* [Text Track Settings](#text-track-settings)
|
* [Text Track Settings](#text-track-settings)
|
||||||
|
* [Resize Manager](#resize-manager)
|
||||||
|
|
||||||
## What is a Component?
|
## What is a Component?
|
||||||
|
|
||||||
@ -312,7 +313,8 @@ Player
|
|||||||
│ ├── AudioTrackButton (hidden, unless there are relevant tracks)
|
│ ├── AudioTrackButton (hidden, unless there are relevant tracks)
|
||||||
│ └── FullscreenToggle
|
│ └── FullscreenToggle
|
||||||
├── ErrorDisplay (hidden, until there is an error)
|
├── ErrorDisplay (hidden, until there is an error)
|
||||||
└── TextTrackSettings
|
├── TextTrackSettings
|
||||||
|
└── ResizeManager (hidden)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Specific Component Details
|
## Specific Component Details
|
||||||
@ -338,3 +340,37 @@ let player = videojs('myplayer', {
|
|||||||
The text track settings component is only available when using emulated text tracks.
|
The text track settings component is only available when using emulated text tracks.
|
||||||
|
|
||||||
[api]: http://docs.videojs.com/Component.html
|
[api]: http://docs.videojs.com/Component.html
|
||||||
|
|
||||||
|
### Resize Manager
|
||||||
|
|
||||||
|
This new component is in charge of triggering a `playerresize` event when the player size changed.
|
||||||
|
It uses the ResizeObserver if available or a polyfill was provided. It has no element when using the ResizeObserver.
|
||||||
|
If a ResizeObserver is not available, it will fallback to an iframe element and listen to its resize event via a debounced handler.
|
||||||
|
|
||||||
|
A ResizeObserver polyfill can be passed in like so:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var player = videojs('myplayer', {
|
||||||
|
resizeManager: {
|
||||||
|
ResizeObserver: ResizeObserverPoylfill
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
To force using the iframe fallback, pass in `null` as the `ResizeObserver`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var player = videojs('myplayer', {
|
||||||
|
resizeManager: {
|
||||||
|
ResizeObserver: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The ResizeManager can also just be disabled like so:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var player = videojs('myplayer', {
|
||||||
|
resizeManager: false
|
||||||
|
});
|
||||||
|
```
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
"docs:api": "jsdoc -c .jsdoc.json",
|
"docs:api": "jsdoc -c .jsdoc.json",
|
||||||
"postdocs:api": "node ./build/fix-api-docs.js",
|
"postdocs:api": "node ./build/fix-api-docs.js",
|
||||||
"netlify": "babel-node ./build/netlify-docs.js",
|
"netlify": "babel-node ./build/netlify-docs.js",
|
||||||
"docs:lint": "remark -- './**/*.md'",
|
"docs:lint": "remark -- './{,!(node_modules)/**/}!(CHANGELOG)*.md'",
|
||||||
"docs:fix": "remark --output -- './**/*.md'",
|
"docs:fix": "remark --output -- './{,!(node_modules)/**/}!(CHANGELOG)*.md'",
|
||||||
"babel": "babel src/js -d es5",
|
"babel": "babel src/js -d es5",
|
||||||
"prepublish": "not-in-install && run-p build || in-install",
|
"prepublish": "not-in-install && run-p build || in-install",
|
||||||
"publish": "node build/gh-release.js",
|
"publish": "node build/gh-release.js",
|
||||||
|
@ -42,3 +42,13 @@
|
|||||||
@import "components/captions-settings";
|
@import "components/captions-settings";
|
||||||
|
|
||||||
@import "print";
|
@import "print";
|
||||||
|
|
||||||
|
.vjs-resize-manager {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,7 @@ import './close-button.js';
|
|||||||
import './control-bar/control-bar.js';
|
import './control-bar/control-bar.js';
|
||||||
import './error-display.js';
|
import './error-display.js';
|
||||||
import './tracks/text-track-settings.js';
|
import './tracks/text-track-settings.js';
|
||||||
|
import './resize-manager.js';
|
||||||
|
|
||||||
// Import Html5 tech, at least for disposing the original video tag.
|
// Import Html5 tech, at least for disposing the original video tag.
|
||||||
import './tech/html5.js';
|
import './tech/html5.js';
|
||||||
@ -661,14 +662,11 @@ class Player extends Component {
|
|||||||
* @param {number} [value]
|
* @param {number} [value]
|
||||||
* The value to set the `Player`'s width to.
|
* The value to set the `Player`'s width to.
|
||||||
*
|
*
|
||||||
* @param {boolean} [skipListeners]
|
|
||||||
* Skip the playerresize event trigger
|
|
||||||
*
|
|
||||||
* @return {number}
|
* @return {number}
|
||||||
* The current width of the `Player` when getting.
|
* The current width of the `Player` when getting.
|
||||||
*/
|
*/
|
||||||
width(value, skipListeners) {
|
width(value) {
|
||||||
return this.dimension('width', value, skipListeners);
|
return this.dimension('width', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -678,21 +676,16 @@ class Player extends Component {
|
|||||||
* @param {number} [value]
|
* @param {number} [value]
|
||||||
* The value to set the `Player`'s heigth to.
|
* The value to set the `Player`'s heigth to.
|
||||||
*
|
*
|
||||||
* @param {boolean} [skipListeners]
|
|
||||||
* Skip the playerresize event trigger
|
|
||||||
*
|
|
||||||
* @return {number}
|
* @return {number}
|
||||||
* The current height of the `Player` when getting.
|
* The current height of the `Player` when getting.
|
||||||
*/
|
*/
|
||||||
height(value, skipListeners) {
|
height(value) {
|
||||||
return this.dimension('height', value, skipListeners);
|
return this.dimension('height', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A getter/setter for the `Player`'s width & height.
|
* A getter/setter for the `Player`'s width & height.
|
||||||
*
|
*
|
||||||
* @fires Player#playerresize
|
|
||||||
*
|
|
||||||
* @param {string} dimension
|
* @param {string} dimension
|
||||||
* This string can be:
|
* This string can be:
|
||||||
* - 'width'
|
* - 'width'
|
||||||
@ -701,13 +694,10 @@ class Player extends Component {
|
|||||||
* @param {number} [value]
|
* @param {number} [value]
|
||||||
* Value for dimension specified in the first argument.
|
* Value for dimension specified in the first argument.
|
||||||
*
|
*
|
||||||
* @param {boolean} [skipListeners]
|
|
||||||
* Skip the playerresize event trigger
|
|
||||||
*
|
|
||||||
* @return {number}
|
* @return {number}
|
||||||
* The dimension arguments value when getting (width/height).
|
* The dimension arguments value when getting (width/height).
|
||||||
*/
|
*/
|
||||||
dimension(dimension, value, skipListeners) {
|
dimension(dimension, value) {
|
||||||
const privDimension = dimension + '_';
|
const privDimension = dimension + '_';
|
||||||
|
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
@ -730,17 +720,6 @@ class Player extends Component {
|
|||||||
|
|
||||||
this[privDimension] = parsedVal;
|
this[privDimension] = parsedVal;
|
||||||
this.updateStyleEl_();
|
this.updateStyleEl_();
|
||||||
|
|
||||||
// skipListeners allows us to avoid triggering the resize event when setting both width and height
|
|
||||||
if (this.isReady_ && !skipListeners) {
|
|
||||||
/**
|
|
||||||
* Triggered when the player is resized.
|
|
||||||
*
|
|
||||||
* @event Player#playerresize
|
|
||||||
* @type {EventTarget~Event}
|
|
||||||
*/
|
|
||||||
this.trigger('playerresize');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3489,6 +3468,10 @@ Player.prototype.options_ = {
|
|||||||
notSupportedMessage: 'No compatible source was found for this media.'
|
notSupportedMessage: 'No compatible source was found for this media.'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!browser.IS_IE8) {
|
||||||
|
Player.prototype.options_.children.push('resizeManager');
|
||||||
|
}
|
||||||
|
|
||||||
[
|
[
|
||||||
/**
|
/**
|
||||||
* Returns whether or not the player is in the "ended" state.
|
* Returns whether or not the player is in the "ended" state.
|
||||||
|
121
src/js/resize-manager.js
Normal file
121
src/js/resize-manager.js
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* @file resize-manager.js
|
||||||
|
*/
|
||||||
|
import window from 'global/window';
|
||||||
|
import { debounce } from './utils/fn.js';
|
||||||
|
import * as Events from './utils/events.js';
|
||||||
|
import mergeOptions from './utils/merge-options.js';
|
||||||
|
import Component from './component.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Resize Manager. It is in charge of triggering `playerresize` on the player in the right conditions.
|
||||||
|
*
|
||||||
|
* It'll either create an iframe and use a debounced resize handler on it or use the new {@link https://wicg.github.io/ResizeObserver/|ResizeObserver}.
|
||||||
|
*
|
||||||
|
* If the ResizeObserver is available natively, it will be used. A polyfill can be passed in as an option.
|
||||||
|
* If a `playerresize` event is not needed, the ResizeManager component can be removed from the player, see the example below.
|
||||||
|
* @example <caption>How to disable the resize manager</caption>
|
||||||
|
* const player = videojs('#vid', {
|
||||||
|
* resizeManager: false
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* @see {@link https://wicg.github.io/ResizeObserver/|ResizeObserver specification}
|
||||||
|
*
|
||||||
|
* @extends Component
|
||||||
|
*/
|
||||||
|
class ResizeManager extends Component {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the ResizeManager.
|
||||||
|
*
|
||||||
|
* @param {Object} player
|
||||||
|
* The `Player` that this class should be attached to.
|
||||||
|
*
|
||||||
|
* @param {Object} [options]
|
||||||
|
* The key/value store of ResizeManager options.
|
||||||
|
*
|
||||||
|
* @param {Object} [options.ResizeObserver]
|
||||||
|
* A polyfill for ResizeObserver can be passed in here.
|
||||||
|
* If this is set to null it will ignore the native ResizeObserver and fall back to the iframe fallback.
|
||||||
|
*/
|
||||||
|
constructor(player, options) {
|
||||||
|
let RESIZE_OBSERVER_AVAILABLE = options.ResizeObserver || window.ResizeObserver;
|
||||||
|
|
||||||
|
// if `null` was passed, we want to disable the ResizeObserver
|
||||||
|
if (options.ResizeObserver === null) {
|
||||||
|
RESIZE_OBSERVER_AVAILABLE = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only create an element when ResizeObserver isn't available
|
||||||
|
const options_ = mergeOptions({createEl: !RESIZE_OBSERVER_AVAILABLE}, options);
|
||||||
|
|
||||||
|
super(player, options_);
|
||||||
|
|
||||||
|
this.ResizeObserver = options.ResizeObserver || window.ResizeObserver;
|
||||||
|
this.loadListener_ = null;
|
||||||
|
this.resizeObserver_ = null;
|
||||||
|
this.debouncedHandler_ = debounce(() => {
|
||||||
|
this.resizeHandler();
|
||||||
|
}, 100, false, player);
|
||||||
|
|
||||||
|
if (RESIZE_OBSERVER_AVAILABLE) {
|
||||||
|
this.resizeObserver_ = new this.ResizeObserver(this.debouncedHandler_);
|
||||||
|
this.resizeObserver_.observe(player.el());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.loadListener_ = () => {
|
||||||
|
if (this.el_.contentWindow) {
|
||||||
|
Events.on(this.el_.contentWindow, 'resize', this.debouncedHandler_);
|
||||||
|
}
|
||||||
|
this.off('load', this.loadListener_);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.on('load', this.loadListener_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createEl() {
|
||||||
|
return super.createEl('iframe', {
|
||||||
|
className: 'vjs-resize-manager'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a resize is triggered on the iframe or a resize is observed via the ResizeObserver
|
||||||
|
*
|
||||||
|
* @fires Player#playerresize
|
||||||
|
*/
|
||||||
|
resizeHandler() {
|
||||||
|
/**
|
||||||
|
* Called when the player size has changed
|
||||||
|
*
|
||||||
|
* @event Player#playerresize
|
||||||
|
* @type {EventTarget~Event}
|
||||||
|
*/
|
||||||
|
this.player_.trigger('playerresize');
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
if (this.resizeObserver_) {
|
||||||
|
this.resizeObserver_.unobserve(this.player_.el());
|
||||||
|
this.resizeObserver_.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.el_ && this.el_.contentWindow) {
|
||||||
|
Events.off(this.el_.contentWindow, 'resize', this.debouncedHandler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.loadListener_) {
|
||||||
|
this.off('load', this.loadListener_);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ResizeObserver = null;
|
||||||
|
this.resizeObserver = null;
|
||||||
|
this.debouncedHandler_ = null;
|
||||||
|
this.loadListener_ = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.registerComponent('ResizeManager', ResizeManager);
|
||||||
|
export default ResizeManager;
|
@ -3,6 +3,7 @@
|
|||||||
* @module fn
|
* @module fn
|
||||||
*/
|
*/
|
||||||
import { newGUID } from './guid.js';
|
import { newGUID } from './guid.js';
|
||||||
|
import window from 'global/window';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind (a.k.a proxy or Context). A simple method for changing the context of a function
|
* Bind (a.k.a proxy or Context). A simple method for changing the context of a function
|
||||||
@ -68,3 +69,54 @@ export const throttle = function(fn, wait) {
|
|||||||
|
|
||||||
return throttled;
|
return throttled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a debounced function that delays invoking `func` until after `wait`
|
||||||
|
* milliseconds have elapsed since the last time the debounced function was
|
||||||
|
* invoked.
|
||||||
|
*
|
||||||
|
* Inspired by lodash and underscore implementations.
|
||||||
|
*
|
||||||
|
* @param {Function} func
|
||||||
|
* The function to wrap with debounce behavior.
|
||||||
|
*
|
||||||
|
* @param {number} wait
|
||||||
|
* The number of milliseconds to wait after the last invocation.
|
||||||
|
*
|
||||||
|
* @param {boolean} [immediate]
|
||||||
|
* Whether or not to invoke the function immediately upon creation.
|
||||||
|
*
|
||||||
|
* @param {Object} [context=window]
|
||||||
|
* The "context" in which the debounced function should debounce. For
|
||||||
|
* example, if this function should be tied to a Video.js player,
|
||||||
|
* the player can be passed here. Alternatively, defaults to the
|
||||||
|
* global `window` object.
|
||||||
|
*
|
||||||
|
* @return {Function}
|
||||||
|
* A debounced function.
|
||||||
|
*/
|
||||||
|
export const debounce = function(func, wait, immediate, context = window) {
|
||||||
|
let timeout;
|
||||||
|
|
||||||
|
/* eslint-disable consistent-this */
|
||||||
|
return function() {
|
||||||
|
const self = this;
|
||||||
|
const args = arguments;
|
||||||
|
|
||||||
|
let later = function() {
|
||||||
|
timeout = null;
|
||||||
|
later = null;
|
||||||
|
if (!immediate) {
|
||||||
|
func.apply(self, args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!timeout && immediate) {
|
||||||
|
func.apply(self, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.clearTimeout(timeout);
|
||||||
|
timeout = context.setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
/* eslint-enable consistent-this */
|
||||||
|
};
|
||||||
|
@ -118,6 +118,8 @@ QUnit.test('should be able to access expected component API methods', function(a
|
|||||||
assert.ok(comp.clearInterval, 'clearInterval exists');
|
assert.ok(comp.clearInterval, 'clearInterval exists');
|
||||||
assert.ok(comp.setTimeout, 'setTimeout exists');
|
assert.ok(comp.setTimeout, 'setTimeout exists');
|
||||||
assert.ok(comp.clearTimeout, 'clearTimeout exists');
|
assert.ok(comp.clearTimeout, 'clearTimeout exists');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should be able to access expected MediaTech API methods', function(assert) {
|
QUnit.test('should be able to access expected MediaTech API methods', function(assert) {
|
||||||
@ -289,4 +291,6 @@ QUnit.test('should extend Component', function(assert) {
|
|||||||
const noMethods = new NoMethods({});
|
const noMethods = new NoMethods({});
|
||||||
|
|
||||||
assert.ok(noMethods.on, 'should extend component with no methods or constructor');
|
assert.ok(noMethods.on, 'should extend component with no methods or constructor');
|
||||||
|
|
||||||
|
myComponent.dispose();
|
||||||
});
|
});
|
||||||
|
@ -24,6 +24,7 @@ QUnit.test('should localize its text', function(assert) {
|
|||||||
assert.ok(el.nodeName.toLowerCase().match('button'));
|
assert.ok(el.nodeName.toLowerCase().match('button'));
|
||||||
assert.ok(el.innerHTML.match(/vjs-control-text"?>Juego/));
|
assert.ok(el.innerHTML.match(/vjs-control-text"?>Juego/));
|
||||||
assert.equal(el.getAttribute('title'), 'Juego');
|
assert.equal(el.getAttribute('title'), 'Juego');
|
||||||
player.dispose();
|
|
||||||
|
|
||||||
|
testButton.dispose();
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
@ -86,6 +86,8 @@ QUnit.test('should create an element', function(assert) {
|
|||||||
const comp = new Component(getFakePlayer(), {});
|
const comp = new Component(getFakePlayer(), {});
|
||||||
|
|
||||||
assert.ok(comp.el().nodeName);
|
assert.ok(comp.el().nodeName);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should add a child component', function(assert) {
|
QUnit.test('should add a child component', function(assert) {
|
||||||
@ -98,6 +100,8 @@ QUnit.test('should add a child component', function(assert) {
|
|||||||
assert.ok(comp.el().childNodes[0] === child.el());
|
assert.ok(comp.el().childNodes[0] === child.el());
|
||||||
assert.ok(comp.getChild('component') === child);
|
assert.ok(comp.getChild('component') === child);
|
||||||
assert.ok(comp.getChildById(child.id()) === child);
|
assert.ok(comp.getChildById(child.id()) === child);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should add a child component to an index', function(assert) {
|
QUnit.test('should add a child component to an index', function(assert) {
|
||||||
@ -129,6 +133,8 @@ QUnit.test('should add a child component to an index', function(assert) {
|
|||||||
assert.ok(comp.children().length === 5);
|
assert.ok(comp.children().length === 5);
|
||||||
assert.ok(comp.children()[3] === child3);
|
assert.ok(comp.children()[3] === child3);
|
||||||
assert.ok(comp.children()[4] === child2);
|
assert.ok(comp.children()[4] === child2);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('addChild should throw if the child does not exist', function(assert) {
|
QUnit.test('addChild should throw if the child does not exist', function(assert) {
|
||||||
@ -138,6 +144,7 @@ QUnit.test('addChild should throw if the child does not exist', function(assert)
|
|||||||
comp.addChild('non-existent-child');
|
comp.addChild('non-existent-child');
|
||||||
}, new Error('Component Non-existent-child does not exist'), 'addChild threw');
|
}, new Error('Component Non-existent-child does not exist'), 'addChild threw');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('addChild with instance should allow getting child correctly', function(assert) {
|
QUnit.test('addChild with instance should allow getting child correctly', function(assert) {
|
||||||
@ -151,6 +158,8 @@ QUnit.test('addChild with instance should allow getting child correctly', functi
|
|||||||
comp.addChild(comp2);
|
comp.addChild(comp2);
|
||||||
assert.ok(comp.getChild('foo'), 'we can get child with camelCase');
|
assert.ok(comp.getChild('foo'), 'we can get child with camelCase');
|
||||||
assert.ok(comp.getChild('Foo'), 'we can get child with TitleCase');
|
assert.ok(comp.getChild('Foo'), 'we can get child with TitleCase');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should add a child component with title case name', function(assert) {
|
QUnit.test('should add a child component with title case name', function(assert) {
|
||||||
@ -163,6 +172,8 @@ QUnit.test('should add a child component with title case name', function(assert)
|
|||||||
assert.ok(comp.el().childNodes[0] === child.el());
|
assert.ok(comp.el().childNodes[0] === child.el());
|
||||||
assert.ok(comp.getChild('Component') === child);
|
assert.ok(comp.getChild('Component') === child);
|
||||||
assert.ok(comp.getChildById(child.id()) === child);
|
assert.ok(comp.getChildById(child.id()) === child);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should init child components from options', function(assert) {
|
QUnit.test('should init child components from options', function(assert) {
|
||||||
@ -174,6 +185,8 @@ QUnit.test('should init child components from options', function(assert) {
|
|||||||
|
|
||||||
assert.ok(comp.children().length === 1);
|
assert.ok(comp.children().length === 1);
|
||||||
assert.ok(comp.el().childNodes.length === 1);
|
assert.ok(comp.el().childNodes.length === 1);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should init child components from simple children array', function(assert) {
|
QUnit.test('should init child components from simple children array', function(assert) {
|
||||||
@ -187,6 +200,8 @@ QUnit.test('should init child components from simple children array', function(a
|
|||||||
|
|
||||||
assert.ok(comp.children().length === 3);
|
assert.ok(comp.children().length === 3);
|
||||||
assert.ok(comp.el().childNodes.length === 3);
|
assert.ok(comp.el().childNodes.length === 3);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should init child components from children array of objects', function(assert) {
|
QUnit.test('should init child components from children array of objects', function(assert) {
|
||||||
@ -200,6 +215,8 @@ QUnit.test('should init child components from children array of objects', functi
|
|||||||
|
|
||||||
assert.ok(comp.children().length === 3);
|
assert.ok(comp.children().length === 3);
|
||||||
assert.ok(comp.el().childNodes.length === 3);
|
assert.ok(comp.el().childNodes.length === 3);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should do a deep merge of child options', function(assert) {
|
QUnit.test('should do a deep merge of child options', function(assert) {
|
||||||
@ -236,6 +253,7 @@ QUnit.test('should do a deep merge of child options', function(assert) {
|
|||||||
|
|
||||||
// Reset default component options to none
|
// Reset default component options to none
|
||||||
Component.prototype.options_ = null;
|
Component.prototype.options_ = null;
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should init child components from component options', function(assert) {
|
QUnit.test('should init child components from component options', function(assert) {
|
||||||
@ -246,6 +264,8 @@ QUnit.test('should init child components from component options', function(asser
|
|||||||
|
|
||||||
assert.ok(!testComp.childNameIndex_.TestComponent2, 'we do not have testComponent2');
|
assert.ok(!testComp.childNameIndex_.TestComponent2, 'we do not have testComponent2');
|
||||||
assert.ok(testComp.childNameIndex_.TestComponent4, 'we have a testComponent4');
|
assert.ok(testComp.childNameIndex_.TestComponent4, 'we have a testComponent4');
|
||||||
|
|
||||||
|
testComp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should allows setting child options at the parent options level', function(assert) {
|
QUnit.test('should allows setting child options at the parent options level', function(assert) {
|
||||||
@ -271,6 +291,7 @@ QUnit.test('should allows setting child options at the parent options level', fu
|
|||||||
}
|
}
|
||||||
assert.equal(parent.children()[0].options_.foo, true, 'child options set when children array is used');
|
assert.equal(parent.children()[0].options_.foo, true, 'child options set when children array is used');
|
||||||
assert.equal(parent.children().length, 1, 'we should only have one child');
|
assert.equal(parent.children().length, 1, 'we should only have one child');
|
||||||
|
parent.dispose();
|
||||||
|
|
||||||
// using children object
|
// using children object
|
||||||
options = {
|
options = {
|
||||||
@ -294,6 +315,7 @@ QUnit.test('should allows setting child options at the parent options level', fu
|
|||||||
}
|
}
|
||||||
assert.equal(parent.children()[0].options_.foo, true, 'child options set when children object is used');
|
assert.equal(parent.children()[0].options_.foo, true, 'child options set when children object is used');
|
||||||
assert.equal(parent.children().length, 1, 'we should only have one child');
|
assert.equal(parent.children().length, 1, 'we should only have one child');
|
||||||
|
parent.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should dispose of component and children', function(assert) {
|
QUnit.test('should dispose of component and children', function(assert) {
|
||||||
@ -349,6 +371,8 @@ QUnit.test('should add and remove event listeners to element', function(assert)
|
|||||||
comp.trigger('test-event');
|
comp.trigger('test-event');
|
||||||
comp.off('test-event', testListener);
|
comp.off('test-event', testListener);
|
||||||
comp.trigger('test-event');
|
comp.trigger('test-event');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should trigger a listener once using one()', function(assert) {
|
QUnit.test('should trigger a listener once using one()', function(assert) {
|
||||||
@ -363,6 +387,8 @@ QUnit.test('should trigger a listener once using one()', function(assert) {
|
|||||||
comp.one('test-event', testListener);
|
comp.one('test-event', testListener);
|
||||||
comp.trigger('test-event');
|
comp.trigger('test-event');
|
||||||
comp.trigger('test-event');
|
comp.trigger('test-event');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should be possible to pass data when you trigger an event', function(assert) {
|
QUnit.test('should be possible to pass data when you trigger an event', function(assert) {
|
||||||
@ -381,6 +407,8 @@ QUnit.test('should be possible to pass data when you trigger an event', function
|
|||||||
comp.one('test-event', testListener);
|
comp.one('test-event', testListener);
|
||||||
comp.trigger('test-event', {d1: data1, d2: data2});
|
comp.trigger('test-event', {d1: data1, d2: data2});
|
||||||
comp.trigger('test-event');
|
comp.trigger('test-event');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should add listeners to other components and remove them', function(assert) {
|
QUnit.test('should add listeners to other components and remove them', function(assert) {
|
||||||
@ -452,6 +480,9 @@ QUnit.test('should add listeners to other components that are fired once', funct
|
|||||||
assert.equal(listenerFired, 1, 'listener was executed once');
|
assert.equal(listenerFired, 1, 'listener was executed once');
|
||||||
comp2.trigger('test-event');
|
comp2.trigger('test-event');
|
||||||
assert.equal(listenerFired, 1, 'listener was executed only once');
|
assert.equal(listenerFired, 1, 'listener was executed only once');
|
||||||
|
|
||||||
|
comp1.dispose();
|
||||||
|
comp2.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should add listeners to other element and remove them', function(assert) {
|
QUnit.test('should add listeners to other element and remove them', function(assert) {
|
||||||
@ -491,6 +522,8 @@ QUnit.test('should add listeners to other element and remove them', function(ass
|
|||||||
}
|
}
|
||||||
Events.trigger(el, 'dispose');
|
Events.trigger(el, 'dispose');
|
||||||
assert.ok(true, 'this component removed dispose listeners from other element');
|
assert.ok(true, 'this component removed dispose listeners from other element');
|
||||||
|
|
||||||
|
comp1.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should add listeners to other components that are fired once', function(assert) {
|
QUnit.test('should add listeners to other components that are fired once', function(assert) {
|
||||||
@ -509,6 +542,8 @@ QUnit.test('should add listeners to other components that are fired once', funct
|
|||||||
assert.equal(listenerFired, 1, 'listener was executed once');
|
assert.equal(listenerFired, 1, 'listener was executed once');
|
||||||
Events.trigger(el, 'test-event');
|
Events.trigger(el, 'test-event');
|
||||||
assert.equal(listenerFired, 1, 'listener was executed only once');
|
assert.equal(listenerFired, 1, 'listener was executed only once');
|
||||||
|
|
||||||
|
comp1.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should trigger a listener when ready', function(assert) {
|
QUnit.test('should trigger a listener when ready', function(assert) {
|
||||||
@ -549,6 +584,8 @@ QUnit.test('should trigger a listener when ready', function(assert) {
|
|||||||
assert.ok(!initListenerFired, 'init listener should be removed');
|
assert.ok(!initListenerFired, 'init listener should be removed');
|
||||||
assert.ok(!methodListenerFired, 'method listener should be removed');
|
assert.ok(!methodListenerFired, 'method listener should be removed');
|
||||||
assert.ok(!syncListenerFired, 'sync listener should be removed');
|
assert.ok(!syncListenerFired, 'sync listener should be removed');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should not retrigger a listener when the listener calls triggerReady', function(assert) {
|
QUnit.test('should not retrigger a listener when the listener calls triggerReady', function(assert) {
|
||||||
@ -573,6 +610,8 @@ QUnit.test('should not retrigger a listener when the listener calls triggerReady
|
|||||||
this.clock.tick(100);
|
this.clock.tick(100);
|
||||||
|
|
||||||
assert.equal(timesCalled, 1, 'triggerReady from inside a ready handler does not result in an infinite loop');
|
assert.equal(timesCalled, 1, 'triggerReady from inside a ready handler does not result in an infinite loop');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should add and remove a CSS class', function(assert) {
|
QUnit.test('should add and remove a CSS class', function(assert) {
|
||||||
@ -586,6 +625,8 @@ QUnit.test('should add and remove a CSS class', function(assert) {
|
|||||||
assert.ok(comp.el().className.indexOf('test-class') !== -1);
|
assert.ok(comp.el().className.indexOf('test-class') !== -1);
|
||||||
comp.toggleClass('test-class');
|
comp.toggleClass('test-class');
|
||||||
assert.ok(comp.el().className.indexOf('test-class') === -1);
|
assert.ok(comp.el().className.indexOf('test-class') === -1);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should show and hide an element', function(assert) {
|
QUnit.test('should show and hide an element', function(assert) {
|
||||||
@ -595,6 +636,8 @@ QUnit.test('should show and hide an element', function(assert) {
|
|||||||
assert.ok(comp.hasClass('vjs-hidden') === true);
|
assert.ok(comp.hasClass('vjs-hidden') === true);
|
||||||
comp.show();
|
comp.show();
|
||||||
assert.ok(comp.hasClass('vjs-hidden') === false);
|
assert.ok(comp.hasClass('vjs-hidden') === false);
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('dimension() should treat NaN and null as zero', function(assert) {
|
QUnit.test('dimension() should treat NaN and null as zero', function(assert) {
|
||||||
@ -624,6 +667,8 @@ QUnit.test('dimension() should treat NaN and null as zero', function(assert) {
|
|||||||
newWidth = comp.dimension('width', undefined);
|
newWidth = comp.dimension('width', undefined);
|
||||||
|
|
||||||
assert.equal(newWidth, width, 'we did not set the width with undefined');
|
assert.equal(newWidth, width, 'we did not set the width with undefined');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should change the width and height of a component', function(assert) {
|
QUnit.test('should change the width and height of a component', function(assert) {
|
||||||
@ -654,6 +699,8 @@ QUnit.test('should change the width and height of a component', function(assert)
|
|||||||
comp.height('auto');
|
comp.height('auto');
|
||||||
assert.ok(comp.width() === 1000, 'forced width was removed');
|
assert.ok(comp.width() === 1000, 'forced width was removed');
|
||||||
assert.ok(comp.height() === 0, 'forced height was removed');
|
assert.ok(comp.height() === 0, 'forced height was removed');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should get the computed dimensions', function(assert) {
|
QUnit.test('should get the computed dimensions', function(assert) {
|
||||||
@ -683,6 +730,7 @@ QUnit.test('should get the computed dimensions', function(assert) {
|
|||||||
assert.equal(comp.currentDimensions().width + 'px', computedWidth, 'matches computed width');
|
assert.equal(comp.currentDimensions().width + 'px', computedWidth, 'matches computed width');
|
||||||
assert.equal(comp.currentDimensions().height + 'px', computedHeight, 'matches computed width');
|
assert.equal(comp.currentDimensions().height + 'px', computedHeight, 'matches computed width');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should use a defined content el for appending children', function(assert) {
|
QUnit.test('should use a defined content el for appending children', function(assert) {
|
||||||
@ -711,6 +759,8 @@ QUnit.test('should use a defined content el for appending children', function(as
|
|||||||
assert.ok(comp.el().childNodes[0].id === 'contentEl', 'Content El should still exist');
|
assert.ok(comp.el().childNodes[0].id === 'contentEl', 'Content El should still exist');
|
||||||
assert.ok(comp.el().childNodes[0].childNodes[0] !== child.el(),
|
assert.ok(comp.el().childNodes[0].childNodes[0] !== child.el(),
|
||||||
'Child el should be removed.');
|
'Child el should be removed.');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should emit a tap event', function(assert) {
|
QUnit.test('should emit a tap event', function(assert) {
|
||||||
@ -769,6 +819,7 @@ QUnit.test('should emit a tap event', function(assert) {
|
|||||||
|
|
||||||
// Reset to orignial value
|
// Reset to orignial value
|
||||||
browser.TOUCH_ENABLED = origTouch;
|
browser.TOUCH_ENABLED = origTouch;
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should provide timeout methods that automatically get cleared on component disposal', function(assert) {
|
QUnit.test('should provide timeout methods that automatically get cleared on component disposal', function(assert) {
|
||||||
@ -919,6 +970,8 @@ QUnit.test('$ and $$ functions', function(assert) {
|
|||||||
|
|
||||||
assert.strictEqual(comp.$('div'), children[0], '$ defaults to contentEl as scope');
|
assert.strictEqual(comp.$('div'), children[0], '$ defaults to contentEl as scope');
|
||||||
assert.strictEqual(comp.$$('div').length, children.length, '$$ defaults to contentEl as scope');
|
assert.strictEqual(comp.$$('div').length, children.length, '$$ defaults to contentEl as scope');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should use the stateful mixin', function(assert) {
|
QUnit.test('should use the stateful mixin', function(assert) {
|
||||||
@ -929,4 +982,6 @@ QUnit.test('should use the stateful mixin', function(assert) {
|
|||||||
|
|
||||||
comp.setState({foo: 'bar'});
|
comp.setState({foo: 'bar'});
|
||||||
assert.strictEqual(comp.state.foo, 'bar', 'the component passes a basic stateful test');
|
assert.strictEqual(comp.state.foo, 'bar', 'the component passes a basic stateful test');
|
||||||
|
|
||||||
|
comp.dispose();
|
||||||
});
|
});
|
||||||
|
@ -31,6 +31,7 @@ QUnit.test('should hide volume control if it\'s not supported', function(assert)
|
|||||||
|
|
||||||
assert.ok(volumeControl.hasClass('vjs-hidden'), 'volumeControl is not hidden');
|
assert.ok(volumeControl.hasClass('vjs-hidden'), 'volumeControl is not hidden');
|
||||||
assert.ok(muteToggle.hasClass('vjs-hidden'), 'muteToggle is not hidden');
|
assert.ok(muteToggle.hasClass('vjs-hidden'), 'muteToggle is not hidden');
|
||||||
|
|
||||||
player.dispose();
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -56,6 +57,8 @@ QUnit.test('should test and toggle volume control on `loadstart`', function(asse
|
|||||||
|
|
||||||
assert.equal(volumeControl.hasClass('vjs-hidden'), false, 'volumeControl does not show itself');
|
assert.equal(volumeControl.hasClass('vjs-hidden'), false, 'volumeControl does not show itself');
|
||||||
assert.equal(muteToggle.hasClass('vjs-hidden'), false, 'muteToggle does not show itself');
|
assert.equal(muteToggle.hasClass('vjs-hidden'), false, 'muteToggle does not show itself');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('calculateDistance should use changedTouches, if available', function(assert) {
|
QUnit.test('calculateDistance should use changedTouches, if available', function(assert) {
|
||||||
@ -78,6 +81,8 @@ QUnit.test('calculateDistance should use changedTouches, if available', function
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert.equal(slider.calculateDistance(event), 0.5, 'we should have touched exactly in the center, so, the ratio should be half');
|
assert.equal(slider.calculateDistance(event), 0.5, 'we should have touched exactly in the center, so, the ratio should be half');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should hide playback rate control if it\'s not supported', function(assert) {
|
QUnit.test('should hide playback rate control if it\'s not supported', function(assert) {
|
||||||
@ -87,6 +92,7 @@ QUnit.test('should hide playback rate control if it\'s not supported', function(
|
|||||||
const playbackRate = new PlaybackRateMenuButton(player);
|
const playbackRate = new PlaybackRateMenuButton(player);
|
||||||
|
|
||||||
assert.ok(playbackRate.el().className.indexOf('vjs-hidden') >= 0, 'playbackRate is not hidden');
|
assert.ok(playbackRate.el().className.indexOf('vjs-hidden') >= 0, 'playbackRate is not hidden');
|
||||||
|
|
||||||
player.dispose();
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -97,9 +103,11 @@ QUnit.test('Fullscreen control text should be correct when fullscreenchange is t
|
|||||||
player.isFullscreen(true);
|
player.isFullscreen(true);
|
||||||
player.trigger('fullscreenchange');
|
player.trigger('fullscreenchange');
|
||||||
assert.equal(fullscreentoggle.controlText(), 'Non-Fullscreen', 'Control Text is correct while switching to fullscreen mode');
|
assert.equal(fullscreentoggle.controlText(), 'Non-Fullscreen', 'Control Text is correct while switching to fullscreen mode');
|
||||||
|
|
||||||
player.isFullscreen(false);
|
player.isFullscreen(false);
|
||||||
player.trigger('fullscreenchange');
|
player.trigger('fullscreenchange');
|
||||||
assert.equal(fullscreentoggle.controlText(), 'Fullscreen', 'Control Text is correct while switching back to normal mode');
|
assert.equal(fullscreentoggle.controlText(), 'Fullscreen', 'Control Text is correct while switching back to normal mode');
|
||||||
|
|
||||||
player.dispose();
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,6 +126,8 @@ if (Html5.isSupported()) {
|
|||||||
|
|
||||||
assert.equal(player.volume(), 1, 'volume is same');
|
assert.equal(player.volume(), 1, 'volume is same');
|
||||||
assert.equal(player.muted(), true, 'player is muted');
|
assert.equal(player.muted(), true, 'player is muted');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('Clicking MuteToggle when volume is 0 and muted is false should set volume to lastVolume and keep muted false', function(assert) {
|
QUnit.test('Clicking MuteToggle when volume is 0 and muted is false should set volume to lastVolume and keep muted false', function(assert) {
|
||||||
@ -132,6 +142,8 @@ if (Html5.isSupported()) {
|
|||||||
|
|
||||||
assert.equal(player.volume(), 1, 'volume is set to lastVolume');
|
assert.equal(player.volume(), 1, 'volume is set to lastVolume');
|
||||||
assert.equal(player.muted(), false, 'muted remains false');
|
assert.equal(player.muted(), false, 'muted remains false');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('Clicking MuteToggle when volume is 0 and muted is true should set volume to lastVolume and sets muted to false', function(assert) {
|
QUnit.test('Clicking MuteToggle when volume is 0 and muted is true should set volume to lastVolume and sets muted to false', function(assert) {
|
||||||
@ -146,6 +158,8 @@ if (Html5.isSupported()) {
|
|||||||
|
|
||||||
assert.equal(player.volume(), 0.5, 'volume is set to lastVolume');
|
assert.equal(player.volume(), 0.5, 'volume is set to lastVolume');
|
||||||
assert.equal(player.muted(), false, 'muted is set to false');
|
assert.equal(player.muted(), false, 'muted is set to false');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('Clicking MuteToggle when volume is 0, lastVolume is less than 0.1, and muted is true sets volume to 0.1 and muted to false', function(assert) {
|
QUnit.test('Clicking MuteToggle when volume is 0, lastVolume is less than 0.1, and muted is true sets volume to 0.1 and muted to false', function(assert) {
|
||||||
@ -161,6 +175,8 @@ if (Html5.isSupported()) {
|
|||||||
// `Number.prototype.toFixed()` is used here to circumvent IE9 rounding issues
|
// `Number.prototype.toFixed()` is used here to circumvent IE9 rounding issues
|
||||||
assert.equal(player.volume().toFixed(1), (0.1).toFixed(1), 'since lastVolume is less than 0.1, volume is set to 0.1');
|
assert.equal(player.volume().toFixed(1), (0.1).toFixed(1), 'since lastVolume is less than 0.1, volume is set to 0.1');
|
||||||
assert.equal(player.muted(), false, 'muted is set to false');
|
assert.equal(player.muted(), false, 'muted is set to false');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('ARIA value of VolumeBar should start at 100', function(assert) {
|
QUnit.test('ARIA value of VolumeBar should start at 100', function(assert) {
|
||||||
@ -170,6 +186,8 @@ if (Html5.isSupported()) {
|
|||||||
this.clock.tick(1);
|
this.clock.tick(1);
|
||||||
|
|
||||||
assert.equal(volumeBar.el_.getAttribute('aria-valuenow'), 100, 'ARIA value of VolumeBar is 100');
|
assert.equal(volumeBar.el_.getAttribute('aria-valuenow'), 100, 'ARIA value of VolumeBar is 100');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('Muting with MuteToggle should set ARIA value of VolumeBar to 0', function(assert) {
|
QUnit.test('Muting with MuteToggle should set ARIA value of VolumeBar to 0', function(assert) {
|
||||||
@ -193,5 +211,7 @@ if (Html5.isSupported()) {
|
|||||||
assert.equal(player.volume(), 1, 'Volume remains 1');
|
assert.equal(player.volume(), 1, 'Volume remains 1');
|
||||||
assert.equal(player.muted(), true, 'Muted is true');
|
assert.equal(player.muted(), true, 'Muted is true');
|
||||||
assert.equal(volumeBar.el_.getAttribute('aria-valuenow'), 0, 'ARIA value of VolumeBar is 0');
|
assert.equal(volumeBar.el_.getAttribute('aria-valuenow'), 0, 'ARIA value of VolumeBar is 0');
|
||||||
|
|
||||||
|
player.dispose();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ QUnit.test('should place title list item into ul', function(assert) {
|
|||||||
|
|
||||||
assert.ok(titleElement.innerHTML === 'TestTitle', 'title element placed in ul');
|
assert.ok(titleElement.innerHTML === 'TestTitle', 'title element placed in ul');
|
||||||
|
|
||||||
|
menuButton.dispose();
|
||||||
player.dispose();
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,5 +72,6 @@ QUnit.test('clicking should display the menu', function(assert) {
|
|||||||
|
|
||||||
assert.equal(menuButton.menu.hasClass('vjs-lock-showing'), true, 'enable() allows clicking to show the menu');
|
assert.equal(menuButton.menu.hasClass('vjs-lock-showing'), true, 'enable() allows clicking to show the menu');
|
||||||
|
|
||||||
|
menuButton.dispose();
|
||||||
player.dispose();
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
@ -1709,32 +1709,3 @@ QUnit.test('player.duration() sets the value of player.cache_.duration', functio
|
|||||||
player.duration(200);
|
player.duration(200);
|
||||||
assert.equal(player.duration(), 200, 'duration() set and get integer duration value');
|
assert.equal(player.duration(), 200, 'duration() set and get integer duration value');
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should fire playerresize when player is resized', function(assert) {
|
|
||||||
assert.expect(2);
|
|
||||||
|
|
||||||
const player = TestHelpers.makePlayer();
|
|
||||||
|
|
||||||
player.on('playerresize', function() {
|
|
||||||
assert.ok(true, 'playerresize fired');
|
|
||||||
});
|
|
||||||
|
|
||||||
player.width(400);
|
|
||||||
player.height(300);
|
|
||||||
|
|
||||||
player.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.test('should fire playerresize exactly once for a two-dimensional resize', function(assert) {
|
|
||||||
assert.expect(1);
|
|
||||||
|
|
||||||
const player = TestHelpers.makePlayer();
|
|
||||||
|
|
||||||
player.on('playerresize', function() {
|
|
||||||
assert.ok(true, 'playerresize fired once');
|
|
||||||
});
|
|
||||||
|
|
||||||
player.dimensions(400, 300);
|
|
||||||
|
|
||||||
player.dispose();
|
|
||||||
});
|
|
||||||
|
@ -18,6 +18,7 @@ QUnit.module('PosterImage', {
|
|||||||
return this.poster_;
|
return this.poster_;
|
||||||
},
|
},
|
||||||
handler_: null,
|
handler_: null,
|
||||||
|
off() {},
|
||||||
on(type, handler) {
|
on(type, handler) {
|
||||||
this.handler_ = handler;
|
this.handler_ = handler;
|
||||||
},
|
},
|
||||||
@ -44,6 +45,8 @@ QUnit.test('should create and update a poster image', function(assert) {
|
|||||||
this.mockPlayer.trigger('posterchange');
|
this.mockPlayer.trigger('posterchange');
|
||||||
backgroundImage = posterImage.el().style.backgroundImage;
|
backgroundImage = posterImage.el().style.backgroundImage;
|
||||||
assert.notEqual(backgroundImage.indexOf(this.poster2), -1, 'Background image updated');
|
assert.notEqual(backgroundImage.indexOf(this.poster2), -1, 'Background image updated');
|
||||||
|
|
||||||
|
posterImage.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should create and update a fallback image in older browsers', function(assert) {
|
QUnit.test('should create and update a fallback image in older browsers', function(assert) {
|
||||||
@ -61,6 +64,8 @@ QUnit.test('should create and update a fallback image in older browsers', functi
|
|||||||
assert.notEqual(posterImage.fallbackImg_.src.indexOf(this.poster2),
|
assert.notEqual(posterImage.fallbackImg_.src.indexOf(this.poster2),
|
||||||
-1,
|
-1,
|
||||||
'Fallback image updated');
|
'Fallback image updated');
|
||||||
|
|
||||||
|
posterImage.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should remove itself from the document flow when there is no poster', function(assert) {
|
QUnit.test('should remove itself from the document flow when there is no poster', function(assert) {
|
||||||
@ -81,6 +86,8 @@ QUnit.test('should remove itself from the document flow when there is no poster'
|
|||||||
assert.equal(posterImage.hasClass('vjs-hidden'),
|
assert.equal(posterImage.hasClass('vjs-hidden'),
|
||||||
false,
|
false,
|
||||||
'Poster image shows again when there is a source');
|
'Poster image shows again when there is a source');
|
||||||
|
|
||||||
|
posterImage.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should hide the poster in the appropriate player states', function(assert) {
|
QUnit.test('should hide the poster in the appropriate player states', function(assert) {
|
||||||
@ -106,4 +113,6 @@ QUnit.test('should hide the poster in the appropriate player states', function(a
|
|||||||
assert.equal(TestHelpers.getComputedStyle(el, 'display'),
|
assert.equal(TestHelpers.getComputedStyle(el, 'display'),
|
||||||
'block',
|
'block',
|
||||||
'The poster continues to show when playing audio');
|
'The poster continues to show when playing audio');
|
||||||
|
|
||||||
|
posterImage.dispose();
|
||||||
});
|
});
|
||||||
|
102
test/unit/resize-manager.test.js
Normal file
102
test/unit/resize-manager.test.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/* eslint-env qunit */
|
||||||
|
import ResizeManager from '../../src/js/resize-manager.js';
|
||||||
|
import TestHelpers from './test-helpers.js';
|
||||||
|
import * as browser from '../../src/js/utils/browser.js';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
|
||||||
|
if (!browser.IS_IE8) {
|
||||||
|
|
||||||
|
QUnit.module('ResizeManager', {
|
||||||
|
beforeEach() {
|
||||||
|
this.clock = sinon.useFakeTimers();
|
||||||
|
this.player = TestHelpers.makePlayer();
|
||||||
|
},
|
||||||
|
afterEach() {
|
||||||
|
this.player.dispose();
|
||||||
|
this.clock.restore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('ResizeManager creates an iframe if ResizeObserver is not available', function(assert) {
|
||||||
|
const rm = new ResizeManager(this.player, {ResizeObserver: null});
|
||||||
|
|
||||||
|
assert.equal(rm.el().tagName.toLowerCase(), 'iframe', 'we got an iframe');
|
||||||
|
|
||||||
|
rm.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('ResizeManager uses the ResizeObserver, if given', function(assert) {
|
||||||
|
let roCreated = false;
|
||||||
|
let observeCalled = false;
|
||||||
|
let unobserveCalled = false;
|
||||||
|
let disconnectCalled = false;
|
||||||
|
let sameEl = false;
|
||||||
|
|
||||||
|
class MyResizeObserver {
|
||||||
|
constructor(fn) {
|
||||||
|
roCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
observe(el) {
|
||||||
|
observeCalled = true;
|
||||||
|
this.el = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
unobserve(el) {
|
||||||
|
unobserveCalled = true;
|
||||||
|
sameEl = this.el === el;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
disconnectCalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rm = new ResizeManager(this.player, {ResizeObserver: MyResizeObserver});
|
||||||
|
|
||||||
|
assert.ok(roCreated, 'we intantiated the RO that was passed');
|
||||||
|
assert.ok(observeCalled, 'we observed the RO');
|
||||||
|
assert.equal(rm.resizeObserver_.el, this.player.el(), 'we observed the player el');
|
||||||
|
|
||||||
|
rm.dispose();
|
||||||
|
|
||||||
|
assert.ok(unobserveCalled, 'we unobserve when disposed');
|
||||||
|
assert.ok(sameEl, 'we unobserve the same el as we observed');
|
||||||
|
assert.ok(disconnectCalled, 'we disconnected when disposed');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('ResizeManager triggers `playerresize` when the observer method is called', function(assert) {
|
||||||
|
let observer;
|
||||||
|
|
||||||
|
class MyResizeObserver {
|
||||||
|
constructor(fn) {
|
||||||
|
observer = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
observe(el) {
|
||||||
|
this.el = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
unobserve(el) {
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let playerresizeCalled = 0;
|
||||||
|
const rm = new ResizeManager(this.player, {ResizeObserver: MyResizeObserver});
|
||||||
|
|
||||||
|
this.player.on('playerresize', function() {
|
||||||
|
playerresizeCalled++;
|
||||||
|
});
|
||||||
|
observer();
|
||||||
|
|
||||||
|
this.clock.tick(100);
|
||||||
|
|
||||||
|
assert.equal(playerresizeCalled, 1, 'playerresize was triggered');
|
||||||
|
|
||||||
|
rm.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
@ -33,6 +33,7 @@ QUnit.test('listen to remove and add track events in native audio tracks', funct
|
|||||||
|
|
||||||
Html5.prototype.audioTracks = function() {
|
Html5.prototype.audioTracks = function() {
|
||||||
return {
|
return {
|
||||||
|
removeEventListener() {},
|
||||||
addEventListener(type, handler) {
|
addEventListener(type, handler) {
|
||||||
events[type] = true;
|
events[type] = true;
|
||||||
}
|
}
|
||||||
@ -72,6 +73,7 @@ QUnit.test('listen to remove and add track events in native audio tracks', funct
|
|||||||
|
|
||||||
Html5.TEST_VID = oldTestVid;
|
Html5.TEST_VID = oldTestVid;
|
||||||
Html5.prototype.audioTracks = oldAudioTracks;
|
Html5.prototype.audioTracks = oldAudioTracks;
|
||||||
|
html.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('html5 tech supports native audio tracks if the video supports it', function(assert) {
|
QUnit.test('html5 tech supports native audio tracks if the video supports it', function(assert) {
|
||||||
|
@ -82,6 +82,7 @@ QUnit.test('listen to remove and add track events in native text tracks', functi
|
|||||||
|
|
||||||
Html5.prototype.textTracks = function() {
|
Html5.prototype.textTracks = function() {
|
||||||
return {
|
return {
|
||||||
|
removeEventListener() {},
|
||||||
addEventListener(type, handler) {
|
addEventListener(type, handler) {
|
||||||
events[type] = true;
|
events[type] = true;
|
||||||
}
|
}
|
||||||
@ -121,6 +122,8 @@ QUnit.test('listen to remove and add track events in native text tracks', functi
|
|||||||
|
|
||||||
Html5.TEST_VID = oldTestVid;
|
Html5.TEST_VID = oldTestVid;
|
||||||
Html5.prototype.textTracks = oldTextTracks;
|
Html5.prototype.textTracks = oldTextTracks;
|
||||||
|
|
||||||
|
html.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('update texttrack buttons on removetrack or addtrack', function(assert) {
|
QUnit.test('update texttrack buttons on removetrack or addtrack', function(assert) {
|
||||||
@ -278,6 +281,8 @@ if (Html5.supportsNativeTextTracks()) {
|
|||||||
emulatedTt.on('removetrack', function() {
|
emulatedTt.on('removetrack', function() {
|
||||||
assert.equal(emulatedTt.length, tt.length, 'we have matching tracks length');
|
assert.equal(emulatedTt.length, tt.length, 'we have matching tracks length');
|
||||||
assert.equal(emulatedTt.length, 0, 'we have no more text tracks');
|
assert.equal(emulatedTt.length, 0, 'we have no more text tracks');
|
||||||
|
|
||||||
|
html.dispose();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -319,6 +324,8 @@ QUnit.test('should check for text track changes when emulating text tracks', fun
|
|||||||
});
|
});
|
||||||
tech.emulateTextTracks();
|
tech.emulateTextTracks();
|
||||||
assert.equal(numTextTrackChanges, 1, 'we got a texttrackchange event');
|
assert.equal(numTextTrackChanges, 1, 'we got a texttrackchange event');
|
||||||
|
|
||||||
|
tech.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('removes cuechange event when text track is hidden for emulated tracks', function(assert) {
|
QUnit.test('removes cuechange event when text track is hidden for emulated tracks', function(assert) {
|
||||||
|
@ -33,6 +33,7 @@ QUnit.test('listen to remove and add track events in native video tracks', funct
|
|||||||
|
|
||||||
Html5.prototype.videoTracks = function() {
|
Html5.prototype.videoTracks = function() {
|
||||||
return {
|
return {
|
||||||
|
removeEventListener() {},
|
||||||
addEventListener(type, handler) {
|
addEventListener(type, handler) {
|
||||||
events[type] = true;
|
events[type] = true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user