Add tests for Youtube part of Videoalpha
This commit is contained in:
committed by
Vasyl Nakvasiuk
parent
80f38b8f3c
commit
70cc9a168b
23
common/lib/xmodule/xmodule/js/fixtures/videoalpha.html
Normal file
23
common/lib/xmodule/xmodule/js/fixtures/videoalpha.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<div class="course-content">
|
||||
<div id="video_example">
|
||||
<div id="example">
|
||||
<div
|
||||
id="video_id"
|
||||
class="video"
|
||||
data-streams="0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId"
|
||||
data-show-captions="true"
|
||||
data-start=""
|
||||
data-end=""
|
||||
data-caption-asset-path="/static/subs/">
|
||||
<div class="tc-wrapper">
|
||||
<article class="video-wrapper">
|
||||
<section class="video-player">
|
||||
<div id="id"></div>
|
||||
</section>
|
||||
<section class="video-controls"></section>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -41,9 +41,12 @@ jasmine.stubRequests = ->
|
||||
throw "External request attempted for #{settings.url}, which is not defined."
|
||||
|
||||
jasmine.stubYoutubePlayer = ->
|
||||
YT.Player = -> jasmine.createSpyObj 'YT.Player', ['cueVideoById', 'getVideoEmbedCode',
|
||||
YT.Player = ->
|
||||
obj = jasmine.createSpyObj 'YT.Player', ['cueVideoById', 'getVideoEmbedCode',
|
||||
'getCurrentTime', 'getPlayerState', 'getVolume', 'setVolume', 'loadVideoById',
|
||||
'playVideo', 'pauseVideo', 'seekTo']
|
||||
'playVideo', 'pauseVideo', 'seekTo', 'getDuration', 'getAvailablePlaybackRates', 'setPlaybackRate']
|
||||
obj['getAvailablePlaybackRates'] = jasmine.createSpy('getAvailablePlaybackRates').andReturn [0.75, 1.0, 1.25, 1.5]
|
||||
obj
|
||||
|
||||
jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) ->
|
||||
enableParts = [enableParts] unless $.isArray(enableParts)
|
||||
@@ -60,6 +63,19 @@ jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) ->
|
||||
if createPlayer
|
||||
return new VideoPlayer(video: context.video)
|
||||
|
||||
jasmine.stubVideoPlayerAlpha = (context, enableParts, createPlayer=true) ->
|
||||
suite = context.suite
|
||||
currentPartName = suite.description while suite = suite.parentSuite
|
||||
|
||||
loadFixtures 'videoalpha.html'
|
||||
jasmine.stubRequests()
|
||||
YT.Player = undefined
|
||||
window.OldVideoPlayerAlpha = undefined
|
||||
context.video = new VideoAlpha '#example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
|
||||
jasmine.stubYoutubePlayer()
|
||||
if createPlayer
|
||||
return new VideoPlayerAlpha(video: context.video)
|
||||
|
||||
|
||||
# Stub jQuery.cookie
|
||||
$.cookie = jasmine.createSpy('jQuery.cookie').andReturn '1.0'
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
describe 'VideoCaptionAlpha', ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(VideoCaptionAlpha.prototype, 'fetchCaption').andCallThrough()
|
||||
spyOn($, 'ajaxWithPrefix').andCallThrough()
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
|
||||
|
||||
afterEach ->
|
||||
YT.Player = undefined
|
||||
$.fn.scrollTo.reset()
|
||||
$('.subtitles').remove()
|
||||
|
||||
describe 'constructor', ->
|
||||
|
||||
describe 'always', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
|
||||
it 'set the youtube id', ->
|
||||
expect(@caption.youtubeId).toEqual 'normalSpeedYoutubeId'
|
||||
|
||||
it 'create the caption element', ->
|
||||
expect($('.video')).toContain 'ol.subtitles'
|
||||
|
||||
it 'add caption control to video player', ->
|
||||
expect($('.video')).toContain 'a.hide-subtitles'
|
||||
|
||||
it 'fetch the caption', ->
|
||||
expect(@caption.loaded).toBeTruthy()
|
||||
expect(@caption.fetchCaption).toHaveBeenCalled()
|
||||
expect($.ajaxWithPrefix).toHaveBeenCalledWith
|
||||
url: @caption.captionURL()
|
||||
notifyOnError: false
|
||||
success: jasmine.any(Function)
|
||||
|
||||
it 'bind window resize event', ->
|
||||
expect($(window)).toHandleWith 'resize', @caption.resize
|
||||
|
||||
it 'bind the hide caption button', ->
|
||||
expect($('.hide-subtitles')).toHandleWith 'click', @caption.toggle
|
||||
|
||||
it 'bind the mouse movement', ->
|
||||
expect($('.subtitles')).toHandleWith 'mouseover', @caption.onMouseEnter
|
||||
expect($('.subtitles')).toHandleWith 'mouseout', @caption.onMouseLeave
|
||||
expect($('.subtitles')).toHandleWith 'mousemove', @caption.onMovement
|
||||
expect($('.subtitles')).toHandleWith 'mousewheel', @caption.onMovement
|
||||
expect($('.subtitles')).toHandleWith 'DOMMouseScroll', @caption.onMovement
|
||||
|
||||
describe 'when on a non touch-based device', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
|
||||
it 'render the caption', ->
|
||||
captionsData = jasmine.stubbedCaption
|
||||
$('.subtitles li[data-index]').each (index, link) =>
|
||||
expect($(link)).toHaveData 'index', index
|
||||
expect($(link)).toHaveData 'start', captionsData.start[index]
|
||||
expect($(link)).toHaveText captionsData.text[index]
|
||||
|
||||
it 'add a padding element to caption', ->
|
||||
expect($('.subtitles li:first')).toBe '.spacing'
|
||||
expect($('.subtitles li:last')).toBe '.spacing'
|
||||
|
||||
it 'bind all the caption link', ->
|
||||
$('.subtitles li[data-index]').each (index, link) =>
|
||||
expect($(link)).toHandleWith 'click', @caption.seekPlayer
|
||||
|
||||
it 'set rendered to true', ->
|
||||
expect(@caption.rendered).toBeTruthy()
|
||||
|
||||
describe 'when on a touch-based device', ->
|
||||
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice.andReturn true
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
|
||||
it 'show explaination message', ->
|
||||
expect($('.subtitles li')).toHaveHtml "Caption will be displayed when you start playing the video."
|
||||
|
||||
it 'does not set rendered to true', ->
|
||||
expect(@caption.rendered).toBeFalsy()
|
||||
|
||||
describe 'mouse movement', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
window.setTimeout.andReturn(100)
|
||||
spyOn window, 'clearTimeout'
|
||||
|
||||
describe 'when cursor is outside of the caption box', ->
|
||||
|
||||
beforeEach ->
|
||||
$(window).trigger jQuery.Event 'mousemove'
|
||||
|
||||
it 'does not set freezing timeout', ->
|
||||
expect(@caption.frozen).toBeFalsy()
|
||||
|
||||
describe 'when cursor is in the caption box', ->
|
||||
|
||||
beforeEach ->
|
||||
$('.subtitles').trigger jQuery.Event 'mouseenter'
|
||||
|
||||
it 'set the freezing timeout', ->
|
||||
expect(@caption.frozen).toEqual 100
|
||||
|
||||
describe 'when the cursor is moving', ->
|
||||
beforeEach ->
|
||||
$('.subtitles').trigger jQuery.Event 'mousemove'
|
||||
|
||||
it 'reset the freezing timeout', ->
|
||||
expect(window.clearTimeout).toHaveBeenCalledWith 100
|
||||
|
||||
describe 'when the mouse is scrolling', ->
|
||||
beforeEach ->
|
||||
$('.subtitles').trigger jQuery.Event 'mousewheel'
|
||||
|
||||
it 'reset the freezing timeout', ->
|
||||
expect(window.clearTimeout).toHaveBeenCalledWith 100
|
||||
|
||||
describe 'when cursor is moving out of the caption box', ->
|
||||
beforeEach ->
|
||||
@caption.frozen = 100
|
||||
$.fn.scrollTo.reset()
|
||||
|
||||
describe 'always', ->
|
||||
beforeEach ->
|
||||
$('.subtitles').trigger jQuery.Event 'mouseout'
|
||||
|
||||
it 'reset the freezing timeout', ->
|
||||
expect(window.clearTimeout).toHaveBeenCalledWith 100
|
||||
|
||||
it 'unfreeze the caption', ->
|
||||
expect(@caption.frozen).toBeNull()
|
||||
|
||||
describe 'when the player is playing', ->
|
||||
beforeEach ->
|
||||
@caption.playing = true
|
||||
$('.subtitles li[data-index]:first').addClass 'current'
|
||||
$('.subtitles').trigger jQuery.Event 'mouseout'
|
||||
|
||||
it 'scroll the caption', ->
|
||||
expect($.fn.scrollTo).toHaveBeenCalled()
|
||||
|
||||
describe 'when the player is not playing', ->
|
||||
beforeEach ->
|
||||
@caption.playing = false
|
||||
$('.subtitles').trigger jQuery.Event 'mouseout'
|
||||
|
||||
it 'does not scroll the caption', ->
|
||||
expect($.fn.scrollTo).not.toHaveBeenCalled()
|
||||
|
||||
describe 'search', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
|
||||
it 'return a correct caption index', ->
|
||||
expect(@caption.search(0)).toEqual 0
|
||||
expect(@caption.search(9999)).toEqual 0
|
||||
expect(@caption.search(10000)).toEqual 1
|
||||
expect(@caption.search(15000)).toEqual 1
|
||||
expect(@caption.search(30000)).toEqual 3
|
||||
expect(@caption.search(30001)).toEqual 3
|
||||
|
||||
describe 'play', ->
|
||||
describe 'when the caption was not rendered', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice.andReturn true
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
@caption.play()
|
||||
|
||||
it 'render the caption', ->
|
||||
captionsData = jasmine.stubbedCaption
|
||||
$('.subtitles li[data-index]').each (index, link) =>
|
||||
expect($(link)).toHaveData 'index', index
|
||||
expect($(link)).toHaveData 'start', captionsData.start[index]
|
||||
expect($(link)).toHaveText captionsData.text[index]
|
||||
|
||||
it 'add a padding element to caption', ->
|
||||
expect($('.subtitles li:first')).toBe '.spacing'
|
||||
expect($('.subtitles li:last')).toBe '.spacing'
|
||||
|
||||
it 'bind all the caption link', ->
|
||||
$('.subtitles li[data-index]').each (index, link) =>
|
||||
expect($(link)).toHandleWith 'click', @caption.seekPlayer
|
||||
|
||||
it 'set rendered to true', ->
|
||||
expect(@caption.rendered).toBeTruthy()
|
||||
|
||||
it 'set playing to true', ->
|
||||
expect(@caption.playing).toBeTruthy()
|
||||
|
||||
describe 'pause', ->
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
@caption.playing = true
|
||||
@caption.pause()
|
||||
|
||||
it 'set playing to false', ->
|
||||
expect(@caption.playing).toBeFalsy()
|
||||
|
||||
describe 'updatePlayTime', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
|
||||
describe 'when the video speed is 1.0x', ->
|
||||
beforeEach ->
|
||||
@caption.currentSpeed = '1.0'
|
||||
@caption.updatePlayTime 25.000
|
||||
|
||||
it 'search the caption based on time', ->
|
||||
expect(@caption.currentIndex).toEqual 2
|
||||
|
||||
describe 'when the video speed is not 1.0x', ->
|
||||
beforeEach ->
|
||||
@caption.currentSpeed = '0.75'
|
||||
@caption.updatePlayTime 25.000
|
||||
|
||||
it 'search the caption based on 1.0x speed', ->
|
||||
expect(@caption.currentIndex).toEqual 1
|
||||
|
||||
describe 'when the index is not the same', ->
|
||||
beforeEach ->
|
||||
@caption.currentIndex = 1
|
||||
$('.subtitles li[data-index=1]').addClass 'current'
|
||||
@caption.updatePlayTime 25.000
|
||||
|
||||
it 'deactivate the previous caption', ->
|
||||
expect($('.subtitles li[data-index=1]')).not.toHaveClass 'current'
|
||||
|
||||
it 'activate new caption', ->
|
||||
expect($('.subtitles li[data-index=2]')).toHaveClass 'current'
|
||||
|
||||
it 'save new index', ->
|
||||
expect(@caption.currentIndex).toEqual 2
|
||||
|
||||
it 'scroll caption to new position', ->
|
||||
expect($.fn.scrollTo).toHaveBeenCalled()
|
||||
|
||||
describe 'when the index is the same', ->
|
||||
beforeEach ->
|
||||
@caption.currentIndex = 1
|
||||
$('.subtitles li[data-index=1]').addClass 'current'
|
||||
@caption.updatePlayTime 15.000
|
||||
|
||||
it 'does not change current subtitle', ->
|
||||
expect($('.subtitles li[data-index=1]')).toHaveClass 'current'
|
||||
|
||||
describe 'resize', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
$('.subtitles li[data-index=1]').addClass 'current'
|
||||
@caption.resize()
|
||||
|
||||
it 'set the height of caption container', ->
|
||||
expect(parseInt($('.subtitles').css('maxHeight'))).toBeCloseTo $('.video-wrapper').height(), 2
|
||||
|
||||
it 'set the height of caption spacing', ->
|
||||
expect(Math.abs(parseInt($('.subtitles .spacing:first').css('height')) - @caption.topSpacingHeight())).toBeLessThan 1
|
||||
expect(Math.abs(parseInt($('.subtitles .spacing:last').css('height')) - @caption.bottomSpacingHeight())).toBeLessThan 1
|
||||
|
||||
|
||||
it 'scroll caption to new position', ->
|
||||
expect($.fn.scrollTo).toHaveBeenCalled()
|
||||
|
||||
describe 'scrollCaption', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
|
||||
describe 'when frozen', ->
|
||||
beforeEach ->
|
||||
@caption.frozen = true
|
||||
$('.subtitles li[data-index=1]').addClass 'current'
|
||||
@caption.scrollCaption()
|
||||
|
||||
it 'does not scroll the caption', ->
|
||||
expect($.fn.scrollTo).not.toHaveBeenCalled()
|
||||
|
||||
describe 'when not frozen', ->
|
||||
beforeEach ->
|
||||
@caption.frozen = false
|
||||
|
||||
describe 'when there is no current caption', ->
|
||||
beforeEach ->
|
||||
@caption.scrollCaption()
|
||||
|
||||
it 'does not scroll the caption', ->
|
||||
expect($.fn.scrollTo).not.toHaveBeenCalled()
|
||||
|
||||
describe 'when there is a current caption', ->
|
||||
beforeEach ->
|
||||
$('.subtitles li[data-index=1]').addClass 'current'
|
||||
@caption.scrollCaption()
|
||||
|
||||
it 'scroll to current caption', ->
|
||||
expect($.fn.scrollTo).toHaveBeenCalledWith $('.subtitles .current:first', @caption.el),
|
||||
offset: - ($('.video-wrapper').height() / 2 - $('.subtitles .current:first').height() / 2)
|
||||
|
||||
describe 'seekPlayer', ->
|
||||
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
@time = null
|
||||
$(@caption).bind 'seek', (event, time) => @time = time
|
||||
|
||||
describe 'when the video speed is 1.0x', ->
|
||||
beforeEach ->
|
||||
@caption.currentSpeed = '1.0'
|
||||
$('.subtitles li[data-start="30000"]').trigger('click')
|
||||
|
||||
it 'trigger seek event with the correct time', ->
|
||||
expect(@time).toEqual 30.000
|
||||
|
||||
describe 'when the video speed is not 1.0x', ->
|
||||
beforeEach ->
|
||||
@caption.currentSpeed = '0.75'
|
||||
$('.subtitles li[data-start="30000"]').trigger('click')
|
||||
|
||||
it 'trigger seek event with the correct time', ->
|
||||
expect(@time).toEqual 40.000
|
||||
|
||||
describe 'toggle', ->
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@caption = @player.caption
|
||||
$('.subtitles li[data-index=1]').addClass 'current'
|
||||
|
||||
describe 'when the caption is visible', ->
|
||||
beforeEach ->
|
||||
@caption.el.removeClass 'closed'
|
||||
@caption.toggle jQuery.Event('click')
|
||||
|
||||
it 'hide the caption', ->
|
||||
expect(@caption.el).toHaveClass 'closed'
|
||||
|
||||
describe 'when the caption is hidden', ->
|
||||
beforeEach ->
|
||||
@caption.el.addClass 'closed'
|
||||
@caption.toggle jQuery.Event('click')
|
||||
|
||||
it 'show the caption', ->
|
||||
expect(@caption.el).not.toHaveClass 'closed'
|
||||
|
||||
it 'scroll the caption', ->
|
||||
expect($.fn.scrollTo).toHaveBeenCalled()
|
||||
@@ -0,0 +1,103 @@
|
||||
describe 'VideoControlAlpha', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
|
||||
loadFixtures 'videoalpha.html'
|
||||
$('.video-controls').html ''
|
||||
|
||||
describe 'constructor', ->
|
||||
|
||||
it 'render the video controls', ->
|
||||
@control = new window.VideoControlAlpha(el: $('.video-controls'))
|
||||
expect($('.video-controls')).toContain
|
||||
['.slider', 'ul.vcr', 'a.play', '.vidtime', '.add-fullscreen'].join(',')
|
||||
expect($('.video-controls').find('.vidtime')).toHaveText '0:00 / 0:00'
|
||||
|
||||
it 'bind the playback button', ->
|
||||
@control = new window.VideoControlAlpha(el: $('.video-controls'))
|
||||
expect($('.video_control')).toHandleWith 'click', @control.togglePlayback
|
||||
|
||||
describe 'when on a touch based device', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice.andReturn true
|
||||
@control = new window.VideoControlAlpha(el: $('.video-controls'))
|
||||
|
||||
it 'does not add the play class to video control', ->
|
||||
expect($('.video_control')).not.toHaveClass 'play'
|
||||
expect($('.video_control')).not.toHaveHtml 'Play'
|
||||
|
||||
|
||||
describe 'when on a non-touch based device', ->
|
||||
|
||||
beforeEach ->
|
||||
@control = new window.VideoControlAlpha(el: $('.video-controls'))
|
||||
|
||||
it 'add the play class to video control', ->
|
||||
expect($('.video_control')).toHaveClass 'play'
|
||||
expect($('.video_control')).toHaveHtml 'Play'
|
||||
|
||||
describe 'play', ->
|
||||
|
||||
beforeEach ->
|
||||
@control = new window.VideoControlAlpha(el: $('.video-controls'))
|
||||
@control.play()
|
||||
|
||||
it 'switch playback button to play state', ->
|
||||
expect($('.video_control')).not.toHaveClass 'play'
|
||||
expect($('.video_control')).toHaveClass 'pause'
|
||||
expect($('.video_control')).toHaveHtml 'Pause'
|
||||
|
||||
describe 'pause', ->
|
||||
|
||||
beforeEach ->
|
||||
@control = new window.VideoControlAlpha(el: $('.video-controls'))
|
||||
@control.pause()
|
||||
|
||||
it 'switch playback button to pause state', ->
|
||||
expect($('.video_control')).not.toHaveClass 'pause'
|
||||
expect($('.video_control')).toHaveClass 'play'
|
||||
expect($('.video_control')).toHaveHtml 'Play'
|
||||
|
||||
describe 'togglePlayback', ->
|
||||
|
||||
beforeEach ->
|
||||
@control = new window.VideoControlAlpha(el: $('.video-controls'))
|
||||
|
||||
describe 'when the control does not have play or pause class', ->
|
||||
beforeEach ->
|
||||
$('.video_control').removeClass('play').removeClass('pause')
|
||||
|
||||
describe 'when the video is playing', ->
|
||||
beforeEach ->
|
||||
$('.video_control').addClass('play')
|
||||
spyOnEvent @control, 'pause'
|
||||
@control.togglePlayback jQuery.Event('click')
|
||||
|
||||
it 'does not trigger the pause event', ->
|
||||
expect('pause').not.toHaveBeenTriggeredOn @control
|
||||
|
||||
describe 'when the video is paused', ->
|
||||
beforeEach ->
|
||||
$('.video_control').addClass('pause')
|
||||
spyOnEvent @control, 'play'
|
||||
@control.togglePlayback jQuery.Event('click')
|
||||
|
||||
it 'does not trigger the play event', ->
|
||||
expect('play').not.toHaveBeenTriggeredOn @control
|
||||
|
||||
describe 'when the video is playing', ->
|
||||
beforeEach ->
|
||||
spyOnEvent @control, 'pause'
|
||||
$('.video_control').addClass 'pause'
|
||||
@control.togglePlayback jQuery.Event('click')
|
||||
|
||||
it 'trigger the pause event', ->
|
||||
expect('pause').toHaveBeenTriggeredOn @control
|
||||
|
||||
describe 'when the video is paused', ->
|
||||
beforeEach ->
|
||||
spyOnEvent @control, 'play'
|
||||
$('.video_control').addClass 'play'
|
||||
@control.togglePlayback jQuery.Event('click')
|
||||
|
||||
it 'trigger the play event', ->
|
||||
expect('play').toHaveBeenTriggeredOn @control
|
||||
@@ -0,0 +1,464 @@
|
||||
describe 'VideoPlayerAlpha', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
|
||||
# It tries to call methods of VideoProgressSlider on Spy
|
||||
for part in ['VideoCaptionAlpha', 'VideoSpeedControlAlpha', 'VideoVolumeControlAlpha', 'VideoProgressSliderAlpha', 'VideoControlAlpha']
|
||||
spyOn(window[part].prototype, 'initialize').andCallThrough()
|
||||
jasmine.stubVideoPlayerAlpha @, [], false
|
||||
|
||||
afterEach ->
|
||||
YT.Player = undefined
|
||||
|
||||
describe 'constructor', ->
|
||||
beforeEach ->
|
||||
spyOn YT, 'Player'
|
||||
$.fn.qtip.andCallFake ->
|
||||
$(this).data('qtip', true)
|
||||
$('.video').append $('<div class="add-fullscreen" /><div class="hide-subtitles" />')
|
||||
|
||||
describe 'always', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
|
||||
it 'instanticate current time to zero', ->
|
||||
expect(@player.currentTime).toEqual 0
|
||||
|
||||
it 'set the element', ->
|
||||
expect(@player.el).toHaveId 'video_id'
|
||||
|
||||
it 'create video control', ->
|
||||
expect(window.VideoControlAlpha.prototype.initialize).toHaveBeenCalled()
|
||||
expect(@player.control).toBeDefined()
|
||||
expect(@player.control.el).toBe $('.video-controls', @player.el)
|
||||
|
||||
it 'create video caption', ->
|
||||
expect(window.VideoCaptionAlpha.prototype.initialize).toHaveBeenCalled()
|
||||
expect(@player.caption).toBeDefined()
|
||||
expect(@player.caption.el).toBe @player.el
|
||||
expect(@player.caption.youtubeId).toEqual 'normalSpeedYoutubeId'
|
||||
expect(@player.caption.currentSpeed).toEqual '1.0'
|
||||
expect(@player.caption.captionAssetPath).toEqual '/static/subs/'
|
||||
|
||||
it 'create video speed control', ->
|
||||
expect(window.VideoSpeedControlAlpha.prototype.initialize).toHaveBeenCalled()
|
||||
expect(@player.speedControl).toBeDefined()
|
||||
expect(@player.speedControl.el).toBe $('.secondary-controls', @player.el)
|
||||
expect(@player.speedControl.speeds).toEqual ['0.75', '1.0']
|
||||
expect(@player.speedControl.currentSpeed).toEqual '1.0'
|
||||
|
||||
it 'create video progress slider', ->
|
||||
expect(window.VideoSpeedControlAlpha.prototype.initialize).toHaveBeenCalled()
|
||||
expect(@player.progressSlider).toBeDefined()
|
||||
expect(@player.progressSlider.el).toBe $('.slider', @player.el)
|
||||
|
||||
it 'create Youtube player', ->
|
||||
expect(YT.Player).toHaveBeenCalledWith('id', {
|
||||
playerVars:
|
||||
controls: 0
|
||||
wmode: 'transparent'
|
||||
rel: 0
|
||||
showinfo: 0
|
||||
enablejsapi: 1
|
||||
modestbranding: 1
|
||||
html5: 1
|
||||
videoId: 'normalSpeedYoutubeId'
|
||||
events:
|
||||
onReady: @player.onReady
|
||||
onStateChange: @player.onStateChange
|
||||
onPlaybackQualityChange: @player.onPlaybackQualityChange
|
||||
})
|
||||
|
||||
it 'bind to video control play event', ->
|
||||
expect($(@player.control)).toHandleWith 'play', @player.play
|
||||
|
||||
it 'bind to video control pause event', ->
|
||||
expect($(@player.control)).toHandleWith 'pause', @player.pause
|
||||
|
||||
it 'bind to video caption seek event', ->
|
||||
expect($(@player.caption)).toHandleWith 'seek', @player.onSeek
|
||||
|
||||
it 'bind to video speed control speedChange event', ->
|
||||
expect($(@player.speedControl)).toHandleWith 'speedChange', @player.onSpeedChange
|
||||
|
||||
it 'bind to video progress slider seek event', ->
|
||||
expect($(@player.progressSlider)).toHandleWith 'seek', @player.onSeek
|
||||
|
||||
it 'bind to video volume control volumeChange event', ->
|
||||
expect($(@player.volumeControl)).toHandleWith 'volumeChange', @player.onVolumeChange
|
||||
|
||||
it 'bind to key press', ->
|
||||
expect($(document.documentElement)).toHandleWith 'keyup', @player.bindExitFullScreen
|
||||
|
||||
it 'bind to fullscreen switching button', ->
|
||||
expect($('.add-fullscreen')).toHandleWith 'click', @player.toggleFullScreen
|
||||
|
||||
describe 'when not on a touch based device', ->
|
||||
beforeEach ->
|
||||
$('.add-fullscreen, .hide-subtitles').removeData 'qtip'
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
|
||||
it 'add the tooltip to fullscreen and subtitle button', ->
|
||||
expect($('.add-fullscreen')).toHaveData 'qtip'
|
||||
expect($('.hide-subtitles')).toHaveData 'qtip'
|
||||
|
||||
it 'create video volume control', ->
|
||||
expect(window.VideoVolumeControlAlpha.prototype.initialize).toHaveBeenCalled()
|
||||
expect(@player.volumeControl).toBeDefined()
|
||||
expect(@player.volumeControl.el).toBe $('.secondary-controls', @player.el)
|
||||
|
||||
describe 'when on a touch based device', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice.andReturn true
|
||||
$('.add-fullscreen, .hide-subtitles').removeData 'qtip'
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
|
||||
it 'does not add the tooltip to fullscreen and subtitle button', ->
|
||||
expect($('.add-fullscreen')).not.toHaveData 'qtip'
|
||||
expect($('.hide-subtitles')).not.toHaveData 'qtip'
|
||||
|
||||
it 'does not create video volume control', ->
|
||||
expect(window.VideoVolumeControlAlpha.prototype.initialize).not.toHaveBeenCalled()
|
||||
expect(@player.volumeControl).not.toBeDefined()
|
||||
|
||||
describe 'onReady', ->
|
||||
beforeEach ->
|
||||
@video.embed()
|
||||
@player = @video.player
|
||||
spyOnEvent @player, 'ready'
|
||||
spyOnEvent @player, 'updatePlayTime'
|
||||
@player.onReady()
|
||||
|
||||
describe 'when not on a touch based device', ->
|
||||
beforeEach ->
|
||||
spyOn @player, 'play'
|
||||
@player.onReady()
|
||||
|
||||
it 'autoplay the first video', ->
|
||||
expect(@player.play).toHaveBeenCalled()
|
||||
|
||||
describe 'when on a touch based device', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice.andReturn true
|
||||
spyOn @player, 'play'
|
||||
@player.onReady()
|
||||
|
||||
it 'does not autoplay the first video', ->
|
||||
expect(@player.play).not.toHaveBeenCalled()
|
||||
|
||||
describe 'onStateChange', ->
|
||||
|
||||
describe 'when the video is unstarted', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn @player.control, 'pause'
|
||||
@player.caption.pause = jasmine.createSpy('VideoCaptionAlpha.pause')
|
||||
@player.onStateChange data: YT.PlayerState.UNSTARTED
|
||||
|
||||
it 'pause the video control', ->
|
||||
expect(@player.control.pause).toHaveBeenCalled()
|
||||
|
||||
it 'pause the video caption', ->
|
||||
expect(@player.caption.pause).toHaveBeenCalled()
|
||||
|
||||
describe 'when the video is playing', ->
|
||||
beforeEach ->
|
||||
@anotherPlayer = jasmine.createSpyObj 'AnotherPlayer', ['onPause']
|
||||
window.OldVideoPlayerAlpha = @anotherPlayer
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn @video, 'log'
|
||||
spyOn(window, 'setInterval').andReturn 100
|
||||
spyOn @player.control, 'play'
|
||||
@player.caption.play = jasmine.createSpy('VideoCaptionAlpha.play')
|
||||
@player.progressSlider.play = jasmine.createSpy('VideoProgressSliderAlpha.play')
|
||||
@player.player.getVideoEmbedCode.andReturn 'embedCode'
|
||||
@player.onStateChange data: YT.PlayerState.PLAYING
|
||||
|
||||
it 'log the play_video event', ->
|
||||
expect(@video.log).toHaveBeenCalledWith 'play_video'
|
||||
|
||||
it 'pause other video player', ->
|
||||
expect(@anotherPlayer.onPause).toHaveBeenCalled()
|
||||
|
||||
it 'set current video player as active player', ->
|
||||
expect(window.OldVideoPlayerAlpha).toEqual @player
|
||||
|
||||
it 'set update interval', ->
|
||||
expect(window.setInterval).toHaveBeenCalledWith @player.update, 200
|
||||
expect(@player.player.interval).toEqual 100
|
||||
|
||||
it 'play the video control', ->
|
||||
expect(@player.control.play).toHaveBeenCalled()
|
||||
|
||||
it 'play the video caption', ->
|
||||
expect(@player.caption.play).toHaveBeenCalled()
|
||||
|
||||
it 'play the video progress slider', ->
|
||||
expect(@player.progressSlider.play).toHaveBeenCalled()
|
||||
|
||||
describe 'when the video is paused', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn @video, 'log'
|
||||
spyOn window, 'clearInterval'
|
||||
spyOn @player.control, 'pause'
|
||||
@player.caption.pause = jasmine.createSpy('VideoCaptionAlpha.pause')
|
||||
@player.player.interval = 100
|
||||
@player.player.getVideoEmbedCode.andReturn 'embedCode'
|
||||
@player.onStateChange data: YT.PlayerState.PAUSED
|
||||
|
||||
it 'log the pause_video event', ->
|
||||
expect(@video.log).toHaveBeenCalledWith 'pause_video'
|
||||
|
||||
it 'clear update interval', ->
|
||||
expect(window.clearInterval).toHaveBeenCalledWith 100
|
||||
expect(@player.player.interval).toBeNull()
|
||||
|
||||
it 'pause the video control', ->
|
||||
expect(@player.control.pause).toHaveBeenCalled()
|
||||
|
||||
it 'pause the video caption', ->
|
||||
expect(@player.caption.pause).toHaveBeenCalled()
|
||||
|
||||
describe 'when the video is ended', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn @player.control, 'pause'
|
||||
@player.caption.pause = jasmine.createSpy('VideoCaptionAlpha.pause')
|
||||
@player.onStateChange data: YT.PlayerState.ENDED
|
||||
|
||||
it 'pause the video control', ->
|
||||
expect(@player.control.pause).toHaveBeenCalled()
|
||||
|
||||
it 'pause the video caption', ->
|
||||
expect(@player.caption.pause).toHaveBeenCalled()
|
||||
|
||||
describe 'onSeek', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn window, 'clearInterval'
|
||||
@player.player.interval = 100
|
||||
spyOn @player, 'updatePlayTime'
|
||||
@player.onSeek {}, 60
|
||||
|
||||
it 'seek the player', ->
|
||||
expect(@player.player.seekTo).toHaveBeenCalledWith 60, true
|
||||
|
||||
it 'call updatePlayTime on player', ->
|
||||
expect(@player.updatePlayTime).toHaveBeenCalledWith 60
|
||||
|
||||
describe 'when the player is playing', ->
|
||||
beforeEach ->
|
||||
@player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
|
||||
@player.onSeek {}, 60
|
||||
|
||||
it 'reset the update interval', ->
|
||||
expect(window.clearInterval).toHaveBeenCalledWith 100
|
||||
|
||||
describe 'when the player is not playing', ->
|
||||
beforeEach ->
|
||||
@player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
|
||||
@player.onSeek {}, 60
|
||||
|
||||
it 'set the current time', ->
|
||||
expect(@player.currentTime).toEqual 60
|
||||
|
||||
describe 'onSpeedChange', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
@player.currentTime = 60
|
||||
spyOn @player, 'updatePlayTime'
|
||||
spyOn(@video, 'setSpeed').andCallThrough()
|
||||
|
||||
describe 'always', ->
|
||||
beforeEach ->
|
||||
@player.onSpeedChange {}, '0.75', false
|
||||
|
||||
it 'convert the current time to the new speed', ->
|
||||
expect(@player.currentTime).toEqual '80.000'
|
||||
|
||||
it 'set video speed to the new speed', ->
|
||||
expect(@video.setSpeed).toHaveBeenCalledWith '0.75', false
|
||||
|
||||
it 'tell video caption that the speed has changed', ->
|
||||
expect(@player.caption.currentSpeed).toEqual '0.75'
|
||||
|
||||
describe 'when the video is playing', ->
|
||||
beforeEach ->
|
||||
@player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
|
||||
@player.onSpeedChange {}, '0.75'
|
||||
|
||||
it 'load the video', ->
|
||||
expect(@player.player.loadVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
|
||||
|
||||
it 'trigger updatePlayTime event', ->
|
||||
expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
|
||||
|
||||
describe 'when the video is not playing', ->
|
||||
beforeEach ->
|
||||
@player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
|
||||
@player.onSpeedChange {}, '0.75'
|
||||
|
||||
it 'cue the video', ->
|
||||
expect(@player.player.cueVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
|
||||
|
||||
it 'trigger updatePlayTime event', ->
|
||||
expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
|
||||
|
||||
describe 'onVolumeChange', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
@player.onVolumeChange undefined, 60
|
||||
|
||||
it 'set the volume on player', ->
|
||||
expect(@player.player.setVolume).toHaveBeenCalledWith 60
|
||||
|
||||
describe 'update', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn @player, 'updatePlayTime'
|
||||
|
||||
describe 'when the current time is unavailable from the player', ->
|
||||
beforeEach ->
|
||||
@player.player.getCurrentTime.andReturn undefined
|
||||
@player.update()
|
||||
|
||||
it 'does not trigger updatePlayTime event', ->
|
||||
expect(@player.updatePlayTime).not.toHaveBeenCalled()
|
||||
|
||||
describe 'when the current time is available from the player', ->
|
||||
beforeEach ->
|
||||
@player.player.getCurrentTime.andReturn 60
|
||||
@player.update()
|
||||
|
||||
it 'trigger updatePlayTime event', ->
|
||||
expect(@player.updatePlayTime).toHaveBeenCalledWith(60)
|
||||
|
||||
describe 'updatePlayTime', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn(@video, 'getDuration').andReturn 1800
|
||||
@player.caption.updatePlayTime = jasmine.createSpy('VideoCaptionAlpha.updatePlayTime')
|
||||
@player.progressSlider.updatePlayTime = jasmine.createSpy('VideoProgressSliderAlpha.updatePlayTime')
|
||||
@player.updatePlayTime 60
|
||||
|
||||
it 'update the video playback time', ->
|
||||
expect($('.vidtime')).toHaveHtml '1:00 / 30:00'
|
||||
|
||||
it 'update the playback time on caption', ->
|
||||
expect(@player.caption.updatePlayTime).toHaveBeenCalledWith 60
|
||||
|
||||
it 'update the playback time on progress slider', ->
|
||||
expect(@player.progressSlider.updatePlayTime).toHaveBeenCalledWith 60, 1800
|
||||
|
||||
describe 'toggleFullScreen', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
@player.caption.resize = jasmine.createSpy('VideoCaptionAlpha.resize')
|
||||
|
||||
describe 'when the video player is not full screen', ->
|
||||
beforeEach ->
|
||||
@player.el.removeClass 'fullscreen'
|
||||
@player.toggleFullScreen(jQuery.Event("click"))
|
||||
|
||||
it 'replace the full screen button tooltip', ->
|
||||
expect($('.add-fullscreen')).toHaveAttr 'title', 'Exit fill browser'
|
||||
|
||||
it 'add the fullscreen class', ->
|
||||
expect(@player.el).toHaveClass 'fullscreen'
|
||||
|
||||
it 'tell VideoCaption to resize', ->
|
||||
expect(@player.caption.resize).toHaveBeenCalled()
|
||||
|
||||
describe 'when the video player already full screen', ->
|
||||
beforeEach ->
|
||||
@player.el.addClass 'fullscreen'
|
||||
@player.toggleFullScreen(jQuery.Event("click"))
|
||||
|
||||
it 'replace the full screen button tooltip', ->
|
||||
expect($('.add-fullscreen')).toHaveAttr 'title', 'Fill browser'
|
||||
|
||||
it 'remove exit full screen button', ->
|
||||
expect(@player.el).not.toContain 'a.exit'
|
||||
|
||||
it 'remove the fullscreen class', ->
|
||||
expect(@player.el).not.toHaveClass 'fullscreen'
|
||||
|
||||
it 'tell VideoCaption to resize', ->
|
||||
expect(@player.caption.resize).toHaveBeenCalled()
|
||||
|
||||
describe 'play', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
|
||||
describe 'when the player is not ready', ->
|
||||
beforeEach ->
|
||||
@player.player.playVideo = undefined
|
||||
@player.play()
|
||||
|
||||
it 'does nothing', ->
|
||||
expect(@player.player.playVideo).toBeUndefined()
|
||||
|
||||
describe 'when the player is ready', ->
|
||||
beforeEach ->
|
||||
@player.player.playVideo.andReturn true
|
||||
@player.play()
|
||||
|
||||
it 'delegate to the Youtube player', ->
|
||||
expect(@player.player.playVideo).toHaveBeenCalled()
|
||||
|
||||
describe 'isPlaying', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
|
||||
describe 'when the video is playing', ->
|
||||
beforeEach ->
|
||||
@player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
|
||||
|
||||
it 'return true', ->
|
||||
expect(@player.isPlaying()).toBeTruthy()
|
||||
|
||||
describe 'when the video is not playing', ->
|
||||
beforeEach ->
|
||||
@player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
|
||||
|
||||
it 'return false', ->
|
||||
expect(@player.isPlaying()).toBeFalsy()
|
||||
|
||||
describe 'pause', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
@player.pause()
|
||||
|
||||
it 'delegate to the Youtube player', ->
|
||||
expect(@player.player.pauseVideo).toHaveBeenCalled()
|
||||
|
||||
describe 'duration', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
spyOn @video, 'getDuration'
|
||||
@player.duration()
|
||||
|
||||
it 'delegate to the video', ->
|
||||
expect(@video.getDuration).toHaveBeenCalled()
|
||||
|
||||
describe 'currentSpeed', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
@video.speed = '3.0'
|
||||
|
||||
it 'delegate to the video', ->
|
||||
expect(@player.currentSpeed()).toEqual '3.0'
|
||||
|
||||
describe 'volume', ->
|
||||
beforeEach ->
|
||||
@player = new VideoPlayerAlpha video: @video
|
||||
@player.player.getVolume.andReturn 42
|
||||
|
||||
describe 'without value', ->
|
||||
it 'return current volume', ->
|
||||
expect(@player.volume()).toEqual 42
|
||||
|
||||
describe 'with value', ->
|
||||
it 'set player volume', ->
|
||||
@player.volume(60)
|
||||
expect(@player.player.setVolume).toHaveBeenCalledWith(60)
|
||||
@@ -0,0 +1,169 @@
|
||||
describe 'VideoProgressSliderAlpha', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
|
||||
|
||||
describe 'constructor', ->
|
||||
describe 'on a non-touch based device', ->
|
||||
beforeEach ->
|
||||
spyOn($.fn, 'slider').andCallThrough()
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
|
||||
it 'build the slider', ->
|
||||
expect(@progressSlider.slider).toBe '.slider'
|
||||
expect($.fn.slider).toHaveBeenCalledWith
|
||||
range: 'min'
|
||||
change: @progressSlider.onChange
|
||||
slide: @progressSlider.onSlide
|
||||
stop: @progressSlider.onStop
|
||||
|
||||
it 'build the seek handle', ->
|
||||
expect(@progressSlider.handle).toBe '.slider .ui-slider-handle'
|
||||
expect($.fn.qtip).toHaveBeenCalledWith
|
||||
content: "0:00"
|
||||
position:
|
||||
my: 'bottom center'
|
||||
at: 'top center'
|
||||
container: @progressSlider.handle
|
||||
hide:
|
||||
delay: 700
|
||||
style:
|
||||
classes: 'ui-tooltip-slider'
|
||||
widget: true
|
||||
|
||||
describe 'on a touch-based device', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice.andReturn true
|
||||
spyOn($.fn, 'slider').andCallThrough()
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
|
||||
it 'does not build the slider', ->
|
||||
expect(@progressSlider.slider).toBeUndefined
|
||||
expect($.fn.slider).not.toHaveBeenCalled()
|
||||
|
||||
describe 'play', ->
|
||||
beforeEach ->
|
||||
spyOn(VideoProgressSliderAlpha.prototype, 'buildSlider').andCallThrough()
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
|
||||
describe 'when the slider was already built', ->
|
||||
|
||||
beforeEach ->
|
||||
@progressSlider.play()
|
||||
|
||||
it 'does not build the slider', ->
|
||||
expect(@progressSlider.buildSlider.calls.length).toEqual 1
|
||||
|
||||
describe 'when the slider was not already built', ->
|
||||
beforeEach ->
|
||||
spyOn($.fn, 'slider').andCallThrough()
|
||||
@progressSlider.slider = null
|
||||
@progressSlider.play()
|
||||
|
||||
it 'build the slider', ->
|
||||
expect(@progressSlider.slider).toBe '.slider'
|
||||
expect($.fn.slider).toHaveBeenCalledWith
|
||||
range: 'min'
|
||||
change: @progressSlider.onChange
|
||||
slide: @progressSlider.onSlide
|
||||
stop: @progressSlider.onStop
|
||||
|
||||
it 'build the seek handle', ->
|
||||
expect(@progressSlider.handle).toBe '.ui-slider-handle'
|
||||
expect($.fn.qtip).toHaveBeenCalledWith
|
||||
content: "0:00"
|
||||
position:
|
||||
my: 'bottom center'
|
||||
at: 'top center'
|
||||
container: @progressSlider.handle
|
||||
hide:
|
||||
delay: 700
|
||||
style:
|
||||
classes: 'ui-tooltip-slider'
|
||||
widget: true
|
||||
|
||||
describe 'updatePlayTime', ->
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
|
||||
describe 'when frozen', ->
|
||||
beforeEach ->
|
||||
spyOn($.fn, 'slider').andCallThrough()
|
||||
@progressSlider.frozen = true
|
||||
@progressSlider.updatePlayTime 20, 120
|
||||
|
||||
it 'does not update the slider', ->
|
||||
expect($.fn.slider).not.toHaveBeenCalled()
|
||||
|
||||
describe 'when not frozen', ->
|
||||
beforeEach ->
|
||||
spyOn($.fn, 'slider').andCallThrough()
|
||||
@progressSlider.frozen = false
|
||||
@progressSlider.updatePlayTime 20, 120
|
||||
|
||||
it 'update the max value of the slider', ->
|
||||
expect($.fn.slider).toHaveBeenCalledWith 'option', 'max', 120
|
||||
|
||||
it 'update current value of the slider', ->
|
||||
expect($.fn.slider).toHaveBeenCalledWith 'value', 20
|
||||
|
||||
describe 'onSlide', ->
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
@time = null
|
||||
$(@progressSlider).bind 'seek', (event, time) => @time = time
|
||||
spyOnEvent @progressSlider, 'seek'
|
||||
@progressSlider.onSlide {}, value: 20
|
||||
|
||||
it 'freeze the slider', ->
|
||||
expect(@progressSlider.frozen).toBeTruthy()
|
||||
|
||||
it 'update the tooltip', ->
|
||||
expect($.fn.qtip).toHaveBeenCalled()
|
||||
|
||||
it 'trigger seek event', ->
|
||||
expect('seek').toHaveBeenTriggeredOn @progressSlider
|
||||
expect(@time).toEqual 20
|
||||
|
||||
describe 'onChange', ->
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
@progressSlider.onChange {}, value: 20
|
||||
|
||||
it 'update the tooltip', ->
|
||||
expect($.fn.qtip).toHaveBeenCalled()
|
||||
|
||||
describe 'onStop', ->
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
@time = null
|
||||
$(@progressSlider).bind 'seek', (event, time) => @time = time
|
||||
spyOnEvent @progressSlider, 'seek'
|
||||
@progressSlider.onStop {}, value: 20
|
||||
|
||||
it 'freeze the slider', ->
|
||||
expect(@progressSlider.frozen).toBeTruthy()
|
||||
|
||||
it 'trigger seek event', ->
|
||||
expect('seek').toHaveBeenTriggeredOn @progressSlider
|
||||
expect(@time).toEqual 20
|
||||
|
||||
it 'set timeout to unfreeze the slider', ->
|
||||
expect(window.setTimeout).toHaveBeenCalledWith jasmine.any(Function), 200
|
||||
window.setTimeout.mostRecentCall.args[0]()
|
||||
expect(@progressSlider.frozen).toBeFalsy()
|
||||
|
||||
describe 'updateTooltip', ->
|
||||
beforeEach ->
|
||||
@player = jasmine.stubVideoPlayerAlpha @
|
||||
@progressSlider = @player.progressSlider
|
||||
@progressSlider.updateTooltip 90
|
||||
|
||||
it 'set the tooltip value', ->
|
||||
expect($.fn.qtip).toHaveBeenCalledWith 'option', 'content.text', '1:30'
|
||||
@@ -0,0 +1,91 @@
|
||||
describe 'VideoSpeedControlAlpha', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
|
||||
jasmine.stubVideoPlayerAlpha @
|
||||
$('.speeds').remove()
|
||||
|
||||
describe 'constructor', ->
|
||||
describe 'always', ->
|
||||
beforeEach ->
|
||||
@speedControl = new VideoSpeedControlAlpha el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
|
||||
|
||||
it 'add the video speed control to player', ->
|
||||
secondaryControls = $('.secondary-controls')
|
||||
li = secondaryControls.find('.video_speeds li')
|
||||
expect(secondaryControls).toContain '.speeds'
|
||||
expect(secondaryControls).toContain '.video_speeds'
|
||||
expect(secondaryControls.find('p.active').text()).toBe '1.0x'
|
||||
expect(li.filter('.active')).toHaveData 'speed', @speedControl.currentSpeed
|
||||
expect(li.length).toBe @speedControl.speeds.length
|
||||
$.each li.toArray().reverse(), (index, link) =>
|
||||
expect($(link)).toHaveData 'speed', @speedControl.speeds[index]
|
||||
expect($(link).find('a').text()).toBe @speedControl.speeds[index] + 'x'
|
||||
|
||||
it 'bind to change video speed link', ->
|
||||
expect($('.video_speeds a')).toHandleWith 'click', @speedControl.changeVideoSpeed
|
||||
|
||||
describe 'when running on touch based device', ->
|
||||
beforeEach ->
|
||||
window.onTouchBasedDevice.andReturn true
|
||||
$('.speeds').removeClass 'open'
|
||||
@speedControl = new VideoSpeedControlAlpha el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
|
||||
|
||||
it 'open the speed toggle on click', ->
|
||||
$('.speeds').click()
|
||||
expect($('.speeds')).toHaveClass 'open'
|
||||
$('.speeds').click()
|
||||
expect($('.speeds')).not.toHaveClass 'open'
|
||||
|
||||
describe 'when running on non-touch based device', ->
|
||||
beforeEach ->
|
||||
$('.speeds').removeClass 'open'
|
||||
@speedControl = new VideoSpeedControlAlpha el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
|
||||
|
||||
it 'open the speed toggle on hover', ->
|
||||
$('.speeds').mouseenter()
|
||||
expect($('.speeds')).toHaveClass 'open'
|
||||
$('.speeds').mouseleave()
|
||||
expect($('.speeds')).not.toHaveClass 'open'
|
||||
|
||||
it 'close the speed toggle on mouse out', ->
|
||||
$('.speeds').mouseenter().mouseleave()
|
||||
expect($('.speeds')).not.toHaveClass 'open'
|
||||
|
||||
it 'close the speed toggle on click', ->
|
||||
$('.speeds').mouseenter().click()
|
||||
expect($('.speeds')).not.toHaveClass 'open'
|
||||
|
||||
describe 'changeVideoSpeed', ->
|
||||
beforeEach ->
|
||||
@speedControl = new VideoSpeedControlAlpha el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
|
||||
@video.setSpeed '1.0'
|
||||
|
||||
describe 'when new speed is the same', ->
|
||||
beforeEach ->
|
||||
spyOnEvent @speedControl, 'speedChange'
|
||||
$('li[data-speed="1.0"] a').click()
|
||||
|
||||
it 'does not trigger speedChange event', ->
|
||||
expect('speedChange').not.toHaveBeenTriggeredOn @speedControl
|
||||
|
||||
describe 'when new speed is not the same', ->
|
||||
beforeEach ->
|
||||
@newSpeed = null
|
||||
$(@speedControl).bind 'speedChange', (event, newSpeed) => @newSpeed = newSpeed
|
||||
spyOnEvent @speedControl, 'speedChange'
|
||||
$('li[data-speed="0.75"] a').click()
|
||||
|
||||
it 'trigger speedChange event', ->
|
||||
expect('speedChange').toHaveBeenTriggeredOn @speedControl
|
||||
expect(@newSpeed).toEqual 0.75
|
||||
|
||||
describe 'onSpeedChange', ->
|
||||
beforeEach ->
|
||||
@speedControl = new VideoSpeedControlAlpha el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
|
||||
$('li[data-speed="1.0"] a').addClass 'active'
|
||||
@speedControl.setSpeed '0.75'
|
||||
|
||||
it 'set the new speed as active', ->
|
||||
expect($('.video_speeds li[data-speed="1.0"]')).not.toHaveClass 'active'
|
||||
expect($('.video_speeds li[data-speed="0.75"]')).toHaveClass 'active'
|
||||
expect($('.speeds p.active')).toHaveHtml '0.75x'
|
||||
@@ -0,0 +1,94 @@
|
||||
describe 'VideoVolumeControlAlpha', ->
|
||||
beforeEach ->
|
||||
jasmine.stubVideoPlayerAlpha @
|
||||
$('.volume').remove()
|
||||
|
||||
describe 'constructor', ->
|
||||
beforeEach ->
|
||||
spyOn($.fn, 'slider')
|
||||
@volumeControl = new VideoVolumeControlAlpha el: $('.secondary-controls')
|
||||
|
||||
it 'initialize currentVolume to 100', ->
|
||||
expect(@volumeControl.currentVolume).toEqual 100
|
||||
|
||||
it 'render the volume control', ->
|
||||
expect($('.secondary-controls').html()).toContain """
|
||||
<div class="volume">
|
||||
<a href="#"></a>
|
||||
<div class="volume-slider-container">
|
||||
<div class="volume-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
it 'create the slider', ->
|
||||
expect($.fn.slider).toHaveBeenCalledWith
|
||||
orientation: "vertical"
|
||||
range: "min"
|
||||
min: 0
|
||||
max: 100
|
||||
value: 100
|
||||
change: @volumeControl.onChange
|
||||
slide: @volumeControl.onChange
|
||||
|
||||
it 'bind the volume control', ->
|
||||
expect($('.volume>a')).toHandleWith 'click', @volumeControl.toggleMute
|
||||
|
||||
expect($('.volume')).not.toHaveClass 'open'
|
||||
$('.volume').mouseenter()
|
||||
expect($('.volume')).toHaveClass 'open'
|
||||
$('.volume').mouseleave()
|
||||
expect($('.volume')).not.toHaveClass 'open'
|
||||
|
||||
describe 'onChange', ->
|
||||
beforeEach ->
|
||||
spyOnEvent @volumeControl, 'volumeChange'
|
||||
@newVolume = undefined
|
||||
@volumeControl = new VideoVolumeControlAlpha el: $('.secondary-controls')
|
||||
$(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
|
||||
|
||||
describe 'when the new volume is more than 0', ->
|
||||
beforeEach ->
|
||||
@volumeControl.onChange undefined, value: 60
|
||||
|
||||
it 'set the player volume', ->
|
||||
expect(@newVolume).toEqual 60
|
||||
|
||||
it 'remote muted class', ->
|
||||
expect($('.volume')).not.toHaveClass 'muted'
|
||||
|
||||
describe 'when the new volume is 0', ->
|
||||
beforeEach ->
|
||||
@volumeControl.onChange undefined, value: 0
|
||||
|
||||
it 'set the player volume', ->
|
||||
expect(@newVolume).toEqual 0
|
||||
|
||||
it 'add muted class', ->
|
||||
expect($('.volume')).toHaveClass 'muted'
|
||||
|
||||
describe 'toggleMute', ->
|
||||
beforeEach ->
|
||||
@newVolume = undefined
|
||||
@volumeControl = new VideoVolumeControlAlpha el: $('.secondary-controls')
|
||||
$(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
|
||||
|
||||
describe 'when the current volume is more than 0', ->
|
||||
beforeEach ->
|
||||
@volumeControl.currentVolume = 60
|
||||
@volumeControl.toggleMute()
|
||||
|
||||
it 'save the previous volume', ->
|
||||
expect(@volumeControl.previousVolume).toEqual 60
|
||||
|
||||
it 'set the player volume', ->
|
||||
expect(@newVolume).toEqual 0
|
||||
|
||||
describe 'when the current volume is 0', ->
|
||||
beforeEach ->
|
||||
@volumeControl.currentVolume = 0
|
||||
@volumeControl.previousVolume = 60
|
||||
@volumeControl.toggleMute()
|
||||
|
||||
it 'set the player volume to previous volume', ->
|
||||
expect(@newVolume).toEqual 60
|
||||
@@ -0,0 +1,153 @@
|
||||
describe 'VideoAlpha', ->
|
||||
metadata = undefined
|
||||
|
||||
beforeEach ->
|
||||
loadFixtures 'videoalpha.html'
|
||||
jasmine.stubRequests()
|
||||
|
||||
@videosDefinition = '0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
|
||||
@slowerSpeedYoutubeId = 'slowerSpeedYoutubeId'
|
||||
@normalSpeedYoutubeId = 'normalSpeedYoutubeId'
|
||||
metadata =
|
||||
slowerSpeedYoutubeId:
|
||||
id: @slowerSpeedYoutubeId
|
||||
duration: 300
|
||||
normalSpeedYoutubeId:
|
||||
id: @normalSpeedYoutubeId
|
||||
duration: 200
|
||||
|
||||
afterEach ->
|
||||
window.OldVideoPlayerAlpha = undefined
|
||||
window.onYouTubePlayerAPIReady = undefined
|
||||
|
||||
describe 'constructor', ->
|
||||
beforeEach ->
|
||||
@stubVideoPlayerAlpha = jasmine.createSpy('VideoPlayerAlpha')
|
||||
$.cookie.andReturn '0.75'
|
||||
|
||||
describe 'by default', ->
|
||||
beforeEach ->
|
||||
spyOn(window.VideoAlpha.prototype, 'fetchMetadata').andCallFake ->
|
||||
@metadata = metadata
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
it 'reset the current video player', ->
|
||||
expect(window.OldVideoPlayerAlpha).toBeUndefined()
|
||||
|
||||
it 'set the elements', ->
|
||||
expect(@video.el).toBe '#video_id'
|
||||
|
||||
it 'parse the videos', ->
|
||||
expect(@video.videos).toEqual
|
||||
'0.75': @slowerSpeedYoutubeId
|
||||
'1.0': @normalSpeedYoutubeId
|
||||
|
||||
it 'fetch the video metadata', ->
|
||||
expect(@video.fetchMetadata).toHaveBeenCalled
|
||||
expect(@video.metadata).toEqual metadata
|
||||
|
||||
it 'parse available video speeds', ->
|
||||
expect(@video.speeds).toEqual ['0.75', '1.0']
|
||||
|
||||
it 'set current video speed via cookie', ->
|
||||
expect(@video.speed).toEqual '0.75'
|
||||
|
||||
it 'store a reference for this video player in the element', ->
|
||||
expect($('.video').data('video')).toEqual @video
|
||||
|
||||
describe 'when the Youtube API is already available', ->
|
||||
beforeEach ->
|
||||
@originalYT = window.YT
|
||||
window.YT = { Player: true }
|
||||
spyOn(window, 'VideoPlayerAlpha').andReturn(@stubVideoPlayerAlpha)
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
|
||||
afterEach ->
|
||||
window.YT = @originalYT
|
||||
|
||||
it 'create the Video Player', ->
|
||||
expect(window.VideoPlayerAlpha).toHaveBeenCalledWith(video: @video)
|
||||
expect(@video.player).toEqual @stubVideoPlayerAlpha
|
||||
|
||||
describe 'when the Youtube API is not ready', ->
|
||||
beforeEach ->
|
||||
@originalYT = window.YT
|
||||
window.YT = {}
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
|
||||
afterEach ->
|
||||
window.YT = @originalYT
|
||||
|
||||
it 'set the callback on the window object', ->
|
||||
expect(window.onYouTubePlayerAPIReady).toEqual jasmine.any(Function)
|
||||
|
||||
describe 'when the Youtube API becoming ready', ->
|
||||
beforeEach ->
|
||||
@originalYT = window.YT
|
||||
window.YT = {}
|
||||
spyOn(window, 'VideoPlayerAlpha').andReturn(@stubVideoPlayerAlpha)
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
window.onYouTubePlayerAPIReady()
|
||||
|
||||
afterEach ->
|
||||
window.YT = @originalYT
|
||||
|
||||
it 'create the Video Player for all video elements', ->
|
||||
expect(window.VideoPlayerAlpha).toHaveBeenCalledWith(video: @video)
|
||||
expect(@video.player).toEqual @stubVideoPlayerAlpha
|
||||
|
||||
describe 'youtubeId', ->
|
||||
beforeEach ->
|
||||
$.cookie.andReturn '1.0'
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
|
||||
describe 'with speed', ->
|
||||
it 'return the video id for given speed', ->
|
||||
expect(@video.youtubeId('0.75')).toEqual @slowerSpeedYoutubeId
|
||||
expect(@video.youtubeId('1.0')).toEqual @normalSpeedYoutubeId
|
||||
|
||||
describe 'without speed', ->
|
||||
it 'return the video id for current speed', ->
|
||||
expect(@video.youtubeId()).toEqual @normalSpeedYoutubeId
|
||||
|
||||
describe 'setSpeed', ->
|
||||
beforeEach ->
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
|
||||
describe 'when new speed is available', ->
|
||||
beforeEach ->
|
||||
@video.setSpeed '0.75'
|
||||
|
||||
it 'set new speed', ->
|
||||
expect(@video.speed).toEqual '0.75'
|
||||
|
||||
it 'save setting for new speed', ->
|
||||
expect($.cookie).toHaveBeenCalledWith 'video_speed', '0.75', expires: 3650, path: '/'
|
||||
|
||||
describe 'when new speed is not available', ->
|
||||
beforeEach ->
|
||||
@video.setSpeed '1.75'
|
||||
|
||||
it 'set speed to 1.0x', ->
|
||||
expect(@video.speed).toEqual '1.0'
|
||||
|
||||
describe 'getDuration', ->
|
||||
beforeEach ->
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
|
||||
it 'return duration for current video', ->
|
||||
expect(@video.getDuration()).toEqual 200
|
||||
|
||||
describe 'log', ->
|
||||
beforeEach ->
|
||||
@video = new VideoAlpha '#example', @videosDefinition
|
||||
@video.setSpeed '1.0'
|
||||
spyOn Logger, 'log'
|
||||
@video.player = { currentTime: 25 }
|
||||
@video.log 'someEvent'
|
||||
|
||||
it 'call the logger with valid parameters', ->
|
||||
expect(Logger.log).toHaveBeenCalledWith 'someEvent',
|
||||
id: 'id'
|
||||
code: @normalSpeedYoutubeId
|
||||
currentTime: 25
|
||||
speed: '1.0'
|
||||
@@ -37,7 +37,7 @@ class @VideoCaptionAlpha extends SubviewAlpha
|
||||
@loaded = true
|
||||
|
||||
if onTouchBasedDevice()
|
||||
$('.subtitles li').html "Caption will be displayed when you start playing the video."
|
||||
$('.subtitles').html "<li>Caption will be displayed when you start playing the video.</li>"
|
||||
else
|
||||
@renderCaption()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ class @VideoPlayerAlpha extends SubviewAlpha
|
||||
# we must pause the player (stop setInterval() method).
|
||||
if (window.OldVideoPlayerAlpha) and (window.OldVideoPlayerAlpha.onPause)
|
||||
window.OldVideoPlayerAlpha.onPause()
|
||||
window.OldVideoPlayerAlpha = this
|
||||
window.OldVideoPlayerAlpha = @
|
||||
|
||||
if @video.videoType is 'youtube'
|
||||
@PlayerState = YT.PlayerState
|
||||
@@ -29,7 +29,7 @@ class @VideoPlayerAlpha extends SubviewAlpha
|
||||
$(@progressSlider).bind('slide_seek', @onSeek)
|
||||
if @volumeControl
|
||||
$(@volumeControl).bind('volumeChange', @onVolumeChange)
|
||||
$(document).keyup @bindExitFullScreen
|
||||
$(document.documentElement).keyup @bindExitFullScreen
|
||||
|
||||
@$('.add-fullscreen').click @toggleFullScreen
|
||||
@addToolTip() unless onTouchBasedDevice()
|
||||
@@ -114,7 +114,7 @@ class @VideoPlayerAlpha extends SubviewAlpha
|
||||
@video.log 'load_video'
|
||||
if @video.videoType is 'html5'
|
||||
@player.setPlaybackRate @video.speed
|
||||
if not onTouchBasedDevice() and $('.video:first').data('autoplay') is 'True'
|
||||
if not onTouchBasedDevice() and $('.video:first').data('autoplay') isnt 'False'
|
||||
$('.video-load-complete:first').data('video').player.play()
|
||||
|
||||
onStateChange: (event) =>
|
||||
@@ -135,6 +135,8 @@ class @VideoPlayerAlpha extends SubviewAlpha
|
||||
# NOTE: It is my strong belief that in the future YouTube Flash player will
|
||||
# not get speed changes. This is a dying technology. So we can safely use
|
||||
# this indirect method to determine player mode.
|
||||
|
||||
|
||||
availableSpeeds = @player.getAvailablePlaybackRates()
|
||||
prev_player_type = $.cookie('prev_player_type')
|
||||
if availableSpeeds.length > 1
|
||||
@@ -308,7 +310,7 @@ class @VideoPlayerAlpha extends SubviewAlpha
|
||||
@player.pauseVideo() if @player.pauseVideo
|
||||
|
||||
duration: ->
|
||||
duration = @player.getDuration()
|
||||
duration = @player.getDuration() if @player.getDuration
|
||||
if isFinite(duration) is false
|
||||
duration = @video.getDuration()
|
||||
duration
|
||||
|
||||
@@ -12,7 +12,7 @@ class @VideoProgressSliderAlpha extends SubviewAlpha
|
||||
@buildHandle()
|
||||
|
||||
buildHandle: ->
|
||||
@handle = @$('.slider .ui-slider-handle')
|
||||
@handle = @$('.ui-slider-handle')
|
||||
@handle.qtip
|
||||
content: "#{Time.format(@slider.slider('value'))}"
|
||||
position:
|
||||
|
||||
Reference in New Issue
Block a user