2016-08-03 21:27:03 +02:00
|
|
|
/* eslint-env qunit */
|
2015-05-04 01:12:38 +02:00
|
|
|
import Flash from '../../../src/js/tech/flash.js';
|
2015-07-21 23:12:24 +02:00
|
|
|
import { createTimeRange } from '../../../src/js/utils/time-ranges.js';
|
2015-03-26 06:43:41 +02:00
|
|
|
import document from 'global/document';
|
2016-08-03 21:27:03 +02:00
|
|
|
import sinon from 'sinon';
|
2013-08-24 01:05:04 +03:00
|
|
|
|
2016-08-03 21:27:03 +02:00
|
|
|
// fake out the <object> interaction but leave all the other logic intact
|
|
|
|
class MockFlash extends Flash {
|
|
|
|
constructor() {
|
|
|
|
super({});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QUnit.module('Flash');
|
2013-08-24 01:05:04 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('Flash.canPlaySource', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const canPlaySource = Flash.canPlaySource;
|
2013-10-29 21:00:54 +03:00
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
// Supported
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(canPlaySource({type: 'video/mp4; codecs=avc1.42E01E,mp4a.40.2' }, {}),
|
2016-08-03 21:27:03 +02:00
|
|
|
'codecs supported');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(canPlaySource({type: 'video/mp4' }, {}), 'video/mp4 supported');
|
|
|
|
assert.ok(canPlaySource({type: 'video/x-flv' }, {}), 'video/x-flv supported');
|
|
|
|
assert.ok(canPlaySource({type: 'video/flv' }, {}), 'video/flv supported');
|
|
|
|
assert.ok(canPlaySource({type: 'video/m4v' }, {}), 'video/m4v supported');
|
|
|
|
assert.ok(canPlaySource({type: 'VIDEO/FLV' }, {}), 'capitalized mime type');
|
2013-10-29 21:00:54 +03:00
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
// Not supported
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!canPlaySource({ type: 'video/webm; codecs="vp8, vorbis"' }, {}));
|
|
|
|
assert.ok(!canPlaySource({ type: 'video/webm' }, {}));
|
2013-10-29 21:00:54 +03:00
|
|
|
});
|
2014-01-24 02:13:22 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('currentTime', function(assert) {
|
2016-11-05 00:03:44 +02:00
|
|
|
const mockFlash = new MockFlash();
|
2015-07-21 23:31:51 +02:00
|
|
|
let seekingCount = 0;
|
2015-06-08 22:42:39 +02:00
|
|
|
let seeking = false;
|
|
|
|
let setPropVal;
|
|
|
|
let getPropVal;
|
|
|
|
let result;
|
|
|
|
|
|
|
|
// Mock out a Flash instance to avoid creating the swf object
|
2016-11-05 00:03:44 +02:00
|
|
|
mockFlash.el_ = {
|
|
|
|
/* eslint-disable camelcase */
|
|
|
|
vjs_setProperty(prop, val) {
|
|
|
|
setPropVal = val;
|
2015-06-08 22:42:39 +02:00
|
|
|
},
|
2016-11-05 00:03:44 +02:00
|
|
|
vjs_getProperty() {
|
|
|
|
return getPropVal;
|
|
|
|
}
|
|
|
|
/* eslint-enable camelcase */
|
|
|
|
};
|
|
|
|
mockFlash.seekable = function() {
|
|
|
|
return createTimeRange(5, 1000);
|
|
|
|
};
|
|
|
|
mockFlash.trigger = function(event) {
|
|
|
|
if (event === 'seeking') {
|
|
|
|
seekingCount++;
|
2014-01-24 02:13:22 +03:00
|
|
|
}
|
|
|
|
};
|
2016-11-05 00:03:44 +02:00
|
|
|
mockFlash.seeking = function() {
|
|
|
|
return seeking;
|
|
|
|
};
|
2014-01-24 02:13:22 +03:00
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
// Test the currentTime getter
|
|
|
|
getPropVal = 3;
|
2016-11-05 00:03:44 +02:00
|
|
|
result = mockFlash.currentTime();
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(result, 3, 'currentTime is retreived from the swf element');
|
2015-06-08 22:42:39 +02:00
|
|
|
|
|
|
|
// Test the currentTime setter
|
2016-11-05 00:03:44 +02:00
|
|
|
mockFlash.setCurrentTime(10);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(setPropVal, 10, 'currentTime is set on the swf element');
|
|
|
|
assert.equal(seekingCount, 1, 'triggered seeking');
|
2014-01-24 02:13:22 +03:00
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
// Test current time while seeking
|
2016-11-05 00:03:44 +02:00
|
|
|
mockFlash.setCurrentTime(20);
|
2014-01-24 02:13:22 +03:00
|
|
|
seeking = true;
|
2016-11-05 00:03:44 +02:00
|
|
|
result = mockFlash.currentTime();
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(result,
|
2016-08-03 21:27:03 +02:00
|
|
|
20,
|
|
|
|
'currentTime is retrieved from the lastSeekTarget while seeking');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.notEqual(result,
|
2016-08-03 21:27:03 +02:00
|
|
|
getPropVal,
|
|
|
|
'currentTime is not retrieved from the element while seeking');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(seekingCount, 2, 'triggered seeking');
|
2015-07-21 23:12:24 +02:00
|
|
|
|
|
|
|
// clamp seeks to seekable
|
2016-11-05 00:03:44 +02:00
|
|
|
mockFlash.setCurrentTime(1001);
|
|
|
|
result = mockFlash.currentTime();
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(result, mockFlash.seekable().end(0), 'clamped to the seekable end');
|
|
|
|
assert.equal(seekingCount, 3, 'triggered seeking');
|
2015-07-21 23:12:24 +02:00
|
|
|
|
2016-11-05 00:03:44 +02:00
|
|
|
mockFlash.setCurrentTime(1);
|
|
|
|
result = mockFlash.currentTime();
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(result, mockFlash.seekable().start(0), 'clamped to the seekable start');
|
|
|
|
assert.equal(seekingCount, 4, 'triggered seeking');
|
2014-01-24 02:13:22 +03:00
|
|
|
});
|
2014-07-17 00:01:01 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('dispose removes the object element even before ready fires', function(assert) {
|
2015-06-08 22:42:39 +02:00
|
|
|
// This test appears to test bad functionaly that was fixed
|
|
|
|
// so it's debateable whether or not it's useful
|
2016-08-03 21:27:03 +02:00
|
|
|
const dispose = Flash.prototype.dispose;
|
|
|
|
const mockFlash = new MockFlash();
|
|
|
|
const noop = function() {};
|
2015-06-08 22:42:39 +02:00
|
|
|
|
|
|
|
// Mock required functions for dispose
|
|
|
|
mockFlash.off = noop;
|
|
|
|
mockFlash.trigger = noop;
|
|
|
|
mockFlash.el_ = {};
|
|
|
|
|
|
|
|
dispose.call(mockFlash);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.strictEqual(mockFlash.el_, null, 'swf el is nulled');
|
2014-07-09 23:08:47 +03:00
|
|
|
});
|
2014-07-29 03:27:29 +03:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('ready triggering before and after disposing the tech', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const checkReady = sinon.stub(Flash, 'checkReady');
|
|
|
|
const fixtureDiv = document.getElementById('qunit-fixture');
|
|
|
|
const playerDiv = document.createElement('div');
|
|
|
|
const techEl = document.createElement('div');
|
2014-07-17 00:01:01 +03:00
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
techEl.id = 'foo1234';
|
2014-07-17 00:01:01 +03:00
|
|
|
playerDiv.appendChild(techEl);
|
|
|
|
fixtureDiv.appendChild(playerDiv);
|
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
// Mock the swf element
|
2015-05-06 20:01:52 +02:00
|
|
|
techEl.tech = {
|
2016-08-03 21:27:03 +02:00
|
|
|
el() {
|
2015-06-08 22:42:39 +02:00
|
|
|
return techEl;
|
|
|
|
}
|
2015-05-06 20:01:52 +02:00
|
|
|
};
|
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
playerDiv.player = {
|
2015-05-06 20:01:52 +02:00
|
|
|
tech: techEl.tech
|
2014-07-17 00:01:01 +03:00
|
|
|
};
|
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
Flash.onReady(techEl.id);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(checkReady.called, 'checkReady should be called before the tech is disposed');
|
2014-07-17 00:01:01 +03:00
|
|
|
|
|
|
|
// remove the tech el from the player div to simulate being disposed
|
|
|
|
playerDiv.removeChild(techEl);
|
2015-06-08 22:42:39 +02:00
|
|
|
Flash.onReady(techEl.id);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!checkReady.calledTwice,
|
2016-08-03 21:27:03 +02:00
|
|
|
'checkReady should not be called after the tech is disposed');
|
2014-07-17 00:01:01 +03:00
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
Flash.checkReady.restore();
|
2014-07-17 00:01:01 +03:00
|
|
|
});
|
2014-12-03 00:22:34 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('should have the source handler interface', function(assert) {
|
|
|
|
assert.ok(Flash.registerSourceHandler, 'has the registerSourceHandler function');
|
2014-12-03 00:22:34 +02:00
|
|
|
});
|
2015-03-24 20:52:04 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('canPlayType should select the correct types to play', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const canPlayType = Flash.nativeSourceHandler.canPlayType;
|
2015-10-27 19:46:05 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(canPlayType('video/flv'), 'maybe', 'should be able to play FLV files');
|
|
|
|
assert.equal(canPlayType('video/x-flv'), 'maybe', 'should be able to play x-FLV files');
|
|
|
|
assert.equal(canPlayType('video/mp4'), 'maybe', 'should be able to play MP4 files');
|
|
|
|
assert.equal(canPlayType('video/m4v'), 'maybe', 'should be able to play M4V files');
|
|
|
|
assert.equal(canPlayType('video/ogg'),
|
2016-08-03 21:27:03 +02:00
|
|
|
'',
|
|
|
|
'should return empty string if it can not play the video');
|
2015-10-27 19:46:05 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('canHandleSource should be able to work with src objects without a type', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const canHandleSource = Flash.nativeSourceHandler.canHandleSource;
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal('maybe',
|
2016-08-03 21:27:03 +02:00
|
|
|
canHandleSource({ src: 'test.video.mp4' }, {}),
|
|
|
|
'should guess that it is a mp4 video');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal('maybe',
|
2016-08-03 21:27:03 +02:00
|
|
|
canHandleSource({ src: 'test.video.m4v' }, {}),
|
|
|
|
'should guess that it is a m4v video');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal('maybe',
|
2016-08-03 21:27:03 +02:00
|
|
|
canHandleSource({ src: 'test.video.flv' }, {}),
|
|
|
|
'should guess that it is a flash video');
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal('',
|
2016-08-03 21:27:03 +02:00
|
|
|
canHandleSource({ src: 'test.video.wgg' }, {}),
|
|
|
|
'should return empty string if it can not play the video');
|
2015-06-08 22:47:04 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('seekable', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const seekable = Flash.prototype.seekable;
|
2015-06-08 22:42:39 +02:00
|
|
|
let result;
|
2016-08-03 21:27:03 +02:00
|
|
|
const mockFlash = {
|
|
|
|
duration() {
|
2015-06-08 22:42:39 +02:00
|
|
|
return this.duration_;
|
2015-06-08 22:47:04 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-08 22:42:39 +02:00
|
|
|
// Test a normal duration
|
|
|
|
mockFlash.duration_ = 23;
|
|
|
|
result = seekable.call(mockFlash);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(result.length, 1, 'seekable is non-empty');
|
|
|
|
assert.equal(result.start(0), 0, 'starts at zero');
|
|
|
|
assert.equal(result.end(0), mockFlash.duration_, 'ends at the duration');
|
2015-06-08 22:42:39 +02:00
|
|
|
|
|
|
|
// Test a zero duration
|
|
|
|
mockFlash.duration_ = 0;
|
|
|
|
result = seekable.call(mockFlash);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(result.length, mockFlash.duration_,
|
2016-08-03 21:27:03 +02:00
|
|
|
'seekable is empty with a zero duration');
|
2015-06-08 22:47:04 +02:00
|
|
|
});
|
2015-07-21 23:12:24 +02:00
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('play after ended seeks to the beginning', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
let plays = 0;
|
|
|
|
const seeks = [];
|
2015-08-31 20:12:12 +02:00
|
|
|
|
|
|
|
Flash.prototype.play.call({
|
|
|
|
el_: {
|
2016-08-03 21:27:03 +02:00
|
|
|
/* eslint-disable camelcase */
|
2015-08-31 20:12:12 +02:00
|
|
|
vjs_play() {
|
|
|
|
plays++;
|
|
|
|
}
|
2016-08-03 21:27:03 +02:00
|
|
|
/* eslint-enable camelcase */
|
2015-08-31 20:12:12 +02:00
|
|
|
},
|
|
|
|
ended() {
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
setCurrentTime(time) {
|
|
|
|
seeks.push(time);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(plays, 1, 'called play on the SWF');
|
|
|
|
assert.equal(seeks.length, 1, 'seeked on play');
|
|
|
|
assert.equal(seeks[0], 0, 'seeked to the beginning');
|
2015-08-31 20:12:12 +02:00
|
|
|
});
|
|
|
|
|
2016-08-12 19:51:31 +02:00
|
|
|
QUnit.test('duration returns NaN, Infinity or duration according to the HTML standard', function(assert) {
|
2016-08-03 21:27:03 +02:00
|
|
|
const duration = Flash.prototype.duration;
|
2016-07-18 20:10:57 +02:00
|
|
|
let mockedDuration = -1;
|
|
|
|
let mockedReadyState = 0;
|
|
|
|
let result;
|
2016-08-03 21:27:03 +02:00
|
|
|
const mockFlash = {
|
2016-07-18 20:10:57 +02:00
|
|
|
el_: {
|
2016-08-03 21:27:03 +02:00
|
|
|
/* eslint-disable camelcase */
|
2016-07-18 20:10:57 +02:00
|
|
|
vjs_getProperty() {
|
|
|
|
return mockedDuration;
|
|
|
|
}
|
2016-08-03 21:27:03 +02:00
|
|
|
/* eslint-enable camelcase */
|
2016-07-18 20:10:57 +02:00
|
|
|
},
|
2016-08-03 21:27:03 +02:00
|
|
|
readyState() {
|
2016-07-18 20:10:57 +02:00
|
|
|
return mockedReadyState;
|
|
|
|
}
|
|
|
|
};
|
2016-08-03 21:27:03 +02:00
|
|
|
|
2016-07-18 20:10:57 +02:00
|
|
|
result = duration.call(mockFlash);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(Number.isNaN(result), 'duration returns NaN when readyState equals 0');
|
2016-07-18 20:10:57 +02:00
|
|
|
|
|
|
|
mockedReadyState = 1;
|
|
|
|
result = duration.call(mockFlash);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.ok(!Number.isFinite(result),
|
2016-08-03 21:27:03 +02:00
|
|
|
'duration returns Infinity when duration property is less then 0');
|
2016-07-18 20:10:57 +02:00
|
|
|
|
|
|
|
mockedDuration = 1;
|
|
|
|
result = duration.call(mockFlash);
|
2016-08-12 19:51:31 +02:00
|
|
|
assert.equal(result,
|
2016-08-03 21:27:03 +02:00
|
|
|
1,
|
|
|
|
'duration returns duration property when readyState' +
|
|
|
|
' and duration property are both higher than 0');
|
2016-07-18 20:10:57 +02:00
|
|
|
});
|