2016-08-04 17:49:32 +02:00
|
|
|
/* eslint-env qunit */
|
2015-10-28 19:28:15 +02:00
|
|
|
import CloseButton from '../../src/js/close-button';
|
2016-08-04 17:49:32 +02:00
|
|
|
import sinon from 'sinon';
|
2015-10-28 19:28:15 +02:00
|
|
|
import ModalDialog from '../../src/js/modal-dialog';
|
|
|
|
import * as Dom from '../../src/js/utils/dom';
|
|
|
|
import TestHelpers from './test-helpers';
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const ESC = 27;
|
2015-10-28 19:28:15 +02:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.module('ModalDialog', {
|
2015-10-28 19:28:15 +02:00
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
beforeEach() {
|
2015-10-28 19:28:15 +02:00
|
|
|
this.player = TestHelpers.makePlayer();
|
|
|
|
this.modal = new ModalDialog(this.player, {temporary: false});
|
|
|
|
this.el = this.modal.el();
|
|
|
|
},
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
afterEach() {
|
2015-10-28 19:28:15 +02:00
|
|
|
this.player.dispose();
|
|
|
|
this.modal.dispose();
|
|
|
|
this.el = null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('should create the expected element', function(assert) {
|
|
|
|
const elAssertions = TestHelpers.assertEl(assert, this.el, {
|
2015-10-28 19:28:15 +02:00
|
|
|
tagName: 'div',
|
|
|
|
classes: [
|
|
|
|
'vjs-modal-dialog',
|
|
|
|
'vjs-hidden'
|
|
|
|
],
|
|
|
|
attrs: {
|
|
|
|
'aria-describedby': this.modal.descEl_.id,
|
|
|
|
'aria-hidden': 'true',
|
|
|
|
'aria-label': this.modal.label(),
|
|
|
|
'role': 'dialog'
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
tabIndex: -1
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.expect(elAssertions.count);
|
|
|
|
elAssertions();
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('should create the expected description element', function(assert) {
|
|
|
|
const elAssertions = TestHelpers.assertEl(assert, this.modal.descEl_, {
|
2015-10-28 19:28:15 +02:00
|
|
|
tagName: 'p',
|
|
|
|
innerHTML: this.modal.description(),
|
|
|
|
classes: [
|
|
|
|
'vjs-modal-dialog-description',
|
|
|
|
'vjs-offscreen'
|
|
|
|
],
|
|
|
|
attrs: {
|
|
|
|
id: this.el.getAttribute('aria-describedby')
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.expect(elAssertions.count);
|
|
|
|
elAssertions();
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('should create the expected contentEl', function(assert) {
|
|
|
|
const elAssertions = TestHelpers.assertEl(assert, this.modal.contentEl(), {
|
2015-10-28 19:28:15 +02:00
|
|
|
tagName: 'div',
|
|
|
|
classes: [
|
|
|
|
'vjs-modal-dialog-content'
|
|
|
|
],
|
|
|
|
props: {
|
|
|
|
parentNode: this.el
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.expect(elAssertions.count);
|
|
|
|
elAssertions();
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('should create a close button by default', function(assert) {
|
|
|
|
const btn = this.modal.getChild('closeButton');
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
// We only check the aspects of the button that relate to the modal. Other
|
|
|
|
// aspects of the button (classes, etc) are tested in their appropriate test
|
|
|
|
// module.
|
|
|
|
assert.expect(2);
|
|
|
|
assert.ok(btn instanceof CloseButton, 'close button is a CloseButton');
|
|
|
|
assert.strictEqual(btn.el().parentNode, this.el, 'close button is a child of el');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('returns `this` for expected methods', function(assert) {
|
|
|
|
const methods = ['close', 'empty', 'fill', 'fillWith', 'open'];
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
assert.expect(methods.length);
|
|
|
|
methods.forEach(function(method) {
|
|
|
|
assert.strictEqual(this[method](), this, '`' + method + '()` returns `this`');
|
|
|
|
}, this.modal);
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('open() triggers events', function(assert) {
|
|
|
|
const modal = this.modal;
|
|
|
|
const beforeModalOpenSpy = sinon.spy(function() {
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.notOk(modal.opened(), 'modal is not opened before opening event');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const modalOpenSpy = sinon.spy(function() {
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.ok(modal.opened(), 'modal is opened on opening event');
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.expect(4);
|
|
|
|
|
|
|
|
modal.
|
|
|
|
on('beforemodalopen', beforeModalOpenSpy).
|
|
|
|
on('modalopen', modalOpenSpy).
|
|
|
|
open();
|
|
|
|
|
|
|
|
assert.strictEqual(beforeModalOpenSpy.callCount, 1, 'beforemodalopen spy was called');
|
|
|
|
assert.strictEqual(modalOpenSpy.callCount, 1, 'modalopen spy was called');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('open() removes "vjs-hidden" class', function(assert) {
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.expect(2);
|
|
|
|
assert.ok(this.modal.hasClass('vjs-hidden'), 'modal starts hidden');
|
|
|
|
this.modal.open();
|
|
|
|
assert.notOk(this.modal.hasClass('vjs-hidden'), 'modal is not hidden after opening');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('open() cannot be called on an opened modal', function(assert) {
|
|
|
|
const spy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
this.modal.on('modalopen', spy).open().open();
|
|
|
|
|
|
|
|
assert.expect(1);
|
|
|
|
assert.strictEqual(spy.callCount, 1, 'modal was only opened once');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('close() triggers events', function(assert) {
|
|
|
|
const modal = this.modal;
|
|
|
|
const beforeModalCloseSpy = sinon.spy(function() {
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.ok(modal.opened(), 'modal is not closed before closing event');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const modalCloseSpy = sinon.spy(function() {
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.notOk(modal.opened(), 'modal is closed on closing event');
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.expect(4);
|
|
|
|
|
|
|
|
modal.
|
|
|
|
on('beforemodalclose', beforeModalCloseSpy).
|
|
|
|
on('modalclose', modalCloseSpy).
|
|
|
|
open().
|
|
|
|
close();
|
|
|
|
|
|
|
|
assert.strictEqual(beforeModalCloseSpy.callCount, 1, 'beforemodalclose spy was called');
|
|
|
|
assert.strictEqual(modalCloseSpy.callCount, 1, 'modalclose spy was called');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('close() adds the "vjs-hidden" class', function(assert) {
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.expect(1);
|
|
|
|
this.modal.open().close();
|
|
|
|
assert.ok(this.modal.hasClass('vjs-hidden'), 'modal is hidden upon close');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('pressing ESC triggers close(), but only when the modal is opened', function(assert) {
|
|
|
|
const spy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
this.modal.on('modalclose', spy).handleKeyPress({which: ESC});
|
|
|
|
assert.expect(2);
|
|
|
|
assert.strictEqual(spy.callCount, 0, 'ESC did not close the closed modal');
|
|
|
|
|
|
|
|
this.modal.open().handleKeyPress({which: ESC});
|
|
|
|
assert.strictEqual(spy.callCount, 1, 'ESC closed the now-opened modal');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('close() cannot be called on a closed modal', function(assert) {
|
|
|
|
const spy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
this.modal.on('modalclose', spy);
|
|
|
|
this.modal.open().close().close();
|
|
|
|
|
|
|
|
assert.expect(1);
|
|
|
|
assert.strictEqual(spy.callCount, 1, 'modal was only closed once');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('open() pauses playback, close() resumes', function(assert) {
|
|
|
|
const playSpy = sinon.spy();
|
|
|
|
const pauseSpy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
// Quick and dirty; make it looks like the player is playing.
|
|
|
|
this.player.paused = function() {
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.player.play = function() {
|
|
|
|
playSpy();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.player.pause = function() {
|
|
|
|
pauseSpy();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.modal.open();
|
|
|
|
|
|
|
|
assert.expect(2);
|
|
|
|
assert.strictEqual(pauseSpy.callCount, 1, 'player is paused when the modal opens');
|
|
|
|
|
|
|
|
this.modal.close();
|
|
|
|
assert.strictEqual(playSpy.callCount, 1, 'player is resumed when the modal closes');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('open() hides controls, close() shows controls', function(assert) {
|
2015-10-28 19:28:15 +02:00
|
|
|
this.modal.open();
|
|
|
|
|
|
|
|
assert.expect(2);
|
|
|
|
assert.notOk(this.player.controls_, 'controls are hidden');
|
|
|
|
|
|
|
|
this.modal.close();
|
|
|
|
assert.ok(this.player.controls_, 'controls are no longer hidden');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('opened()', function(assert) {
|
|
|
|
const openSpy = sinon.spy();
|
|
|
|
const closeSpy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
assert.expect(4);
|
|
|
|
assert.strictEqual(this.modal.opened(), false, 'the modal is closed');
|
|
|
|
this.modal.open();
|
|
|
|
assert.strictEqual(this.modal.opened(), true, 'the modal is open');
|
|
|
|
|
|
|
|
this.modal.
|
|
|
|
close().
|
|
|
|
on('modalopen', openSpy).
|
|
|
|
on('modalclose', closeSpy).
|
|
|
|
opened(true);
|
|
|
|
|
|
|
|
this.modal.opened(true);
|
|
|
|
this.modal.opened(false);
|
|
|
|
assert.strictEqual(openSpy.callCount, 1, 'modal was opened only once');
|
|
|
|
assert.strictEqual(closeSpy.callCount, 1, 'modal was closed only once');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('content()', function(assert) {
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.expect(3);
|
|
|
|
assert.strictEqual(typeof this.modal.content(), 'undefined', 'no content by default');
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const content = this.modal.content(Dom.createEl());
|
|
|
|
|
2015-10-28 19:28:15 +02:00
|
|
|
assert.ok(Dom.isEl(content), 'content was set from a single DOM element');
|
|
|
|
|
|
|
|
assert.strictEqual(this.modal.content(null), null, 'content was nullified');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('fillWith()', function(assert) {
|
|
|
|
const contentEl = this.modal.contentEl();
|
|
|
|
const children = [Dom.createEl(), Dom.createEl(), Dom.createEl()];
|
|
|
|
const beforeFillSpy = sinon.spy();
|
|
|
|
const fillSpy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
children.forEach(function(el) {
|
|
|
|
contentEl.appendChild(el);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.modal.
|
|
|
|
on('beforemodalfill', beforeFillSpy).
|
|
|
|
on('modalfill', fillSpy).
|
|
|
|
fillWith(children);
|
|
|
|
|
|
|
|
assert.expect(5 + children.length);
|
|
|
|
assert.strictEqual(contentEl.children.length, children.length, 'has the right number of children');
|
|
|
|
|
|
|
|
children.forEach(function(el) {
|
|
|
|
assert.strictEqual(el.parentNode, contentEl, 'new child appended');
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.strictEqual(beforeFillSpy.callCount, 1, 'the "beforemodalfill" callback was called');
|
|
|
|
assert.strictEqual(beforeFillSpy.getCall(0).thisValue, this.modal, 'the value of "this" is the modal');
|
|
|
|
assert.strictEqual(fillSpy.callCount, 1, 'the "modalfill" callback was called');
|
|
|
|
assert.strictEqual(fillSpy.getCall(0).thisValue, this.modal, 'the value of "this" is the modal');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('empty()', function(assert) {
|
|
|
|
const beforeEmptySpy = sinon.spy();
|
|
|
|
const emptySpy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
this.modal.
|
|
|
|
fillWith([Dom.createEl(), Dom.createEl()]).
|
|
|
|
on('beforemodalempty', beforeEmptySpy).
|
|
|
|
on('modalempty', emptySpy).
|
|
|
|
empty();
|
|
|
|
|
|
|
|
assert.expect(5);
|
|
|
|
assert.strictEqual(this.modal.contentEl().children.length, 0, 'removed all `contentEl()` children');
|
|
|
|
assert.strictEqual(beforeEmptySpy.callCount, 1, 'the "beforemodalempty" callback was called');
|
|
|
|
assert.strictEqual(beforeEmptySpy.getCall(0).thisValue, this.modal, 'the value of "this" is the modal');
|
|
|
|
assert.strictEqual(emptySpy.callCount, 1, 'the "modalempty" callback was called');
|
|
|
|
assert.strictEqual(emptySpy.getCall(0).thisValue, this.modal, 'the value of "this" is the modal');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('closeable()', function(assert) {
|
|
|
|
const initialCloseButton = this.modal.getChild('closeButton');
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
assert.expect(8);
|
|
|
|
assert.strictEqual(this.modal.closeable(), true, 'the modal is closed');
|
|
|
|
|
|
|
|
this.modal.open().closeable(false);
|
|
|
|
assert.notOk(this.modal.getChild('closeButton'), 'the close button is no longer a child of the modal');
|
|
|
|
assert.notOk(initialCloseButton.el(), 'the initial close button was disposed');
|
|
|
|
|
|
|
|
this.modal.handleKeyPress({which: ESC});
|
|
|
|
assert.ok(this.modal.opened(), 'the modal was not closed by the ESC key');
|
|
|
|
|
|
|
|
this.modal.close();
|
|
|
|
assert.notOk(this.modal.opened(), 'the modal was closed programmatically');
|
|
|
|
|
|
|
|
this.modal.open().closeable(true);
|
|
|
|
assert.ok(this.modal.getChild('closeButton'), 'a new close button was created');
|
|
|
|
|
|
|
|
this.modal.getChild('closeButton').trigger('click');
|
|
|
|
assert.notOk(this.modal.opened(), 'the modal was closed by the new close button');
|
|
|
|
|
|
|
|
this.modal.open().handleKeyPress({which: ESC});
|
|
|
|
assert.notOk(this.modal.opened(), 'the modal was closed by the ESC key');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('"content" option (fills on first open() invocation)', function(assert) {
|
|
|
|
const modal = new ModalDialog(this.player, {
|
2015-10-28 19:28:15 +02:00
|
|
|
content: Dom.createEl(),
|
|
|
|
temporary: false
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const spy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
modal.on('modalfill', spy);
|
|
|
|
modal.open().close().open();
|
|
|
|
|
|
|
|
assert.expect(3);
|
|
|
|
assert.strictEqual(modal.content(), modal.options_.content, 'has the expected content');
|
|
|
|
assert.strictEqual(spy.callCount, 1, 'auto-fills only once');
|
|
|
|
assert.strictEqual(modal.contentEl().firstChild, modal.options_.content, 'has the expected content in the DOM');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('"temporary" option', function(assert) {
|
|
|
|
const temp = new ModalDialog(this.player, {temporary: true});
|
|
|
|
const tempSpy = sinon.spy();
|
|
|
|
const perm = new ModalDialog(this.player, {temporary: false});
|
|
|
|
const permSpy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
temp.on('dispose', tempSpy);
|
|
|
|
perm.on('dispose', permSpy);
|
|
|
|
temp.open().close();
|
|
|
|
perm.open().close();
|
|
|
|
|
|
|
|
assert.expect(2);
|
|
|
|
assert.strictEqual(tempSpy.callCount, 1, 'temporary modals are disposed');
|
|
|
|
assert.strictEqual(permSpy.callCount, 0, 'permanent modals are not disposed');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('"fillAlways" option', function(assert) {
|
|
|
|
const modal = new ModalDialog(this.player, {
|
2015-10-28 19:28:15 +02:00
|
|
|
content: 'foo',
|
|
|
|
fillAlways: true,
|
|
|
|
temporary: false
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const spy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
modal.on('modalfill', spy);
|
|
|
|
modal.open().close().open();
|
|
|
|
|
|
|
|
assert.expect(1);
|
|
|
|
assert.strictEqual(spy.callCount, 2, 'the modal was filled on each open call');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('"label" option', function(assert) {
|
|
|
|
const label = 'foo';
|
|
|
|
const modal = new ModalDialog(this.player, {label});
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
assert.expect(1);
|
|
|
|
assert.strictEqual(modal.el().getAttribute('aria-label'), label, 'uses the label as the aria-label');
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
QUnit.test('"uncloseable" option', function(assert) {
|
|
|
|
const modal = new ModalDialog(this.player, {
|
2015-10-28 19:28:15 +02:00
|
|
|
temporary: false,
|
|
|
|
uncloseable: true
|
|
|
|
});
|
|
|
|
|
2016-08-04 17:49:32 +02:00
|
|
|
const spy = sinon.spy();
|
2015-10-28 19:28:15 +02:00
|
|
|
|
|
|
|
modal.on('modalclose', spy);
|
|
|
|
|
|
|
|
assert.expect(3);
|
|
|
|
assert.strictEqual(modal.closeable(), false, 'the modal is uncloseable');
|
|
|
|
assert.notOk(modal.getChild('closeButton'), 'the close button is not present');
|
|
|
|
|
|
|
|
modal.open().handleKeyPress({which: ESC});
|
|
|
|
assert.strictEqual(spy.callCount, 0, 'ESC did not close the modal');
|
|
|
|
});
|