2014-05-17 00:48:05 +03:00
var player , tech , el ;
2015-05-04 01:12:38 +02:00
import Html5 from '../../../src/js/tech/html5.js' ;
import * as browser from '../../../src/js/utils/browser.js' ;
2015-03-26 06:43:41 +02:00
import document from 'global/document' ;
2015-03-11 03:01:11 +02:00
2015-03-26 06:43:41 +02:00
q . module ( 'HTML5' , {
2014-05-17 00:48:05 +03:00
'setup' : function ( ) {
el = document . createElement ( 'div' ) ;
el . innerHTML = '<div />' ;
player = {
id : function ( ) { return 'id' ; } ,
el : function ( ) { return el ; } ,
options _ : { } ,
2014-10-04 01:24:22 +03:00
options : function ( ) { return this . options _ ; } ,
2014-08-14 02:44:36 +03:00
bufferedPercent : function ( ) { return 0 ; } ,
2014-05-17 00:48:05 +03:00
controls : function ( ) { return false ; } ,
usingNativeControls : function ( ) { return false ; } ,
on : function ( ) { return this ; } ,
off : function ( ) { return this ; } ,
2014-08-14 02:44:36 +03:00
ready : function ( ) { } ,
2015-02-14 01:18:07 +02:00
addChild : function ( ) { } ,
2014-08-14 02:44:36 +03:00
trigger : function ( ) { }
2014-05-17 00:48:05 +03:00
} ;
2015-05-06 20:01:52 +02:00
tech = new Html5 ( { } ) ;
2014-05-17 00:48:05 +03:00
} ,
'teardown' : function ( ) {
tech . dispose ( ) ;
el = null ;
player = null ;
tech = null ;
}
} ) ;
2013-03-02 01:11:20 +03:00
test ( 'should detect whether the volume can be changed' , function ( ) {
2013-03-05 21:38:47 +03:00
var testVid , ConstVolumeVideo ;
2013-03-06 02:07:35 +03:00
if ( ! { } [ '__defineSetter__' ] ) {
ok ( true , 'your browser does not support this test, skipping it' ) ;
return ;
}
2015-05-04 01:12:38 +02:00
testVid = Html5 . TEST _VID ;
2013-03-05 21:38:47 +03:00
ConstVolumeVideo = function ( ) {
this . volume = 1 ;
this . _ _defineSetter _ _ ( 'volume' , function ( ) { } ) ;
} ;
2015-05-04 01:12:38 +02:00
Html5 . TEST _VID = new ConstVolumeVideo ( ) ;
2013-03-02 01:11:20 +03:00
2015-03-11 03:01:11 +02:00
ok ( ! Html5 . canControlVolume ( ) ) ;
2015-05-04 01:12:38 +02:00
Html5 . TEST _VID = testVid ;
2013-03-02 01:11:20 +03:00
} ) ;
2013-03-08 04:57:52 +03:00
2014-05-17 00:48:05 +03:00
test ( 'test playbackRate' , function ( ) {
var playbackRate ;
2014-09-03 03:38:11 +03:00
// Android 2.3 always returns 0 for playback rate
2015-03-11 03:01:11 +02:00
if ( ! Html5 . canControlPlaybackRate ( ) ) {
2014-09-03 03:38:11 +03:00
ok ( 'Playback rate is not supported' ) ;
return ;
}
2014-05-17 00:48:05 +03:00
tech . createEl ( ) ;
tech . el ( ) . playbackRate = 1.25 ;
strictEqual ( tech . playbackRate ( ) , 1.25 ) ;
tech [ 'setPlaybackRate' ] ( 0.75 ) ;
strictEqual ( tech . playbackRate ( ) , 0.75 ) ;
} ) ;
2015-07-21 22:56:23 +02:00
test ( 'should export played' , function ( ) {
tech . createEl ( ) ;
deepEqual ( tech . played ( ) , tech . el ( ) . played , 'returns the played attribute' ) ;
} ) ;
2014-10-04 01:24:22 +03:00
test ( 'should remove the controls attribute when recreating the element' , function ( ) {
var el ;
player . tagAttributes = {
controls : true
} ;
// force custom controls so the test environment is equivalent on iOS
player . options _ [ 'nativeControlsForTouch' ] = false ;
el = tech . createEl ( ) ;
2015-02-17 23:49:32 +02:00
// On the iPhone controls are always true
2015-05-04 01:12:38 +02:00
if ( ! browser . IS _IPHONE ) {
2015-02-17 23:49:32 +02:00
ok ( ! el . controls , 'controls attribute is absent' ) ;
}
2014-10-04 01:24:22 +03:00
ok ( player . tagAttributes . controls , 'tag attribute is still present' ) ;
} ) ;
2014-03-18 03:47:47 +03:00
test ( 'patchCanPlayType patches canplaytype with our function, conditionally' , function ( ) {
2014-03-27 21:19:21 +03:00
// the patch runs automatically so we need to first unpatch
2015-03-11 03:01:11 +02:00
Html5 . unpatchCanPlayType ( ) ;
2014-03-27 21:19:21 +03:00
2015-05-04 01:12:38 +02:00
var oldAV = browser . ANDROID _VERSION ,
2014-03-18 03:47:47 +03:00
video = document . createElement ( 'video' ) ,
2015-05-04 01:12:38 +02:00
canPlayType = Html5 . TEST _VID . constructor . prototype . canPlayType ,
2014-03-26 21:58:36 +03:00
patchedCanPlayType ,
2014-03-18 03:47:47 +03:00
unpatchedCanPlayType ;
2015-05-04 01:12:38 +02:00
browser . ANDROID _VERSION = 4.0 ;
2015-03-11 03:01:11 +02:00
Html5 . patchCanPlayType ( ) ;
2014-03-18 03:47:47 +03:00
notStrictEqual ( video . canPlayType , canPlayType , 'original canPlayType and patched canPlayType should not be equal' ) ;
2014-03-26 21:58:36 +03:00
patchedCanPlayType = video . canPlayType ;
2015-03-11 03:01:11 +02:00
unpatchedCanPlayType = Html5 . unpatchCanPlayType ( ) ;
2014-03-18 03:47:47 +03:00
2015-05-04 01:12:38 +02:00
strictEqual ( canPlayType , Html5 . TEST _VID . constructor . prototype . canPlayType , 'original canPlayType and unpatched canPlayType should be equal' ) ;
2014-03-26 23:59:04 +03:00
strictEqual ( patchedCanPlayType , unpatchedCanPlayType , 'patched canPlayType and function returned from unpatch are equal' ) ;
2014-03-18 03:47:47 +03:00
2015-05-04 01:12:38 +02:00
browser . ANDROID _VERSION = oldAV ;
2015-03-26 06:43:41 +02:00
Html5 . unpatchCanPlayType ( ) ;
2014-03-18 03:47:47 +03:00
} ) ;
test ( 'should return maybe for HLS urls on Android 4.0 or above' , function ( ) {
2015-05-04 01:12:38 +02:00
var oldAV = browser . ANDROID _VERSION ,
2014-03-18 03:47:47 +03:00
video = document . createElement ( 'video' ) ;
2015-05-04 01:12:38 +02:00
browser . ANDROID _VERSION = 4.0 ;
2015-03-26 06:43:41 +02:00
Html5 . patchCanPlayType ( ) ;
2014-03-18 03:47:47 +03:00
2014-03-25 01:00:00 +03:00
strictEqual ( video . canPlayType ( 'application/x-mpegurl' ) , 'maybe' , 'android version 4.0 or above should be a maybe for x-mpegurl' ) ;
strictEqual ( video . canPlayType ( 'application/x-mpegURL' ) , 'maybe' , 'android version 4.0 or above should be a maybe for x-mpegURL' ) ;
strictEqual ( video . canPlayType ( 'application/vnd.apple.mpegurl' ) , 'maybe' , 'android version 4.0 or above should be a maybe for vnd.apple.mpegurl' ) ;
strictEqual ( video . canPlayType ( 'application/vnd.apple.mpegURL' ) , 'maybe' , 'android version 4.0 or above should be a maybe for vnd.apple.mpegurl' ) ;
2014-03-18 03:47:47 +03:00
2015-05-04 01:12:38 +02:00
browser . ANDROID _VERSION = oldAV ;
2015-03-26 06:43:41 +02:00
Html5 . unpatchCanPlayType ( ) ;
2014-03-18 03:47:47 +03:00
} ) ;
test ( 'should return a maybe for mp4 on OLD ANDROID' , function ( ) {
2015-05-04 01:12:38 +02:00
var isOldAndroid = browser . IS _OLD _ANDROID ,
2014-03-18 03:47:47 +03:00
video = document . createElement ( 'video' ) ;
2015-05-04 01:12:38 +02:00
browser . IS _OLD _ANDROID = true ;
2015-03-26 06:43:41 +02:00
Html5 . patchCanPlayType ( ) ;
2014-03-18 03:47:47 +03:00
strictEqual ( video . canPlayType ( 'video/mp4' ) , 'maybe' , 'old android should return a maybe for video/mp4' ) ;
2015-05-04 01:12:38 +02:00
browser . IS _OLD _ANDROID = isOldAndroid ;
2015-03-26 06:43:41 +02:00
Html5 . unpatchCanPlayType ( ) ;
2014-03-18 03:47:47 +03:00
} ) ;
2014-09-04 19:12:36 +03:00
test ( 'error events may not set the errors property' , function ( ) {
equal ( tech . error ( ) , undefined , 'no tech-level error' ) ;
tech . trigger ( 'error' ) ;
ok ( true , 'no error was thrown' ) ;
} ) ;
2014-12-03 00:22:34 +02:00
test ( 'should have the source handler interface' , function ( ) {
2015-03-26 06:43:41 +02:00
ok ( Html5 . registerSourceHandler , 'has the registerSourceHandler function' ) ;
2014-12-03 00:22:34 +02:00
} ) ;
2015-01-16 21:42:27 +02:00
test ( 'native source handler canHandleSource' , function ( ) {
var result ;
// Stub the test video canPlayType (used in canHandleSource) to control results
2015-05-04 01:12:38 +02:00
var origCPT = Html5 . TEST _VID . canPlayType ;
Html5 . TEST _VID . canPlayType = function ( type ) {
2015-01-16 21:42:27 +02:00
if ( type === 'video/mp4' ) {
return 'maybe' ;
}
return '' ;
} ;
2015-03-26 06:43:41 +02:00
var canHandleSource = Html5 . nativeSourceHandler . canHandleSource ;
2015-01-16 21:42:27 +02:00
equal ( canHandleSource ( { type : 'video/mp4' , src : 'video.flv' } ) , 'maybe' , 'Native source handler reported type support' ) ;
equal ( canHandleSource ( { src : 'http://www.example.com/video.mp4' } ) , 'maybe' , 'Native source handler reported extension support' ) ;
2015-01-22 03:55:35 +02:00
equal ( canHandleSource ( { src : 'https://example.com/video.sd.mp4?s=foo&token=bar' } ) , 'maybe' , 'Native source handler reported extension support' ) ;
equal ( canHandleSource ( { src : 'https://example.com/video.sd.mp4?s=foo' } ) , 'maybe' , 'Native source handler reported extension support' ) ;
2015-01-16 21:42:27 +02:00
// Test for issue videojs/video.js#1785 and other potential failures
equal ( canHandleSource ( { src : '' } ) , '' , 'Native source handler handled empty src' ) ;
equal ( canHandleSource ( { } ) , '' , 'Native source handler handled empty object' ) ;
equal ( canHandleSource ( { src : 'foo' } ) , '' , 'Native source handler handled bad src' ) ;
equal ( canHandleSource ( { type : 'foo' } ) , '' , 'Native source handler handled bad type' ) ;
// Reset test video canPlayType
2015-05-04 01:12:38 +02:00
Html5 . TEST _VID . canPlayType = origCPT ;
2015-01-16 21:42:27 +02:00
} ) ;
2015-08-03 21:19:36 +02:00
if ( Html5 . supportsNativeTextTracks ( ) ) {
test ( 'add native textTrack listeners on startup' , function ( ) {
let adds = [ ] ;
let rems = [ ] ;
let tt = {
length : 0 ,
addEventListener : ( type , fn ) => adds . push ( [ type , fn ] ) ,
removeEventListener : ( type , fn ) => rems . push ( [ type , fn ] ) ,
} ;
let el = document . createElement ( 'div' ) ;
el . textTracks = tt ;
let htmlTech = new Html5 ( { el } ) ;
equal ( adds [ 0 ] [ 0 ] , 'change' , 'change event handler added' ) ;
equal ( adds [ 1 ] [ 0 ] , 'addtrack' , 'addtrack event handler added' ) ;
equal ( adds [ 2 ] [ 0 ] , 'removetrack' , 'removetrack event handler added' ) ;
} ) ;
test ( 'remove all tracks from emulated list on dispose' , function ( ) {
let adds = [ ] ;
let rems = [ ] ;
let tt = {
length : 0 ,
addEventListener : ( type , fn ) => adds . push ( [ type , fn ] ) ,
removeEventListener : ( type , fn ) => rems . push ( [ type , fn ] ) ,
} ;
let el = document . createElement ( 'div' ) ;
el . textTracks = tt ;
let htmlTech = new Html5 ( { el } ) ;
htmlTech . dispose ( ) ;
equal ( adds [ 0 ] [ 0 ] , 'change' , 'change event handler added' ) ;
equal ( adds [ 1 ] [ 0 ] , 'addtrack' , 'addtrack event handler added' ) ;
equal ( adds [ 2 ] [ 0 ] , 'removetrack' , 'removetrack event handler added' ) ;
equal ( rems [ 0 ] [ 0 ] , 'change' , 'change event handler removed' ) ;
equal ( rems [ 1 ] [ 0 ] , 'addtrack' , 'addtrack event handler removed' ) ;
equal ( rems [ 2 ] [ 0 ] , 'removetrack' , 'removetrack event handler removed' ) ;
equal ( adds [ 0 ] [ 0 ] , rems [ 0 ] [ 0 ] , 'change event handler removed' ) ;
equal ( adds [ 1 ] [ 0 ] , rems [ 1 ] [ 0 ] , 'addtrack event handler removed' ) ;
equal ( adds [ 2 ] [ 0 ] , rems [ 2 ] [ 0 ] , 'removetrack event handler removed' ) ;
} ) ;
}
2015-09-15 01:37:39 +02:00
test ( 'should fire makeup events when a video tag is initialized late' , function ( ) {
let lateInit = Html5 . prototype . handleLateInit _ ;
let triggeredEvents = [ ] ;
let mockHtml5 = {
readyListeners : [ ] ,
ready ( listener ) {
this . readyListeners . push ( listener ) ;
} ,
triggerReady ( ) {
this . readyListeners . forEach ( function ( listener ) {
listener . call ( this ) ;
} , this ) ;
} ,
trigger ( type ) {
triggeredEvents . push ( type ) ;
} ,
on : function ( ) { } ,
off : function ( ) { }
} ;
function resetMock ( ) {
triggeredEvents = { } ;
mockHtml5 . readyListeners = [ ] ;
}
function testStates ( statesObject , expectedEvents ) {
lateInit . call ( mockHtml5 , statesObject ) ;
mockHtml5 . triggerReady ( ) ;
deepEqual ( triggeredEvents , expectedEvents , ` wrong events triggered for networkState: ${ statesObject . networkState } and readyState: ${ statesObject . readyState || 'no readyState' } ` ) ;
// reset mock
triggeredEvents = [ ] ;
mockHtml5 . readyListeners = [ ] ;
}
// Network States
testStates ( { networkState : 0 , readyState : 0 } , [ ] ) ;
testStates ( { networkState : 1 , readyState : 0 } , [ 'loadstart' ] ) ;
testStates ( { networkState : 2 , readyState : 0 } , [ 'loadstart' ] ) ;
testStates ( { networkState : 3 , readyState : 0 } , [ ] ) ;
// Ready States
testStates ( { networkState : 1 , readyState : 0 } , [ 'loadstart' ] ) ;
testStates ( { networkState : 1 , readyState : 1 } , [ 'loadstart' , 'loadedmetadata' ] ) ;
testStates ( { networkState : 1 , readyState : 2 } , [ 'loadstart' , 'loadedmetadata' , 'loadeddata' ] ) ;
testStates ( { networkState : 1 , readyState : 3 } , [ 'loadstart' , 'loadedmetadata' , 'loadeddata' , 'canplay' ] ) ;
testStates ( { networkState : 1 , readyState : 4 } , [ 'loadstart' , 'loadedmetadata' , 'loadeddata' , 'canplay' , 'canplaythrough' ] ) ;
} ) ;