2016-08-03 21:27:03 +02:00
/* eslint-env qunit */
2015-05-04 01:12:38 +02:00
import Tech from '../../../src/js/tech/tech.js' ;
2015-11-06 23:42:19 +02:00
import Html5 from '../../../src/js/tech/html5.js' ;
import Button from '../../../src/js/button.js' ;
2015-07-21 23:12:24 +02:00
import { createTimeRange } from '../../../src/js/utils/time-ranges.js' ;
2015-09-22 17:19:04 +02:00
import extendFn from '../../../src/js/extend.js' ;
2015-08-31 20:21:53 +02:00
import MediaError from '../../../src/js/media-error.js' ;
2016-04-22 20:31:12 +02:00
import AudioTrack from '../../../src/js/tracks/audio-track' ;
import VideoTrack from '../../../src/js/tracks/video-track' ;
import TextTrack from '../../../src/js/tracks/text-track' ;
import AudioTrackList from '../../../src/js/tracks/audio-track-list' ;
import VideoTrackList from '../../../src/js/tracks/video-track-list' ;
import TextTrackList from '../../../src/js/tracks/text-track-list' ;
2016-08-03 21:27:03 +02:00
import sinon from 'sinon' ;
2016-12-15 22:48:19 +02:00
import log from '../../../src/js/utils/log.js' ;
2016-04-22 20:31:12 +02:00
2016-08-03 21:27:03 +02:00
QUnit . module ( 'Media Tech' , {
2016-08-12 19:51:31 +02:00
beforeEach ( assert ) {
2014-12-03 21:31:39 +02:00
this . noop = function ( ) { } ;
this . clock = sinon . useFakeTimers ( ) ;
2016-08-03 21:27:03 +02:00
this . featuresProgessEvents = Tech . prototype . featuresProgessEvents ;
Tech . prototype . featuresProgressEvents = false ;
2014-08-14 02:44:36 +03:00
} ,
2016-08-12 19:51:31 +02:00
afterEach ( assert ) {
2014-12-03 21:31:39 +02:00
this . clock . restore ( ) ;
2016-08-03 21:27:03 +02:00
Tech . prototype . featuresProgessEvents = this . featuresProgessEvents ;
2014-08-14 02:44:36 +03:00
}
} ) ;
2017-02-02 21:34:33 +02:00
QUnit . test ( 'Tech.registerTech and Tech.getTech' , function ( assert ) {
const MyTech = extendFn ( Tech ) ;
const oldTechs = Tech . techs _ ;
const oldDefaultTechOrder = Tech . defaultTechOrder _ ;
Tech . registerTech ( 'MyTech' , MyTech ) ;
assert . ok ( Tech . techs _ . MyTech , 'Tech is stored in the global list' ) ;
assert . notEqual ( Tech . defaultTechOrder _ . indexOf ( 'MyTech' ) , - 1 , 'Tech is stored in the defaultTechOrder array' ) ;
assert . strictEqual ( Tech . getTech ( 'myTech' ) , MyTech , 'can get a tech using `camelCase` name' ) ;
assert . strictEqual ( Tech . getTech ( 'MyTech' ) , MyTech , 'can get a tech using `titleCase` name' ) ;
// reset techs and defaultTechOrder
Tech . techs _ = oldTechs ;
Tech . defaultTechOrder _ = oldDefaultTechOrder ;
} ) ;
2016-08-12 19:51:31 +02:00
QUnit . test ( 'should synthesize timeupdate events by default' , function ( assert ) {
2016-08-03 21:27:03 +02:00
let timeupdates = 0 ;
const tech = new Tech ( ) ;
2015-05-06 20:01:52 +02:00
2014-08-14 02:44:36 +03:00
tech . on ( 'timeupdate' , function ( ) {
timeupdates ++ ;
} ) ;
2015-05-06 20:01:52 +02:00
tech . trigger ( 'play' ) ;
2014-12-03 21:31:39 +02:00
this . clock . tick ( 250 ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( timeupdates , 1 , 'triggered at least one timeupdate' ) ;
2014-08-14 02:44:36 +03:00
} ) ;
2016-08-12 19:51:31 +02:00
QUnit . test ( 'stops manual timeupdates while paused' , function ( assert ) {
2016-08-03 21:27:03 +02:00
let timeupdates = 0 ;
const tech = new Tech ( ) ;
2015-05-06 20:01:52 +02:00
tech . on ( 'timeupdate' , function ( ) {
timeupdates ++ ;
2014-08-14 02:44:36 +03:00
} ) ;
2015-05-06 20:01:52 +02:00
tech . trigger ( 'play' ) ;
2014-12-03 21:31:39 +02:00
this . clock . tick ( 10 * 250 ) ;
2016-08-12 19:51:31 +02:00
assert . ok ( timeupdates > 0 , 'timeupdates fire during playback' ) ;
2014-08-14 02:44:36 +03:00
2015-05-06 20:01:52 +02:00
tech . trigger ( 'pause' ) ;
2014-08-14 02:44:36 +03:00
timeupdates = 0 ;
2014-12-03 21:31:39 +02:00
this . clock . tick ( 10 * 250 ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( timeupdates , 0 , 'timeupdates do not fire when paused' ) ;
2014-08-14 02:44:36 +03:00
2015-05-06 20:01:52 +02:00
tech . trigger ( 'play' ) ;
2014-12-03 21:31:39 +02:00
this . clock . tick ( 10 * 250 ) ;
2016-08-12 19:51:31 +02:00
assert . ok ( timeupdates > 0 , 'timeupdates fire when playback resumes' ) ;
2014-08-14 02:44:36 +03:00
} ) ;
2016-08-12 19:51:31 +02:00
QUnit . test ( 'should synthesize progress events by default' , function ( assert ) {
2016-08-03 21:27:03 +02:00
let progresses = 0 ;
let bufferedPercent = 0.5 ;
const tech = new Tech ( ) ;
2014-08-14 02:44:36 +03:00
tech . on ( 'progress' , function ( ) {
progresses ++ ;
} ) ;
2015-07-07 20:35:17 +02:00
tech . bufferedPercent = function ( ) {
return bufferedPercent ;
} ;
2014-08-14 02:44:36 +03:00
2015-07-07 20:35:17 +02:00
this . clock . tick ( 500 ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( progresses , 0 , 'waits until ready' ) ;
2015-07-07 20:35:17 +02:00
tech . trigger ( 'ready' ) ;
2014-12-03 21:31:39 +02:00
this . clock . tick ( 500 ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( progresses , 1 , 'triggered one event' ) ;
2015-07-07 20:35:17 +02:00
tech . trigger ( 'ready' ) ;
bufferedPercent = 0.75 ;
this . clock . tick ( 500 ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( progresses , 2 , 'repeated readies are ok' ) ;
2014-08-14 02:44:36 +03:00
} ) ;
2014-08-20 21:39:02 +03:00
2016-08-12 19:51:31 +02:00
QUnit . test ( 'dispose() should stop time tracking' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const tech = new Tech ( ) ;
2014-08-20 21:39:02 +03:00
tech . dispose ( ) ;
// progress and timeupdate events will throw exceptions after the
// tech is disposed
try {
2014-12-03 21:31:39 +02:00
this . clock . tick ( 10 * 1000 ) ;
2014-08-20 21:39:02 +03:00
} catch ( e ) {
2016-08-12 19:51:31 +02:00
return assert . equal ( e , undefined , 'threw an exception' ) ;
2014-08-20 21:39:02 +03:00
}
2016-08-12 19:51:31 +02:00
assert . ok ( true , 'no exception was thrown' ) ;
2014-08-20 21:39:02 +03:00
} ) ;
2014-12-03 00:22:34 +02:00
2016-08-12 19:51:31 +02:00
QUnit . test ( 'dispose() should clear all tracks that are passed when its created' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const audioTracks = new AudioTrackList ( [ new AudioTrack ( ) , new AudioTrack ( ) ] ) ;
const videoTracks = new VideoTrackList ( [ new VideoTrack ( ) , new VideoTrack ( ) ] ) ;
const textTracks = new TextTrackList ( [ new TextTrack ( { tech : { } } ) ,
new TextTrack ( { tech : { } } ) ] ) ;
2016-04-22 20:31:12 +02:00
2016-08-12 19:51:31 +02:00
assert . equal ( audioTracks . length , 2 , 'should have two audio tracks at the start' ) ;
assert . equal ( videoTracks . length , 2 , 'should have two video tracks at the start' ) ;
assert . equal ( textTracks . length , 2 , 'should have two text tracks at the start' ) ;
2016-04-22 20:31:12 +02:00
2016-08-03 21:27:03 +02:00
const tech = new Tech ( { audioTracks , videoTracks , textTracks } ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . videoTracks ( ) . length ,
2016-08-03 21:27:03 +02:00
videoTracks . length ,
'should hold video tracks that we passed' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . audioTracks ( ) . length ,
2016-08-03 21:27:03 +02:00
audioTracks . length ,
'should hold audio tracks that we passed' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . textTracks ( ) . length ,
2016-08-03 21:27:03 +02:00
textTracks . length ,
'should hold text tracks that we passed' ) ;
2016-04-22 20:31:12 +02:00
tech . dispose ( ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( audioTracks . length , 0 , 'should have zero audio tracks after dispose' ) ;
assert . equal ( videoTracks . length , 0 , 'should have zero video tracks after dispose' ) ;
assert . equal ( textTracks . length , 0 , 'should have zero text tracks after dispose' ) ;
2016-04-22 20:31:12 +02:00
} ) ;
2016-08-12 19:51:31 +02:00
QUnit . test ( 'dispose() should clear all tracks that are added after creation' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const tech = new Tech ( ) ;
2016-04-22 20:31:12 +02:00
2016-12-15 22:48:19 +02:00
tech . addRemoteTextTrack ( { } , true ) ;
tech . addRemoteTextTrack ( { } , true ) ;
2016-04-22 20:31:12 +02:00
2017-01-19 22:16:28 +02:00
tech . audioTracks ( ) . addTrack ( new AudioTrack ( ) ) ;
tech . audioTracks ( ) . addTrack ( new AudioTrack ( ) ) ;
2016-04-22 20:31:12 +02:00
2017-01-19 22:16:28 +02:00
tech . videoTracks ( ) . addTrack ( new VideoTrack ( ) ) ;
tech . videoTracks ( ) . addTrack ( new VideoTrack ( ) ) ;
2016-04-22 20:31:12 +02:00
2016-08-12 19:51:31 +02:00
assert . equal ( tech . audioTracks ( ) . length , 2 , 'should have two audio tracks at the start' ) ;
assert . equal ( tech . videoTracks ( ) . length , 2 , 'should have two video tracks at the start' ) ;
2016-11-09 23:07:59 +02:00
assert . equal ( tech . textTracks ( ) . length , 2 , 'should have two text tracks at the start' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . remoteTextTrackEls ( ) . length ,
2016-08-03 21:27:03 +02:00
2 ,
'should have two remote text tracks els' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . remoteTextTracks ( ) . length , 2 , 'should have two remote text tracks' ) ;
2016-04-22 20:31:12 +02:00
tech . dispose ( ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . audioTracks ( ) . length ,
2016-08-03 21:27:03 +02:00
0 ,
'should have zero audio tracks after dispose' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . videoTracks ( ) . length ,
2016-08-03 21:27:03 +02:00
0 ,
'should have zero video tracks after dispose' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . remoteTextTrackEls ( ) . length ,
2016-08-03 21:27:03 +02:00
0 ,
'should have zero remote text tracks els' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . remoteTextTracks ( ) . length , 0 , 'should have zero remote text tracks' ) ;
assert . equal ( tech . textTracks ( ) . length , 0 , 'should have zero video tracks after dispose' ) ;
2016-04-22 20:31:12 +02:00
} ) ;
2016-11-09 23:07:59 +02:00
QUnit . test ( 'switching sources should clear all remote tracks that are added with manualCleanup = false' , function ( assert ) {
2016-12-15 22:48:19 +02:00
const oldLogWarn = log . warn ;
let warning ;
log . warn = function ( wrning ) {
warning = wrning ;
} ;
2016-11-09 23:07:59 +02:00
// Define a new tech class
const MyTech = extendFn ( Tech ) ;
// Create source handler
const handler = {
canPlayType : ( ) => 'probably' ,
canHandleSource : ( ) => 'probably' ,
handleSource : ( ) => {
return {
dispose : ( ) => { }
} ;
}
} ;
// Extend Tech with source handlers
Tech . withSourceHandlers ( MyTech ) ;
MyTech . registerSourceHandler ( handler ) ;
const tech = new MyTech ( ) ;
// set the initial source
tech . setSource ( { src : 'foo.mp4' , type : 'mp4' } ) ;
// default value for manualCleanup is true
tech . addRemoteTextTrack ( { } ) ;
2016-12-15 22:48:19 +02:00
assert . equal ( warning ,
'Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js' ,
'we log a warning when `addRemoteTextTrack` is called without a manualCleanup argument' ) ;
2016-11-09 23:07:59 +02:00
// should be automatically cleaned up when source changes
tech . addRemoteTextTrack ( { } , false ) ;
assert . equal ( tech . textTracks ( ) . length , 2 , 'should have two text tracks at the start' ) ;
assert . equal ( tech . remoteTextTrackEls ( ) . length ,
2 ,
'should have two remote text tracks els' ) ;
assert . equal ( tech . remoteTextTracks ( ) . length , 2 , 'should have two remote text tracks' ) ;
assert . equal ( tech . autoRemoteTextTracks _ . length ,
1 ,
'should have one auto-cleanup remote text track' ) ;
// change source to force cleanup of auto remote text tracks
tech . setSource ( { src : 'bar.mp4' , type : 'mp4' } ) ;
assert . equal ( tech . textTracks ( ) . length ,
1 ,
'should have one text track after source change' ) ;
assert . equal ( tech . remoteTextTrackEls ( ) . length ,
1 ,
'should have one remote remote text track els after source change' ) ;
assert . equal ( tech . remoteTextTracks ( ) . length ,
1 ,
'should have one remote text track after source change' ) ;
assert . equal ( tech . autoRemoteTextTracks _ . length ,
0 ,
'should have zero auto-cleanup remote text tracks' ) ;
2016-12-15 22:48:19 +02:00
log . warn = oldLogWarn ;
2016-11-09 23:07:59 +02:00
} ) ;
2016-08-12 19:51:31 +02:00
QUnit . test ( 'should add the source handler interface to a tech' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const sourceA = { src : 'foo.mp4' , type : 'video/mp4' } ;
const sourceB = { src : 'no-support' , type : 'no-support' } ;
2014-12-03 00:22:34 +02:00
// Define a new tech class
2016-08-03 21:27:03 +02:00
const MyTech = extendFn ( Tech ) ;
2014-12-03 00:22:34 +02:00
// Extend Tech with source handlers
2015-04-14 22:08:32 +02:00
Tech . withSourceHandlers ( MyTech ) ;
2014-12-03 00:22:34 +02:00
// Check for the expected class methods
2016-08-12 19:51:31 +02:00
assert . ok ( MyTech . registerSourceHandler ,
2016-08-03 21:27:03 +02:00
'added a registerSourceHandler function to the Tech' ) ;
2016-08-12 19:51:31 +02:00
assert . ok ( MyTech . selectSourceHandler ,
2016-08-03 21:27:03 +02:00
'added a selectSourceHandler function to the Tech' ) ;
2014-12-03 00:22:34 +02:00
// Create an instance of Tech
2016-08-03 21:27:03 +02:00
const tech = new MyTech ( ) ;
2014-12-03 00:22:34 +02:00
// Check for the expected instance methods
2016-08-12 19:51:31 +02:00
assert . ok ( tech . setSource , 'added a setSource function to the tech instance' ) ;
2014-12-03 00:22:34 +02:00
// Create an internal state class for the source handler
2015-07-24 18:07:58 +02:00
// The internal class would be used by a source handler to maintain state
2014-12-03 00:22:34 +02:00
// and provde a dispose method for the handler.
// This is optional for source handlers
2016-08-03 21:27:03 +02:00
let disposeCalled = false ;
const HandlerInternalState = function ( ) { } ;
HandlerInternalState . prototype . dispose = function ( ) {
2014-12-03 00:22:34 +02:00
disposeCalled = true ;
} ;
// Create source handlers
2016-08-03 21:27:03 +02:00
const handlerOne = {
canPlayType ( type ) {
if ( type !== 'no-support' ) {
2015-10-27 19:46:05 +02:00
return 'probably' ;
}
return '' ;
} ,
2016-08-03 21:27:03 +02:00
canHandleSource ( source , options ) {
2016-08-12 19:51:31 +02:00
assert . strictEqual ( tech . options _ ,
2016-08-03 21:27:03 +02:00
options ,
'tech options passed to canHandleSource' ) ;
if ( source . type !== 'no-support' ) {
2014-12-03 00:22:34 +02:00
return 'probably' ;
}
return '' ;
} ,
2016-08-03 21:27:03 +02:00
handleSource ( s , t , o ) {
2016-08-12 19:51:31 +02:00
assert . strictEqual ( tech ,
2016-08-03 21:27:03 +02:00
t ,
'tech instance passed to source handler' ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( sourceA ,
2016-08-03 21:27:03 +02:00
s ,
'tech instance passed to the source handler' ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( tech . options _ ,
2016-08-03 21:27:03 +02:00
o ,
'tech options passed to the source handler handleSource' ) ;
return new HandlerInternalState ( ) ;
2014-12-03 00:22:34 +02:00
}
} ;
2016-08-03 21:27:03 +02:00
const handlerTwo = {
canPlayType ( type ) {
// no support
return '' ;
2015-10-27 19:46:05 +02:00
} ,
2016-08-03 21:27:03 +02:00
canHandleSource ( source , options ) {
// no support
return '' ;
2014-12-03 00:22:34 +02:00
} ,
2016-08-03 21:27:03 +02:00
handleSource ( source , tech _ , options ) {
2016-08-12 19:51:31 +02:00
assert . ok ( false , 'handlerTwo supports nothing and should never be called' ) ;
2014-12-03 00:22:34 +02:00
}
} ;
// Test registering source handlers
2015-04-14 22:08:32 +02:00
MyTech . registerSourceHandler ( handlerOne ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . sourceHandlers [ 0 ] ,
2016-08-03 21:27:03 +02:00
handlerOne ,
'handlerOne was added to the source handler array' ) ;
2015-04-14 22:08:32 +02:00
MyTech . registerSourceHandler ( handlerTwo , 0 ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . sourceHandlers [ 0 ] ,
2016-08-03 21:27:03 +02:00
handlerTwo ,
'handlerTwo was registered at the correct index (0)' ) ;
2014-12-03 00:22:34 +02:00
// Test handler selection
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . selectSourceHandler ( sourceA , tech . options _ ) ,
2016-08-03 21:27:03 +02:00
handlerOne ,
'handlerOne was selected to handle the valid source' ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . selectSourceHandler ( sourceB , tech . options _ ) ,
2016-08-03 21:27:03 +02:00
null ,
'no handler was selected to handle the invalid source' ) ;
2014-12-03 00:22:34 +02:00
2015-10-27 19:46:05 +02:00
// Test canPlayType return values
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . canPlayType ( sourceA . type ) ,
2016-08-03 21:27:03 +02:00
'probably' ,
'the Tech returned probably for the valid source' ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . canPlayType ( sourceB . type ) ,
2016-08-03 21:27:03 +02:00
'' ,
'the Tech returned an empty string for the invalid source' ) ;
2015-10-27 19:46:05 +02:00
2014-12-03 00:22:34 +02:00
// Test canPlaySource return values
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . canPlaySource ( sourceA , tech . options _ ) ,
2016-08-03 21:27:03 +02:00
'probably' ,
'the Tech returned probably for the valid source' ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( MyTech . canPlaySource ( sourceB , tech . options _ ) ,
2016-08-03 21:27:03 +02:00
'' ,
'the Tech returned an empty string for the invalid source' ) ;
2014-12-03 00:22:34 +02:00
2016-12-15 22:48:19 +02:00
tech . addRemoteTextTrack ( { } , true ) ;
tech . addRemoteTextTrack ( { } , true ) ;
2016-04-22 20:31:12 +02:00
2017-01-19 22:16:28 +02:00
tech . audioTracks ( ) . addTrack ( new AudioTrack ( ) ) ;
tech . audioTracks ( ) . addTrack ( new AudioTrack ( ) ) ;
2016-04-22 20:31:12 +02:00
2017-01-19 22:16:28 +02:00
tech . videoTracks ( ) . addTrack ( new VideoTrack ( ) ) ;
tech . videoTracks ( ) . addTrack ( new VideoTrack ( ) ) ;
2016-04-22 20:31:12 +02:00
2016-08-12 19:51:31 +02:00
assert . equal ( tech . audioTracks ( ) . length , 2 , 'should have two audio tracks at the start' ) ;
assert . equal ( tech . videoTracks ( ) . length , 2 , 'should have two video tracks at the start' ) ;
assert . equal ( tech . textTracks ( ) . length , 2 , 'should have two video tracks at the start' ) ;
assert . equal ( tech . remoteTextTrackEls ( ) . length ,
2016-08-03 21:27:03 +02:00
2 ,
'should have two remote text tracks els' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . remoteTextTracks ( ) . length , 2 , 'should have two remote text tracks' ) ;
2016-04-22 20:31:12 +02:00
2014-12-03 00:22:34 +02:00
// Pass a source through the source handler process of a tech instance
tech . setSource ( sourceA ) ;
2016-04-22 20:31:12 +02:00
// verify that the Tracks are still there
2016-08-12 19:51:31 +02:00
assert . equal ( tech . audioTracks ( ) . length , 2 , 'should have two audio tracks at the start' ) ;
assert . equal ( tech . videoTracks ( ) . length , 2 , 'should have two video tracks at the start' ) ;
assert . equal ( tech . textTracks ( ) . length , 2 , 'should have two video tracks at the start' ) ;
assert . equal ( tech . remoteTextTrackEls ( ) . length ,
2016-08-03 21:27:03 +02:00
2 ,
'should have two remote text tracks els' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . remoteTextTracks ( ) . length , 2 , 'should have two remote text tracks' ) ;
2016-04-22 20:31:12 +02:00
2016-08-12 19:51:31 +02:00
assert . strictEqual ( tech . currentSource _ , sourceA , 'sourceA was handled and stored' ) ;
assert . ok ( tech . sourceHandler _ . dispose , 'the handlerOne state instance was stored' ) ;
2014-12-03 00:22:34 +02:00
2016-04-22 20:31:12 +02:00
// Pass a second source
tech . setSource ( sourceA ) ;
2016-08-12 19:51:31 +02:00
assert . strictEqual ( tech . currentSource _ , sourceA , 'sourceA was handled and stored' ) ;
assert . ok ( tech . sourceHandler _ . dispose , 'the handlerOne state instance was stored' ) ;
2016-04-22 20:31:12 +02:00
// verify that all the tracks were removed as we got a new source
2016-08-12 19:51:31 +02:00
assert . equal ( tech . audioTracks ( ) . length , 0 , 'should have zero audio tracks' ) ;
assert . equal ( tech . videoTracks ( ) . length , 0 , 'should have zero video tracks' ) ;
assert . equal ( tech . textTracks ( ) . length , 2 , 'should have two text tracks' ) ;
assert . equal ( tech . remoteTextTrackEls ( ) . length ,
2016-08-03 21:27:03 +02:00
2 ,
'should have two remote text tracks els' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . remoteTextTracks ( ) . length , 2 , 'should have two remote text tracks' ) ;
2016-04-22 20:31:12 +02:00
2014-12-03 00:22:34 +02:00
// Check that the handler dipose method works
2016-08-12 19:51:31 +02:00
assert . ok ( disposeCalled , 'dispose has been called for the handler yet' ) ;
2016-04-22 20:31:12 +02:00
disposeCalled = false ;
2014-12-03 00:22:34 +02:00
tech . dispose ( ) ;
2016-08-12 19:51:31 +02:00
assert . ok ( disposeCalled ,
2016-08-03 21:27:03 +02:00
'the handler dispose method was called when the tech was disposed' ) ;
2014-12-03 00:22:34 +02:00
} ) ;
2015-02-28 01:50:13 +02:00
2016-08-12 19:51:31 +02:00
QUnit . test ( 'should handle unsupported sources with the source handler API' , function ( assert ) {
2015-02-28 01:50:13 +02:00
// Define a new tech class
2016-08-03 21:27:03 +02:00
const MyTech = extendFn ( Tech ) ;
2015-02-28 01:50:13 +02:00
// Extend Tech with source handlers
2015-04-14 22:08:32 +02:00
Tech . withSourceHandlers ( MyTech ) ;
2015-02-28 01:50:13 +02:00
// Create an instance of Tech
2016-08-03 21:27:03 +02:00
const tech = new MyTech ( ) ;
let usedNative ;
2015-02-28 01:50:13 +02:00
2015-04-14 22:08:32 +02:00
MyTech . nativeSourceHandler = {
2016-08-03 21:27:03 +02:00
handleSource ( ) {
usedNative = true ;
}
2015-02-28 01:50:13 +02:00
} ;
tech . setSource ( '' ) ;
2016-08-12 19:51:31 +02:00
assert . ok ( usedNative ,
2016-08-03 21:27:03 +02:00
'native source handler was used when an unsupported source was set' ) ;
2015-03-11 03:01:11 +02:00
} ) ;
2015-07-21 22:56:23 +02:00
2016-08-12 19:51:31 +02:00
QUnit . test ( 'should allow custom error events to be set' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const tech = new Tech ( ) ;
const errors = [ ] ;
2015-08-31 20:21:53 +02:00
tech . on ( 'error' , function ( ) {
errors . push ( tech . error ( ) ) ;
} ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . error ( ) , null , 'error is null by default' ) ;
2015-08-31 20:21:53 +02:00
tech . error ( new MediaError ( 1 ) ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( errors . length , 1 , 'triggered an error event' ) ;
assert . equal ( errors [ 0 ] . code , 1 , 'set the proper code' ) ;
2015-08-31 20:21:53 +02:00
tech . error ( 2 ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( errors . length , 2 , 'triggered an error event' ) ;
assert . equal ( errors [ 1 ] . code , 2 , 'wrapped the error code' ) ;
2015-08-31 20:21:53 +02:00
} ) ;
2016-08-12 19:51:31 +02:00
QUnit . test ( 'should track whether a video has played' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const tech = new Tech ( ) ;
2015-07-21 22:56:23 +02:00
2016-08-12 19:51:31 +02:00
assert . equal ( tech . played ( ) . length , 0 , 'starts with zero length' ) ;
2015-07-21 22:56:23 +02:00
tech . trigger ( 'playing' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( tech . played ( ) . length , 1 , 'has length after playing' ) ;
2015-07-21 22:56:23 +02:00
} ) ;
2015-07-21 23:12:24 +02:00
2016-08-12 19:51:31 +02:00
QUnit . test ( 'delegates seekable to the source handler' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const MyTech = extendFn ( Tech , {
seekable ( ) {
2015-07-21 23:12:24 +02:00
throw new Error ( 'You should not be calling me!' ) ;
}
} ) ;
2016-08-03 21:27:03 +02:00
2015-07-21 23:12:24 +02:00
Tech . withSourceHandlers ( MyTech ) ;
let seekableCount = 0 ;
2016-08-03 21:27:03 +02:00
const handler = {
seekable ( ) {
2015-07-21 23:12:24 +02:00
seekableCount ++ ;
return createTimeRange ( 0 , 0 ) ;
}
} ;
MyTech . registerSourceHandler ( {
2016-08-03 21:27:03 +02:00
canPlayType ( ) {
2015-10-27 19:46:05 +02:00
return true ;
} ,
2016-08-03 21:27:03 +02:00
canHandleSource ( ) {
2015-07-21 23:12:24 +02:00
return true ;
} ,
2016-08-03 21:27:03 +02:00
handleSource ( source , tech , options ) {
2015-07-21 23:12:24 +02:00
return handler ;
}
} ) ;
2016-08-03 21:27:03 +02:00
const tech = new MyTech ( ) ;
2015-07-21 23:12:24 +02:00
tech . setSource ( {
src : 'example.mp4' ,
type : 'video/mp4'
} ) ;
tech . seekable ( ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( seekableCount , 1 , 'called the source handler' ) ;
2015-07-21 23:12:24 +02:00
} ) ;
2015-11-06 23:42:19 +02:00
2016-08-12 19:51:31 +02:00
QUnit . test ( 'Tech.isTech returns correct answers for techs and components' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const isTech = Tech . isTech ;
2016-08-12 19:51:31 +02:00
assert . ok ( isTech ( Tech ) , 'Tech is a Tech' ) ;
assert . ok ( isTech ( Html5 ) , 'Html5 is a Tech' ) ;
assert . ok ( isTech ( new Html5 ( { } , { } ) ) , 'An html5 instance is a Tech' ) ;
assert . ok ( ! isTech ( 5 ) , 'A number is not a Tech' ) ;
assert . ok ( ! isTech ( 'this is a tech' ) , 'A string is not a Tech' ) ;
assert . ok ( ! isTech ( Button ) , 'A Button is not a Tech' ) ;
assert . ok ( ! isTech ( new Button ( { } , { } ) ) , 'A Button instance is not a Tech' ) ;
assert . ok ( ! isTech ( isTech ) , 'A function is not a Tech' ) ;
2015-11-06 23:42:19 +02:00
} ) ;
2016-05-03 00:54:34 +02:00
2016-08-12 19:51:31 +02:00
QUnit . test ( 'setSource after tech dispose should dispose source handler once' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const MyTech = extendFn ( Tech ) ;
2016-05-28 00:12:47 +02:00
Tech . withSourceHandlers ( MyTech ) ;
let disposeCount = 0 ;
2016-08-03 21:27:03 +02:00
const handler = {
2016-05-28 00:12:47 +02:00
dispose ( ) {
disposeCount ++ ;
}
} ;
MyTech . registerSourceHandler ( {
2016-08-03 21:27:03 +02:00
canPlayType ( ) {
2016-05-28 00:12:47 +02:00
return true ;
} ,
2016-08-03 21:27:03 +02:00
canHandleSource ( ) {
2016-05-28 00:12:47 +02:00
return true ;
} ,
2016-08-03 21:27:03 +02:00
handleSource ( source , tech , options ) {
2016-05-28 00:12:47 +02:00
return handler ;
}
} ) ;
2016-08-03 21:27:03 +02:00
const tech = new MyTech ( ) ;
2016-05-28 00:12:47 +02:00
tech . setSource ( 'test' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( disposeCount , 0 , 'did not call sourceHandler_ dispose for initial dispose' ) ;
2016-05-28 00:12:47 +02:00
tech . dispose ( ) ;
2016-08-12 19:51:31 +02:00
assert . ok ( ! tech . sourceHandler _ , 'sourceHandler should be unset' ) ;
assert . equal ( disposeCount , 1 , 'called the source handler dispose' ) ;
2016-05-28 00:12:47 +02:00
// this would normally be done above tech on src after dispose
tech . el _ = tech . createEl ( ) ;
tech . setSource ( 'test' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( disposeCount , 1 , 'did not dispose after initial setSource' ) ;
2016-05-28 00:12:47 +02:00
tech . setSource ( 'test' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( disposeCount , 2 , 'did dispose on second setSource' ) ;
2016-05-28 00:12:47 +02:00
} ) ;
2016-08-12 19:51:31 +02:00
QUnit . test ( 'setSource after previous setSource should dispose source handler once' , function ( assert ) {
2016-08-03 21:27:03 +02:00
const MyTech = extendFn ( Tech ) ;
2016-05-28 00:12:47 +02:00
Tech . withSourceHandlers ( MyTech ) ;
let disposeCount = 0 ;
2016-08-03 21:27:03 +02:00
const handler = {
2016-05-28 00:12:47 +02:00
dispose ( ) {
disposeCount ++ ;
}
} ;
MyTech . registerSourceHandler ( {
2016-08-03 21:27:03 +02:00
canPlayType ( ) {
2016-05-28 00:12:47 +02:00
return true ;
} ,
2016-08-03 21:27:03 +02:00
canHandleSource ( ) {
2016-05-28 00:12:47 +02:00
return true ;
} ,
2016-08-03 21:27:03 +02:00
handleSource ( source , tech , options ) {
2016-05-28 00:12:47 +02:00
return handler ;
}
} ) ;
2016-08-03 21:27:03 +02:00
const tech = new MyTech ( ) ;
2016-05-28 00:12:47 +02:00
tech . setSource ( 'test' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( disposeCount , 0 , 'did not call dispose for initial setSource' ) ;
2016-05-28 00:12:47 +02:00
tech . setSource ( 'test' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( disposeCount , 1 , 'did dispose for second setSource' ) ;
2016-05-28 00:12:47 +02:00
tech . setSource ( 'test' ) ;
2016-08-12 19:51:31 +02:00
assert . equal ( disposeCount , 2 , 'did dispose for third setSource' ) ;
2016-05-28 00:12:47 +02:00
} ) ;
2017-05-12 21:22:02 +02:00
QUnit . test ( 'returns an empty object for getVideoPlaybackQuality' , function ( assert ) {
const tech = new Tech ( ) ;
assert . deepEqual ( tech . getVideoPlaybackQuality ( ) , { } , 'returns an empty object' ) ;
} ) ;