From 7eb18fe01991654aee2fdca68ea3916bc51cb0ee Mon Sep 17 00:00:00 2001 From: Anton Stupak Date: Mon, 27 May 2013 11:37:01 +0300 Subject: [PATCH 1/6] adds test files for video --- .../xmodule/xmodule/js/fixtures/video.html | 27 +++-- .../lib/xmodule/xmodule/js/spec/helper.coffee | 10 +- .../video/display/video_caption_spec.coffee | 82 ++++++++----- .../video/display/video_control_spec.coffee | 47 ++++---- .../video/display/video_player_spec.coffee | 53 ++++++--- .../display/video_progress_slider_spec.coffee | 108 ++++++++++-------- .../display/video_speed_control_spec.coffee | 7 +- .../display/video_volume_control_spec.coffee | 3 +- .../xmodule/js/spec/video/display_spec.coffee | 48 ++++---- .../js/src/video/display/video_caption.coffee | 2 +- .../display/video_progress_slider.coffee | 2 +- 11 files changed, 219 insertions(+), 170 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/fixtures/video.html b/common/lib/xmodule/xmodule/js/fixtures/video.html index 15404a89d190..e86a24dc5ce0 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video.html @@ -1,12 +1,21 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file diff --git a/common/lib/xmodule/xmodule/js/spec/helper.coffee b/common/lib/xmodule/xmodule/js/spec/helper.coffee index fbc89f7bd984..5cf75366d8f0 100644 --- a/common/lib/xmodule/xmodule/js/spec/helper.coffee +++ b/common/lib/xmodule/xmodule/js/spec/helper.coffee @@ -28,7 +28,7 @@ jasmine.stubRequests = -> spyOn($, 'ajax').andCallFake (settings) -> if match = settings.url.match /youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/ settings.success data: jasmine.stubbedMetadata[match[1]] - else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/ + else if match = settings.url.match /static(\/.*)?\/subs\/(.+)\.srt\.sjson/ settings.success jasmine.stubbedCaption else if settings.url.match /.+\/problem_get$/ settings.success html: readFixtures('problem_content.html') @@ -47,19 +47,15 @@ jasmine.stubYoutubePlayer = -> jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) -> enableParts = [enableParts] unless $.isArray(enableParts) - suite = context.suite currentPartName = suite.description while suite = suite.parentSuite enableParts.push currentPartName - for part in ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider'] - unless $.inArray(part, enableParts) >= 0 - spyOn window, part - loadFixtures 'video.html' jasmine.stubRequests() YT.Player = undefined - context.video = new Video 'example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId' + videosDefinition = '0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId' + context.video = new Video '#example', videosDefinition jasmine.stubYoutubePlayer() if createPlayer return new VideoPlayer(video: context.video) diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee index 90e026e57e01..ddf6be18db66 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee @@ -1,23 +1,25 @@ -# TODO: figure out why failing -xdescribe 'VideoCaption', -> +describe 'VideoCaption', -> + beforeEach -> - jasmine.stubVideoPlayer @ - $('.subtitles').remove() + spyOn(VideoCaption.prototype, 'fetchCaption').andCallThrough() + spyOn($, 'ajaxWithPrefix').andCallThrough() + window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false afterEach -> YT.Player = undefined $.fn.scrollTo.reset() + $('.subtitles').remove() describe 'constructor', -> - beforeEach -> - spyOn($, 'getWithPrefix').andCallThrough() describe 'always', -> + beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption it 'set the youtube id', -> - expect(@caption.youtubeId).toEqual 'def456' + expect(@caption.youtubeId).toEqual 'normalSpeedYoutubeId' it 'create the caption element', -> expect($('.video')).toContain 'ol.subtitles' @@ -26,7 +28,12 @@ xdescribe 'VideoCaption', -> expect($('.video')).toContain 'a.hide-subtitles' it 'fetch the caption', -> - expect($.getWithPrefix).toHaveBeenCalledWith @caption.captionURL(), jasmine.any(Function) + 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 @@ -42,9 +49,10 @@ xdescribe 'VideoCaption', -> expect($('.subtitles')).toHandleWith 'DOMMouseScroll', @caption.onMovement describe 'when on a non touch-based device', -> + beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn false - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption it 'render the caption', -> expect($('.subtitles').html()).toMatch new RegExp(''' @@ -66,9 +74,11 @@ xdescribe 'VideoCaption', -> expect(@caption.rendered).toBeTruthy() describe 'when on a touch-based device', -> + beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn true - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + window.onTouchBasedDevice.andReturn true + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption it 'show explaination message', -> expect($('.subtitles li')).toHaveHtml "Caption will be displayed when you start playing the video." @@ -77,12 +87,15 @@ xdescribe 'VideoCaption', -> expect(@caption.rendered).toBeFalsy() describe 'mouse movement', -> + beforeEach -> - spyOn(window, 'setTimeout').andReturn 100 + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption + window.setTimeout.andReturn(100) spyOn window, 'clearTimeout' - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' describe 'when cursor is outside of the caption box', -> + beforeEach -> $(window).trigger jQuery.Event 'mousemove' @@ -90,6 +103,7 @@ xdescribe 'VideoCaption', -> expect(@caption.frozen).toBeFalsy() describe 'when cursor is in the caption box', -> + beforeEach -> $('.subtitles').trigger jQuery.Event 'mouseenter' @@ -143,8 +157,10 @@ xdescribe 'VideoCaption', -> expect($.fn.scrollTo).not.toHaveBeenCalled() describe 'search', -> + beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption it 'return a correct caption index', -> expect(@caption.search(0)).toEqual 0 @@ -157,8 +173,9 @@ xdescribe 'VideoCaption', -> describe 'play', -> describe 'when the caption was not rendered', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn true - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + window.onTouchBasedDevice.andReturn true + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption @caption.play() it 'render the caption', -> @@ -185,7 +202,8 @@ xdescribe 'VideoCaption', -> describe 'pause', -> beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption @caption.playing = true @caption.pause() @@ -193,8 +211,10 @@ xdescribe 'VideoCaption', -> expect(@caption.playing).toBeFalsy() describe 'updatePlayTime', -> + beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption describe 'when the video speed is 1.0x', -> beforeEach -> @@ -240,13 +260,15 @@ xdescribe 'VideoCaption', -> expect($('.subtitles li[data-index=1]')).toHaveClass 'current' describe 'resize', -> + beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption $('.subtitles li[data-index=1]').addClass 'current' @caption.resize() it 'set the height of caption container', -> - expect(parseInt($('.subtitles').css('maxHeight'))).toEqual $('.video-wrapper').height() + expect(parseInt($('.subtitles').css('maxHeight'))).toBeCloseTo $('.video-wrapper').height(), 5 it 'set the height of caption spacing', -> expect(parseInt($('.subtitles .spacing:first').css('height'))).toEqual( @@ -258,8 +280,10 @@ xdescribe 'VideoCaption', -> expect($.fn.scrollTo).toHaveBeenCalled() describe 'scrollCaption', -> + beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption describe 'when frozen', -> beforeEach -> @@ -291,15 +315,17 @@ xdescribe 'VideoCaption', -> offset: - ($('.video-wrapper').height() / 2 - $('.subtitles .current:first').height() / 2) describe 'seekPlayer', -> + beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @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"]').click() + $('.subtitles li[data-start="30000"]').trigger('click') it 'trigger seek event with the correct time', -> expect(@time).toEqual 30.000 @@ -307,14 +333,15 @@ xdescribe 'VideoCaption', -> describe 'when the video speed is not 1.0x', -> beforeEach -> @caption.currentSpeed = '0.75' - $('.subtitles li[data-start="30000"]').click() + $('.subtitles li[data-start="30000"]').trigger('click') it 'trigger seek event with the correct time', -> expect(@time).toEqual 40.000 describe 'toggle', -> beforeEach -> - @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0' + @player = jasmine.stubVideoPlayer @ + @caption = @player.caption $('.subtitles li[data-index=1]').addClass 'current' describe 'when the caption is visible', -> @@ -325,7 +352,6 @@ xdescribe 'VideoCaption', -> it 'hide the caption', -> expect(@caption.el).toHaveClass 'closed' - describe 'when the caption is hidden', -> beforeEach -> @caption.el.addClass 'closed' diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee index 7603d5777f06..e15b0c856acc 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee @@ -1,53 +1,44 @@ -# TODO: figure out why failing -xdescribe 'VideoControl', -> +describe 'VideoControl', -> beforeEach -> - jasmine.stubVideoPlayer @ + window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false + loadFixtures 'video.html' $('.video-controls').html '' describe 'constructor', -> + it 'render the video controls', -> - new VideoControl(el: $('.video-controls')) - expect($('.video-controls').html()).toContain ''' -
-
-
    -
  • Play
  • -
  • -
    0:00 / 0:00
    -
  • -
