UNPKG

10.8 kBJavaScriptView Raw
1import Flash from '../src/plugin';
2import {createTimeRange} from 'video.js';
3import document from 'global/document';
4import window from 'global/window';
5import sinon from 'sinon';
6import QUnit from 'qunit';
7
8// fake out the <object> interaction but leave all the other logic intact
9class MockFlash extends Flash {
10 constructor() {
11 super({});
12 }
13}
14
15QUnit.module('Flash');
16
17QUnit.test('Flash.canPlaySource', function(assert) {
18 const canPlaySource = Flash.canPlaySource;
19
20 // Supported
21 assert.ok(canPlaySource({type: 'video/mp4; codecs=avc1.42E01E,mp4a.40.2' }, {}),
22 'codecs supported');
23 assert.ok(canPlaySource({type: 'video/mp4' }, {}), 'video/mp4 supported');
24 assert.ok(canPlaySource({type: 'video/x-flv' }, {}), 'video/x-flv supported');
25 assert.ok(canPlaySource({type: 'video/flv' }, {}), 'video/flv supported');
26 assert.ok(canPlaySource({type: 'video/m4v' }, {}), 'video/m4v supported');
27 assert.ok(canPlaySource({type: 'VIDEO/FLV' }, {}), 'capitalized mime type');
28
29 // Not supported
30 assert.ok(!canPlaySource({ type: 'video/webm; codecs="vp8, vorbis"' }, {}));
31 assert.ok(!canPlaySource({ type: 'video/webm' }, {}));
32});
33
34QUnit.test('currentTime', function(assert) {
35 const getCurrentTime = Flash.prototype.currentTime;
36 const setCurrentTime = Flash.prototype.setCurrentTime;
37 let seekingCount = 0;
38 let seeking = false;
39 let setPropVal;
40 let getPropVal;
41 let result;
42
43 // Mock out a Flash instance to avoid creating the swf object
44 const mockFlash = {
45 el_: {
46 /* eslint-disable camelcase */
47 vjs_setProperty(prop, val) {
48 setPropVal = val;
49 },
50 vjs_getProperty() {
51 return getPropVal;
52 }
53 /* eslint-enable camelcase */
54 },
55 seekable() {
56 return createTimeRange(5, 1000);
57 },
58 trigger(event) {
59 if (event === 'seeking') {
60 seekingCount++;
61 }
62 },
63 seeking() {
64 return seeking;
65 }
66 };
67
68 // Test the currentTime getter
69 getPropVal = 3;
70 result = getCurrentTime.call(mockFlash);
71 assert.equal(result, 3, 'currentTime is retreived from the swf element');
72
73 // Test the currentTime setter
74 setCurrentTime.call(mockFlash, 10);
75 assert.equal(setPropVal, 10, 'currentTime is set on the swf element');
76 assert.equal(seekingCount, 1, 'triggered seeking');
77
78 // Test current time while seeking
79 setCurrentTime.call(mockFlash, 20);
80 seeking = true;
81 result = getCurrentTime.call(mockFlash);
82 assert.equal(result,
83 20,
84 'currentTime is retrieved from the lastSeekTarget while seeking');
85 assert.notEqual(result,
86 getPropVal,
87 'currentTime is not retrieved from the element while seeking');
88 assert.equal(seekingCount, 2, 'triggered seeking');
89
90 // clamp seeks to seekable
91 setCurrentTime.call(mockFlash, 1001);
92 result = getCurrentTime.call(mockFlash);
93 assert.equal(result, mockFlash.seekable().end(0), 'clamped to the seekable end');
94 assert.equal(seekingCount, 3, 'triggered seeking');
95
96 setCurrentTime.call(mockFlash, 1);
97 result = getCurrentTime.call(mockFlash);
98 assert.equal(result, mockFlash.seekable().start(0), 'clamped to the seekable start');
99 assert.equal(seekingCount, 4, 'triggered seeking');
100});
101
102QUnit.test('dispose removes the object element even before ready fires', function(assert) {
103 // This test appears to test bad functionaly that was fixed
104 // so it's debateable whether or not it's useful
105 const dispose = Flash.prototype.dispose;
106 const mockFlash = new MockFlash();
107 const noop = function() {};
108
109 // Mock required functions for dispose
110 mockFlash.off = noop;
111 mockFlash.trigger = noop;
112 mockFlash.el_ = {};
113
114 dispose.call(mockFlash);
115 assert.strictEqual(mockFlash.el_, null, 'swf el is nulled');
116});
117
118QUnit.test('ready triggering before and after disposing the tech', function(assert) {
119 const checkReady = sinon.stub(Flash, 'checkReady');
120 const fixtureDiv = document.getElementById('qunit-fixture');
121 const playerDiv = document.createElement('div');
122 const techEl = document.createElement('div');
123
124 techEl.id = 'foo1234';
125 playerDiv.appendChild(techEl);
126 fixtureDiv.appendChild(playerDiv);
127
128 // Mock the swf element
129 techEl.tech = {
130 el() {
131 return techEl;
132 }
133 };
134
135 playerDiv.player = {
136 tech: techEl.tech
137 };
138
139 Flash.onReady(techEl.id);
140 assert.ok(checkReady.called, 'checkReady should be called before the tech is disposed');
141
142 // remove the tech el from the player div to simulate being disposed
143 playerDiv.removeChild(techEl);
144 Flash.onReady(techEl.id);
145 assert.ok(!checkReady.calledTwice,
146 'checkReady should not be called after the tech is disposed');
147
148 Flash.checkReady.restore();
149});
150
151QUnit.test('should have the source handler interface', function(assert) {
152 assert.ok(Flash.registerSourceHandler, 'has the registerSourceHandler function');
153});
154
155QUnit.test('canPlayType should select the correct types to play', function(assert) {
156 const canPlayType = Flash.nativeSourceHandler.canPlayType;
157
158 assert.equal(canPlayType('video/flv'), 'maybe', 'should be able to play FLV files');
159 assert.equal(canPlayType('video/x-flv'), 'maybe', 'should be able to play x-FLV files');
160 assert.equal(canPlayType('video/mp4'), 'maybe', 'should be able to play MP4 files');
161 assert.equal(canPlayType('video/m4v'), 'maybe', 'should be able to play M4V files');
162 assert.equal(canPlayType('video/ogg'),
163 '',
164 'should return empty string if it can not play the video');
165});
166
167QUnit.test('canHandleSource should be able to work with src objects without a type', function(assert) {
168 const canHandleSource = Flash.nativeSourceHandler.canHandleSource;
169
170 assert.equal('maybe',
171 canHandleSource({ src: 'test.video.mp4' }, {}),
172 'should guess that it is a mp4 video');
173 assert.equal('maybe',
174 canHandleSource({ src: 'test.video.m4v' }, {}),
175 'should guess that it is a m4v video');
176 assert.equal('maybe',
177 canHandleSource({ src: 'test.video.flv' }, {}),
178 'should guess that it is a flash video');
179 assert.equal('',
180 canHandleSource({ src: 'test.video.wgg' }, {}),
181 'should return empty string if it can not play the video');
182});
183
184QUnit.test('seekable', function(assert) {
185 const seekable = Flash.prototype.seekable;
186 let result;
187 const mockFlash = {
188 duration() {
189 return this.duration_;
190 }
191 };
192
193 // Test a normal duration
194 mockFlash.duration_ = 23;
195 result = seekable.call(mockFlash);
196 assert.equal(result.length, 1, 'seekable is non-empty');
197 assert.equal(result.start(0), 0, 'starts at zero');
198 assert.equal(result.end(0), mockFlash.duration_, 'ends at the duration');
199
200 // Test a zero duration
201 mockFlash.duration_ = 0;
202 result = seekable.call(mockFlash);
203 assert.equal(result.length, mockFlash.duration_,
204 'seekable is empty with a zero duration');
205});
206
207QUnit.test('play after ended seeks to the beginning', function(assert) {
208 let plays = 0;
209 const seeks = [];
210
211 Flash.prototype.play.call({
212 el_: {
213 /* eslint-disable camelcase */
214 vjs_play() {
215 plays++;
216 }
217 /* eslint-enable camelcase */
218 },
219 ended() {
220 return true;
221 },
222 setCurrentTime(time) {
223 seeks.push(time);
224 }
225 });
226
227 assert.equal(plays, 1, 'called play on the SWF');
228 assert.equal(seeks.length, 1, 'seeked on play');
229 assert.equal(seeks[0], 0, 'seeked to the beginning');
230});
231
232QUnit.test('duration returns NaN, Infinity or duration according to the HTML standard', function(assert) {
233 const duration = Flash.prototype.duration;
234 let mockedDuration = -1;
235 let mockedReadyState = 0;
236 let result;
237 const mockFlash = {
238 el_: {
239 /* eslint-disable camelcase */
240 vjs_getProperty() {
241 return mockedDuration;
242 }
243 /* eslint-enable camelcase */
244 },
245 readyState() {
246 return mockedReadyState;
247 }
248 };
249
250 result = duration.call(mockFlash);
251 assert.ok(Number.isNaN(result), 'duration returns NaN when readyState equals 0');
252
253 mockedReadyState = 1;
254 result = duration.call(mockFlash);
255 assert.ok(!Number.isFinite(result),
256 'duration returns Infinity when duration property is less then 0');
257
258 mockedDuration = 1;
259 result = duration.call(mockFlash);
260 assert.equal(result,
261 1,
262 'duration returns duration property when readyState' +
263 ' and duration property are both higher than 0');
264});
265
266QUnit.test('getVideoPlaybackQuality API exists', function(assert) {
267 const propertyCalls = [];
268 const videoPlaybackQuality = { test: 'test' };
269 const mockFlash = {
270 el_: {
271 /* eslint-disable camelcase */
272 vjs_getProperty(attr) {
273 propertyCalls.push(attr);
274 return videoPlaybackQuality;
275 }
276 /* eslint-enable camelcase */
277 }
278 };
279
280 assert.deepEqual(Flash.prototype.getVideoPlaybackQuality.call(mockFlash),
281 videoPlaybackQuality,
282 'called to get property from flash');
283 assert.equal(propertyCalls.length, 1, 'only one property call');
284 assert.equal(propertyCalls[0],
285 'getVideoPlaybackQuality',
286 'called for getVideoPlaybackQuality');
287});
288
289QUnit.test('getVideoPlaybackQuality uses best available creationTime', function(assert) {
290 const origPerformance = window.performance;
291 const origDate = window.Date;
292 const videoPlaybackQuality = {};
293 const mockFlash = {
294 el_: {
295 /* eslint-disable camelcase */
296 vjs_getProperty(attr) {
297 return videoPlaybackQuality;
298 }
299 /* eslint-enable camelcase */
300 }
301 };
302
303 window.performance = void 0;
304 assert.notOk(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
305 'no creationTime when no performance API available');
306
307 window.performance = {
308 timing: {}
309 };
310 assert.notOk(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
311 'no creationTime when performance API insufficient');
312
313 window.performance = {
314 now: () => 4
315 };
316 assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
317 4,
318 'creationTime is performance.now when available');
319
320 window.Date = {
321 now: () => 10
322 };
323 window.performance = {
324 timing: {
325 navigationStart: 3
326 }
327 };
328 assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
329 7,
330 'creationTime uses Date.now() - navigationStart when available');
331
332 window.performance.now = () => 4;
333 assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime,
334 4,
335 'creationTime prioritizes performance.now when available');
336
337 window.Date = origDate;
338 window.performance = origPerformance;
339});