- -
- ''' + @control = new window.VideoControl(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 VideoControl(el: $('.video-controls')) - expect($('.video_control')).toHandleWith 'click', control.togglePlayback + @control = new window.VideoControl(el: $('.video-controls')) + expect($('.video_control')).toHandleWith 'click', @control.togglePlayback describe 'when on a touch based device', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn true + window.onTouchBasedDevice.andReturn true + @control = new window.VideoControl(el: $('.video-controls')) it 'does not add the play class to video control', -> - new VideoControl(el: $('.video-controls')) expect($('.video_control')).not.toHaveClass 'play' expect($('.video_control')).not.toHaveHtml 'Play' describe 'when on a non-touch based device', -> + beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn false + @control = new window.VideoControl(el: $('.video-controls')) it 'add the play class to video control', -> - new VideoControl(el: $('.video-controls')) expect($('.video_control')).toHaveClass 'play' expect($('.video_control')).toHaveHtml 'Play' describe 'play', -> + beforeEach -> - @control = new VideoControl(el: $('.video-controls')) + @control = new window.VideoControl(el: $('.video-controls')) @control.play() it 'switch playback button to play state', -> @@ -56,8 +47,9 @@ xdescribe 'VideoControl', -> expect($('.video_control')).toHaveHtml 'Pause' describe 'pause', -> + beforeEach -> - @control = new VideoControl(el: $('.video-controls')) + @control = new window.VideoControl(el: $('.video-controls')) @control.pause() it 'switch playback button to pause state', -> @@ -66,8 +58,9 @@ xdescribe 'VideoControl', -> expect($('.video_control')).toHaveHtml 'Play' describe 'togglePlayback', -> + beforeEach -> - @control = new VideoControl(el: $('.video-controls')) + @control = new window.VideoControl(el: $('.video-controls')) describe 'when the control does not have play or pause class', -> beforeEach -> diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee index b6c562c88a14..0fa2c6f5151e 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee @@ -1,6 +1,9 @@ -# TODO: figure out why failing -xdescribe 'VideoPlayer', -> +describe 'VideoPlayer', -> beforeEach -> + window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false + # It tries to call methods of VideoProgressSlider on Spy + for part in ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider', 'VideoControl'] + spyOn(window[part].prototype, 'initialize').andCallThrough() jasmine.stubVideoPlayer @, [], false afterEach -> @@ -8,7 +11,6 @@ xdescribe 'VideoPlayer', -> describe 'constructor', -> beforeEach -> - spyOn window, 'VideoControl' spyOn YT, 'Player' $.fn.qtip.andCallFake -> $(this).data('qtip', true) @@ -22,32 +24,47 @@ xdescribe 'VideoPlayer', -> expect(@player.currentTime).toEqual 0 it 'set the element', -> - expect(@player.el).toBe '#video_example' + expect(@player.el).toHaveId 'video_id' it 'create video control', -> - expect(window.VideoControl).toHaveBeenCalledWith el: $('.video-controls', @player.el) + expect(window.VideoControl.prototype.initialize).toHaveBeenCalled() + expect(@player.control).toBeDefined() + expect(@player.control.el).toBe $('.video-controls', @player.el) it 'create video caption', -> - expect(window.VideoCaption).toHaveBeenCalledWith el: @player.el, youtubeId: 'normalSpeedYoutubeId', currentSpeed: '1.0' + expect(window.VideoCaption.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.VideoSpeedControl).toHaveBeenCalledWith el: $('.secondary-controls', @player.el), speeds: ['0.75', '1.0'], currentSpeed: '1.0' + expect(window.VideoSpeedControl.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.VideoProgressSlider).toHaveBeenCalledWith el: $('.slider', @player.el) + expect(window.VideoSpeedControl.prototype.initialize).toHaveBeenCalled() + expect(@player.progressSlider).toBeDefined() + expect(@player.progressSlider.el).toBe $('.slider', @player.el) it 'create Youtube player', -> - expect(YT.Player).toHaveBeenCalledWith('example', { + expect(YT.Player).toHaveBeenCalledWith('id', { playerVars: controls: 0 wmode: 'transparent' rel: 0 showinfo: 0 enablejsapi: 1 + modestbranding: 1 videoId: 'normalSpeedYoutubeId' events: onReady: @player.onReady onStateChange: @player.onStateChange + onPlaybackQualityChange: @player.onPlaybackQualityChange }) it 'bind to video control play event', -> @@ -76,7 +93,6 @@ xdescribe 'VideoPlayer', -> describe 'when not on a touch based device', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn false $('.add-fullscreen, .hide-subtitles').removeData 'qtip' @player = new VideoPlayer video: @video @@ -85,11 +101,13 @@ xdescribe 'VideoPlayer', -> expect($('.hide-subtitles')).toHaveData 'qtip' it 'create video volume control', -> - expect(window.VideoVolumeControl).toHaveBeenCalledWith el: $('.secondary-controls', @player.el) + expect(window.VideoVolumeControl.prototype.initialize).toHaveBeenCalled() + expect(@player.volumeControl).toBeDefined() + expect(@player.volumeControl.el).toBe $('.secondary-controls', @player.el) describe 'when on a touch based device', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn true + window.onTouchBasedDevice.andReturn true $('.add-fullscreen, .hide-subtitles').removeData 'qtip' @player = new VideoPlayer video: @video @@ -98,7 +116,8 @@ xdescribe 'VideoPlayer', -> expect($('.hide-subtitles')).not.toHaveData 'qtip' it 'does not create video volume control', -> - expect(window.VideoVolumeControl).not.toHaveBeenCalled() + expect(window.VideoVolumeControl.prototype.initialize).not.toHaveBeenCalled() + expect(@player.volumeControl).not.toBeDefined() describe 'onReady', -> beforeEach -> @@ -110,7 +129,6 @@ xdescribe 'VideoPlayer', -> describe 'when not on a touch based device', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn false spyOn @player, 'play' @player.onReady() @@ -119,7 +137,7 @@ xdescribe 'VideoPlayer', -> describe 'when on a touch based device', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn true + window.onTouchBasedDevice.andReturn true spyOn @player, 'play' @player.onReady() @@ -347,9 +365,6 @@ xdescribe 'VideoPlayer', -> it 'replace the full screen button tooltip', -> expect($('.add-fullscreen')).toHaveAttr 'title', 'Exit fill browser' - it 'add a new exit from fullscreen button', -> - expect(@player.el).toContain 'a.exit' - it 'add the fullscreen class', -> expect(@player.el).toHaveClass 'fullscreen' @@ -438,7 +453,7 @@ xdescribe 'VideoPlayer', -> describe 'volume', -> beforeEach -> - @player = new VideoPlayer @video + @player = new VideoPlayer video: @video @player.player.getVolume.andReturn 42 describe 'without value', -> diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee index 99b675b1d73a..bf6dada93b39 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee @@ -1,31 +1,30 @@ -# TODO: figure out why failing -xdescribe 'VideoProgressSlider', -> +describe 'VideoProgressSlider', -> beforeEach -> - jasmine.stubVideoPlayer @ + window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false describe 'constructor', -> describe 'on a non-touch based device', -> beforeEach -> spyOn($.fn, 'slider').andCallThrough() - spyOn(window, 'onTouchBasedDevice').andReturn false - @slider = new VideoProgressSlider el: $('.slider') + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider it 'build the slider', -> - expect(@slider.slider).toBe '.slider' + expect(@progressSlider.slider).toBe '.slider' expect($.fn.slider).toHaveBeenCalledWith range: 'min' - change: @slider.onChange - slide: @slider.onSlide - stop: @slider.onStop + change: @progressSlider.onChange + slide: @progressSlider.onSlide + stop: @progressSlider.onStop it 'build the seek handle', -> - expect(@slider.handle).toBe '.slider .ui-slider-handle' + expect(@progressSlider.handle).toBe '.slider .ui-slider-handle' expect($.fn.qtip).toHaveBeenCalledWith content: "0:00" position: my: 'bottom center' at: 'top center' - container: @slider.handle + container: @progressSlider.handle hide: delay: 700 style: @@ -34,47 +33,51 @@ xdescribe 'VideoProgressSlider', -> describe 'on a touch-based device', -> beforeEach -> + window.onTouchBasedDevice.andReturn true spyOn($.fn, 'slider').andCallThrough() - spyOn(window, 'onTouchBasedDevice').andReturn true - @slider = new VideoProgressSlider el: $('.slider') + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider it 'does not build the slider', -> - expect(@slider.slider).toBeUndefined + expect(@progressSlider.slider).toBeUndefined expect($.fn.slider).not.toHaveBeenCalled() describe 'play', -> beforeEach -> - @slider = new VideoProgressSlider el: $('.slider') - spyOn($.fn, 'slider').andCallThrough() + spyOn(VideoProgressSlider.prototype, 'buildSlider').andCallThrough() + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider describe 'when the slider was already built', -> + beforeEach -> - @slider.play() + @progressSlider.play() it 'does not build the slider', -> - expect($.fn.slider).not.toHaveBeenCalled + expect(@progressSlider.buildSlider.calls.length).toEqual 1 describe 'when the slider was not already built', -> beforeEach -> - @slider.slider = null - @slider.play() + spyOn($.fn, 'slider').andCallThrough() + @progressSlider.slider = null + @progressSlider.play() it 'build the slider', -> - expect(@slider.slider).toBe '.slider' + expect(@progressSlider.slider).toBe '.slider' expect($.fn.slider).toHaveBeenCalledWith range: 'min' - change: @slider.onChange - slide: @slider.onSlide - stop: @slider.onStop + change: @progressSlider.onChange + slide: @progressSlider.onSlide + stop: @progressSlider.onStop it 'build the seek handle', -> - expect(@slider.handle).toBe '.ui-slider-handle' + expect(@progressSlider.handle).toBe '.ui-slider-handle' expect($.fn.qtip).toHaveBeenCalledWith content: "0:00" position: my: 'bottom center' at: 'top center' - container: @slider.handle + container: @progressSlider.handle hide: delay: 700 style: @@ -83,21 +86,23 @@ xdescribe 'VideoProgressSlider', -> describe 'updatePlayTime', -> beforeEach -> - @slider = new VideoProgressSlider el: $('.slider') - spyOn($.fn, 'slider').andCallThrough() + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider describe 'when frozen', -> beforeEach -> - @slider.frozen = true - @slider.updatePlayTime 20, 120 + 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 -> - @slider.frozen = false - @slider.updatePlayTime 20, 120 + 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 @@ -107,55 +112,58 @@ xdescribe 'VideoProgressSlider', -> describe 'onSlide', -> beforeEach -> - @slider = new VideoProgressSlider el: $('.slider') + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider @time = null - $(@slider).bind 'seek', (event, time) => @time = time - spyOnEvent @slider, 'seek' - @slider.onSlide {}, value: 20 + $(@progressSlider).bind 'seek', (event, time) => @time = time + spyOnEvent @progressSlider, 'seek' + @progressSlider.onSlide {}, value: 20 it 'freeze the slider', -> - expect(@slider.frozen).toBeTruthy() + expect(@progressSlider.frozen).toBeTruthy() it 'update the tooltip', -> expect($.fn.qtip).toHaveBeenCalled() it 'trigger seek event', -> - expect('seek').toHaveBeenTriggeredOn @slider + expect('seek').toHaveBeenTriggeredOn @progressSlider expect(@time).toEqual 20 describe 'onChange', -> beforeEach -> - @slider = new VideoProgressSlider el: $('.slider') - @slider.onChange {}, value: 20 + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider + @progressSlider.onChange {}, value: 20 it 'update the tooltip', -> expect($.fn.qtip).toHaveBeenCalled() describe 'onStop', -> beforeEach -> - @slider = new VideoProgressSlider el: $('.slider') + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider @time = null - $(@slider).bind 'seek', (event, time) => @time = time - spyOnEvent @slider, 'seek' - spyOn(window, 'setTimeout') - @slider.onStop {}, value: 20 + $(@progressSlider).bind 'seek', (event, time) => @time = time + spyOnEvent @progressSlider, 'seek' + @progressSlider.onStop {}, value: 20 it 'freeze the slider', -> - expect(@slider.frozen).toBeTruthy() + expect(@progressSlider.frozen).toBeTruthy() it 'trigger seek event', -> - expect('seek').toHaveBeenTriggeredOn @slider + 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(@slider.frozen).toBeFalsy() + expect(@progressSlider.frozen).toBeFalsy() describe 'updateTooltip', -> beforeEach -> - @slider = new VideoProgressSlider el: $('.slider') - @slider.updateTooltip 90 + @player = jasmine.stubVideoPlayer @ + @progressSlider = @player.progressSlider + @progressSlider.updateTooltip 90 it 'set the tooltip value', -> expect($.fn.qtip).toHaveBeenCalledWith 'option', 'content.text', '1:30' diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee index a7af239094f9..ac321b8e9794 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee @@ -1,6 +1,6 @@ -# TODO: figure out why failing -xdescribe 'VideoSpeedControl', -> +describe 'VideoSpeedControl', -> beforeEach -> + window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false jasmine.stubVideoPlayer @ $('.speeds').remove() @@ -25,7 +25,7 @@ xdescribe 'VideoSpeedControl', -> describe 'when running on touch based device', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn true + window.onTouchBasedDevice.andReturn true $('.speeds').removeClass 'open' @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0' @@ -37,7 +37,6 @@ xdescribe 'VideoSpeedControl', -> describe 'when running on non-touch based device', -> beforeEach -> - spyOn(window, 'onTouchBasedDevice').andReturn false $('.speeds').removeClass 'open' @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0' diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee index 41ac5dd3e401..a2b14afa5553 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee @@ -1,5 +1,4 @@ -# TODO: figure out why failing -xdescribe 'VideoVolumeControl', -> +describe 'VideoVolumeControl', -> beforeEach -> jasmine.stubVideoPlayer @ $('.volume').remove() diff --git a/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee index ac90310519bb..a83fa3905cb2 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee @@ -1,12 +1,20 @@ -# TODO: figure out why failing -xdescribe 'Video', -> +describe 'Video', -> + metadata = undefined + beforeEach -> loadFixtures 'video.html' jasmine.stubRequests() - @videosDefinition = '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId' + @videosDefinition = '0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId' @slowerSpeedYoutubeId = 'slowerSpeedYoutubeId' @normalSpeedYoutubeId = 'normalSpeedYoutubeId' + metadata = + slowerSpeedYoutubeId: + id: @slowerSpeedYoutubeId + duration: 300 + normalSpeedYoutubeId: + id: @normalSpeedYoutubeId + duration: 200 afterEach -> window.player = undefined @@ -16,17 +24,18 @@ xdescribe 'Video', -> beforeEach -> @stubVideoPlayer = jasmine.createSpy('VideoPlayer') $.cookie.andReturn '0.75' - window.player = 100 + window.player = undefined describe 'by default', -> beforeEach -> - @video = new Video 'example', @videosDefinition - + spyOn(window.Video.prototype, 'fetchMetadata').andCallFake -> + @metadata = metadata + @video = new Video '#example', @videosDefinition it 'reset the current video player', -> expect(window.player).toBeNull() it 'set the elements', -> - expect(@video.el).toBe '#video_example' + expect(@video.el).toBe '#video_id' it 'parse the videos', -> expect(@video.videos).toEqual @@ -34,13 +43,8 @@ xdescribe 'Video', -> '1.0': @normalSpeedYoutubeId it 'fetch the video metadata', -> - expect(@video.metadata).toEqual - slowerSpeedYoutubeId: - id: @slowerSpeedYoutubeId - duration: 300 - normalSpeedYoutubeId: - id: @normalSpeedYoutubeId - duration: 200 + expect(@video.fetchMetadata).toHaveBeenCalled + expect(@video.metadata).toEqual metadata it 'parse available video speeds', -> expect(@video.speeds).toEqual ['0.75', '1.0'] @@ -56,7 +60,7 @@ xdescribe 'Video', -> @originalYT = window.YT window.YT = { Player: true } spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer) - @video = new Video 'example', @videosDefinition + @video = new Video '#example', @videosDefinition afterEach -> window.YT = @originalYT @@ -69,7 +73,7 @@ xdescribe 'Video', -> beforeEach -> @originalYT = window.YT window.YT = {} - @video = new Video 'example', @videosDefinition + @video = new Video '#example', @videosDefinition afterEach -> window.YT = @originalYT @@ -82,7 +86,7 @@ xdescribe 'Video', -> @originalYT = window.YT window.YT = {} spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer) - @video = new Video 'example', @videosDefinition + @video = new Video '#example', @videosDefinition window.onYouTubePlayerAPIReady() afterEach -> @@ -95,7 +99,7 @@ xdescribe 'Video', -> describe 'youtubeId', -> beforeEach -> $.cookie.andReturn '1.0' - @video = new Video 'example', @videosDefinition + @video = new Video '#example', @videosDefinition describe 'with speed', -> it 'return the video id for given speed', -> @@ -108,7 +112,7 @@ xdescribe 'Video', -> describe 'setSpeed', -> beforeEach -> - @video = new Video 'example', @videosDefinition + @video = new Video '#example', @videosDefinition describe 'when new speed is available', -> beforeEach -> @@ -129,14 +133,14 @@ xdescribe 'Video', -> describe 'getDuration', -> beforeEach -> - @video = new Video 'example', @videosDefinition + @video = new Video '#example', @videosDefinition it 'return duration for current video', -> expect(@video.getDuration()).toEqual 200 describe 'log', -> beforeEach -> - @video = new Video 'example', @videosDefinition + @video = new Video '#example', @videosDefinition @video.setSpeed '1.0' spyOn Logger, 'log' @video.player = { currentTime: 25 } @@ -144,7 +148,7 @@ xdescribe 'Video', -> it 'call the logger with valid parameters', -> expect(Logger.log).toHaveBeenCalledWith 'someEvent', - id: 'example' + id: 'id' code: @normalSpeedYoutubeId currentTime: 25 speed: '1.0' diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee index bf3ec1e1029c..c72067b0dc45 100644 --- a/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee @@ -37,7 +37,7 @@ class @VideoCaption extends Subview @loaded = true if onTouchBasedDevice() - $('.subtitles li').html "Caption will be displayed when you start playing the video." + $('.subtitles').html "
  • Caption will be displayed when you start playing the video.
  • " else @renderCaption() diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee index 874756cb7196..ef2f38698b60 100644 --- a/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee @@ -11,7 +11,7 @@ class @VideoProgressSlider extends Subview @buildHandle() buildHandle: -> - @handle = @$('.slider .ui-slider-handle') + @handle = @$('.ui-slider-handle') @handle.qtip content: "#{Time.format(@slider.slider('value'))}" position: From 8b06916eb6e6d15723d1fe66695a2537e1b46a51 Mon Sep 17 00:00:00 2001 From: Anto Stupak Date: Wed, 29 May 2013 15:53:00 +0300 Subject: [PATCH 2/6] Fix tests for firefox --- .../video/display/video_caption_spec.coffee | 31 +++++++++---------- .../video/display/video_player_spec.coffee | 2 +- .../display/video_speed_control_spec.coffee | 19 ++++++------ .../js/src/video/display/video_player.coffee | 2 +- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee index ddf6be18db66..8c63751f0761 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee @@ -55,12 +55,11 @@ describe 'VideoCaption', -> @caption = @player.caption it 'render the caption', -> - expect($('.subtitles').html()).toMatch new RegExp(''' -
  • Caption at 0
  • -
  • Caption at 10000
  • -
  • Caption at 20000
  • -
  • Caption at 30000
  • - '''.replace(/\n/g, '')) + 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' @@ -179,12 +178,11 @@ describe 'VideoCaption', -> @caption.play() it 'render the caption', -> - expect($('.subtitles').html()).toMatch new RegExp( - '''
  • Caption at 0
  • ''' + - '''
  • Caption at 10000
  • ''' + - '''
  • Caption at 20000
  • ''' + - '''
  • Caption at 30000
  • ''' - ) + 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' @@ -268,13 +266,12 @@ describe 'VideoCaption', -> @caption.resize() it 'set the height of caption container', -> - expect(parseInt($('.subtitles').css('maxHeight'))).toBeCloseTo $('.video-wrapper').height(), 5 + expect(parseInt($('.subtitles').css('maxHeight'))).toBeCloseTo $('.video-wrapper').height(), 2 it 'set the height of caption spacing', -> - expect(parseInt($('.subtitles .spacing:first').css('height'))).toEqual( - $('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):first').height() / 2) - expect(parseInt($('.subtitles .spacing:last').css('height'))).toEqual( - $('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):last').height() / 2) + 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() diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee index 0fa2c6f5151e..dab8c0815a10 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee @@ -86,7 +86,7 @@ describe 'VideoPlayer', -> expect($(@player.volumeControl)).toHandleWith 'volumeChange', @player.onVolumeChange it 'bind to key press', -> - expect($(document)).toHandleWith 'keyup', @player.bindExitFullScreen + expect($(document.documentElement)).toHandleWith 'keyup', @player.bindExitFullScreen it 'bind to fullscreen switching button', -> expect($('.add-fullscreen')).toHandleWith 'click', @player.toggleFullScreen diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee index ac321b8e9794..687f90e03071 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee @@ -10,15 +10,16 @@ describe 'VideoSpeedControl', -> @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0' it 'add the video speed control to player', -> - expect($('.secondary-controls').html()).toContain ''' - - ''' + 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 diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee index 561ca07c8a3f..73ff3512e2aa 100644 --- a/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee @@ -15,7 +15,7 @@ class @VideoPlayer extends Subview $(@progressSlider).bind('seek', @onSeek) if @volumeControl $(@volumeControl).bind('volumeChange', @onVolumeChange) - $(document).keyup @bindExitFullScreen + $(document.documentElement).keyup @bindExitFullScreen @$('.add-fullscreen').click @toggleFullScreen @addToolTip() unless onTouchBasedDevice() From b25710346f44c3e0bdbc69928eba39fc8abc3106 Mon Sep 17 00:00:00 2001 From: Vasyl Nakvasiuk Date: Thu, 30 May 2013 11:22:20 +0300 Subject: [PATCH 3/6] add python video tests --- lms/djangoapps/courseware/tests/__init__.py | 97 +++++++++++++ .../courseware/tests/test_video_mongo.py | 49 +++++++ .../courseware/tests/test_video_xml.py | 137 ++++++++++++++++++ 3 files changed, 283 insertions(+) create mode 100644 lms/djangoapps/courseware/tests/test_video_mongo.py create mode 100644 lms/djangoapps/courseware/tests/test_video_xml.py diff --git a/lms/djangoapps/courseware/tests/__init__.py b/lms/djangoapps/courseware/tests/__init__.py index e69de29bb2d1..dd3c4dc2b385 100644 --- a/lms/djangoapps/courseware/tests/__init__.py +++ b/lms/djangoapps/courseware/tests/__init__.py @@ -0,0 +1,97 @@ +""" +integration tests for xmodule + +Contains: + + 1. BaseTestXmodule class provides course and users + for testing Xmodules with mongo store. +""" + +from django.test.utils import override_settings +from django.core.urlresolvers import reverse +from django.test.client import Client + +from student.tests.factories import UserFactory, CourseEnrollmentFactory +from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from xmodule.modulestore import Location +from xmodule.modulestore.django import modulestore +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase + + +@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +class BaseTestXmodule(ModuleStoreTestCase): + """Base class for testing Xmodules with mongo store. + + This class prepares course and users for tests: + 1. create test course + 2. create, enrol and login users for this course + + Any xmodule should overwrite only next parameters for test: + 1. TEMPLATE_NAME + 2. DATA + 3. COURSE_DATA and USER_COUNT if needed + + This class should not contain any tests, because TEMPLATE_NAME + should be defined in child class. + """ + USER_COUNT = 2 + COURSE_DATA = {} + + # Data from YAML common/lib/xmodule/xmodule/templates/NAME/default.yaml + TEMPLATE_NAME = "" + DATA = {} + + def setUp(self): + + self.course = CourseFactory.create(data=self.COURSE_DATA) + + # Turn off cache. + modulestore().request_cache = None + modulestore().metadata_inheritance_cache_subsystem = None + + chapter = ItemFactory.create( + parent_location=self.course.location, + template="i4x://edx/templates/sequential/Empty", + ) + section = ItemFactory.create( + parent_location=chapter.location, + template="i4x://edx/templates/sequential/Empty" + ) + + # username = robot{0}, password = 'test' + self.users = [ + UserFactory.create(username='robot%d' % i, email='robot+test+%d@edx.org' % i) + for i in range(self.USER_COUNT) + ] + + for user in self.users: + CourseEnrollmentFactory.create(user=user, course_id=self.course.id) + + item = ItemFactory.create( + parent_location=section.location, + template=self.TEMPLATE_NAME, + data=self.DATA + ) + self.item_url = Location(item.location).url() + + # login all users for acces to Xmodule + self.clients = {user.username: Client() for user in self.users} + self.login_statuses = [ + self.clients[user.username].login( + username=user.username, password='test') + for user in self.users + ] + + self.assertTrue(all(self.login_statuses)) + + def get_url(self, dispatch): + """Return word cloud url with dispatch.""" + return reverse( + 'modx_dispatch', + args=(self.course.id, self.item_url, dispatch) + ) + + def tearDown(self): + for user in self.users: + user.delete() diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py new file mode 100644 index 000000000000..f979ae2686bd --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +"""Video xmodule tests in mongo.""" + +import json + +from . import BaseTestXmodule + + +class TestVideo(BaseTestXmodule): + """Integration tests: web client + mongo.""" + + TEMPLATE_NAME = "i4x://edx/templates/video/default" + DATA = '