Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
b5ba7b82
Commit
b5ba7b82
authored
Jun 06, 2013
by
Vasyl Nakvasiuk
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7 from edx/anton/video_tests_fix
Video tests fix
parents
a65a0f62
d0e3f99e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
544 additions
and
233 deletions
+544
-233
common/lib/xmodule/xmodule/js/fixtures/video.html
+19
-9
common/lib/xmodule/xmodule/js/spec/helper.coffee
+3
-7
common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
+67
-44
common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
+20
-27
common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
+35
-20
common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
+58
-50
common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
+13
-13
common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
+1
-2
common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee
+26
-22
common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee
+1
-1
common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee
+1
-1
common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee
+1
-1
common/lib/xmodule/xmodule/video_module.py
+29
-36
lms/djangoapps/courseware/tests/__init__.py
+108
-0
lms/djangoapps/courseware/tests/test_video_mongo.py
+27
-0
lms/djangoapps/courseware/tests/test_video_xml.py
+135
-0
No files found.
common/lib/xmodule/xmodule/js/fixtures/video.html
View file @
b5ba7b82
<div
class=
"course-content"
>
<div
id=
"video_example"
class=
"video"
>
<div
class=
"tc-wrapper"
>
<article
class=
"video-wrapper"
>
<section
class=
"video-player"
>
<div
id=
"example"
></div>
</section>
<section
class=
"video-controls"
></section>
</article>
<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>
</div>
\ No newline at end of file
common/lib/xmodule/xmodule/js/spec/helper.coffee
View file @
b5ba7b82
...
...
@@ -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
)
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
View file @
b5ba7b82
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
View file @
b5ba7b82
# 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
'''
<div class="slider"></div>
<div>
<ul class="vcr">
<li><a class="video_control play" href="#">Play</a></li>
<li>
<div class="vidtime">0:00 / 0:00</div>
</li>
</ul>
<div class="secondary-controls">
<a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>
</div>
</div>
'''
@
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
->
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
View file @
b5ba7b82
# 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
).
to
Be
'#video_example
'
expect
(
@
player
.
el
).
to
HaveId
'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'
,
->
...
...
@@ -69,14 +86,13 @@ xdescribe '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
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'
,
->
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
View file @
b5ba7b82
# 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
(
@
s
lider
.
slider
).
toBe
'.slider'
expect
(
@
progressS
lider
.
slider
).
toBe
'.slider'
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
range
:
'min'
change
:
@
s
lider
.
onChange
slide
:
@
s
lider
.
onSlide
stop
:
@
s
lider
.
onStop
change
:
@
progressS
lider
.
onChange
slide
:
@
progressS
lider
.
onSlide
stop
:
@
progressS
lider
.
onStop
it
'build the seek handle'
,
->
expect
(
@
s
lider
.
handle
).
toBe
'.slider .ui-slider-handle'
expect
(
@
progressS
lider
.
handle
).
toBe
'.slider .ui-slider-handle'
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
content
:
"0:00"
position
:
my
:
'bottom center'
at
:
'top center'
container
:
@
s
lider
.
handle
container
:
@
progressS
lider
.
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
(
@
s
lider
.
slider
).
toBeUndefined
expect
(
@
progressS
lider
.
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
->
@
s
lider
.
play
()
@
progressS
lider
.
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
(
@
s
lider
.
slider
).
toBe
'.slider'
expect
(
@
progressS
lider
.
slider
).
toBe
'.slider'
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
range
:
'min'
change
:
@
s
lider
.
onChange
slide
:
@
s
lider
.
onSlide
stop
:
@
s
lider
.
onStop
change
:
@
progressS
lider
.
onChange
slide
:
@
progressS
lider
.
onSlide
stop
:
@
progressS
lider
.
onStop
it
'build the seek handle'
,
->
expect
(
@
s
lider
.
handle
).
toBe
'.ui-slider-handle'
expect
(
@
progressS
lider
.
handle
).
toBe
'.ui-slider-handle'
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
content
:
"0:00"
position
:
my
:
'bottom center'
at
:
'top center'
container
:
@
s
lider
.
handle
container
:
@
progressS
lider
.
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
$
(
@
s
lider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
s
lider
,
'seek'
@
s
lider
.
onSlide
{},
value
:
20
$
(
@
progressS
lider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
progressS
lider
,
'seek'
@
progressS
lider
.
onSlide
{},
value
:
20
it
'freeze the slider'
,
->
expect
(
@
s
lider
.
frozen
).
toBeTruthy
()
expect
(
@
progressS
lider
.
frozen
).
toBeTruthy
()
it
'update the tooltip'
,
->
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalled
()
it
'trigger seek event'
,
->
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
s
lider
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
progressS
lider
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
(
@
s
lider
.
frozen
).
toBeTruthy
()
expect
(
@
progressS
lider
.
frozen
).
toBeTruthy
()
it
'trigger seek event'
,
->
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
s
lider
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
progressS
lider
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
(
@
s
lider
.
frozen
).
toBeFalsy
()
expect
(
@
progressS
lider
.
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'
common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
View file @
b5ba7b82
# TODO: figure out why failing
xdescribe
'VideoSpeedControl'
,
->
describe
'VideoSpeedControl'
,
->
beforeEach
->
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
jasmine
.
stubVideoPlayer
@
$
(
'.speeds'
).
remove
()
...
...
@@ -10,22 +10,23 @@ xdescribe '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
'''
<div class="speeds">
<a href="#">
<h3>Speed</h3>
<p class="active">1.0x</p>
</a>
<ol class="video_speeds"><li data-speed="1.0" class="active"><a href="#">1.0x</a></li><li data-speed="0.75"><a href="#">0.75x</a></li></ol>
</div>
'''
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
->
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 +38,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'
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
View file @
b5ba7b82
# TODO: figure out why failing
xdescribe
'VideoVolumeControl'
,
->
describe
'VideoVolumeControl'
,
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
$
(
'.volume'
).
remove
()
...
...
common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee
View file @
b5ba7b82
# 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'
common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee
View file @
b5ba7b82
...
...
@@ -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
"<li>Caption will be displayed when you start playing the video.</li>
"
else
@
renderCaption
()
...
...
common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee
View file @
b5ba7b82
...
...
@@ -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
()
...
...
common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee
View file @
b5ba7b82
...
...
@@ -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
:
...
...
common/lib/xmodule/xmodule/video_module.py
View file @
b5ba7b82
# pylint: disable=W0223
"""Video is ungraded Xmodule for support video content."""
import
json
import
logging
...
...
@@ -8,7 +11,6 @@ from django.http import Http404
from
xmodule.x_module
import
XModule
from
xmodule.raw_module
import
RawDescriptor
from
xmodule.contentstore.content
import
StaticContent
from
xblock.core
import
Integer
,
Scope
,
String
import
datetime
...
...
@@ -18,21 +20,26 @@ log = logging.getLogger(__name__)
class
VideoFields
(
object
):
"""Fields for `VideoModule` and `VideoDescriptor`."""
data
=
String
(
help
=
"XML data for the problem"
,
scope
=
Scope
.
content
)
position
=
Integer
(
help
=
"Current position in the video"
,
scope
=
Scope
.
user_state
,
default
=
0
)
class
VideoModule
(
VideoFields
,
XModule
):
"""Video Xmodule."""
video_time
=
0
icon_class
=
'video'
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/time.coffee'
),
resource_string
(
__name__
,
'js/src/video/display.coffee'
)]
+
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/time.coffee'
),
resource_string
(
__name__
,
'js/src/video/display.coffee'
)
]
+
[
resource_string
(
__name__
,
'js/src/video/display/'
+
filename
)
for
filename
in
sorted
(
resource_listdir
(
__name__
,
'js/src/video/display'
))
if
filename
.
endswith
(
'.coffee'
)]}
if
filename
.
endswith
(
'.coffee'
)]
}
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/video/display.scss'
)]}
js_module_name
=
"Video"
...
...
@@ -44,14 +51,14 @@ class VideoModule(VideoFields, XModule):
self
.
show_captions
=
xmltree
.
get
(
'show_captions'
,
'true'
)
self
.
source
=
self
.
_get_source
(
xmltree
)
self
.
track
=
self
.
_get_track
(
xmltree
)
self
.
start_time
,
self
.
end_time
=
self
.
_
get_timeframe
(
xmltree
)
self
.
start_time
,
self
.
end_time
=
self
.
get_timeframe
(
xmltree
)
def
_get_source
(
self
,
xmltree
):
# find the first valid source
"""Find the first valid source."""
return
self
.
_get_first_external
(
xmltree
,
'source'
)
def
_get_track
(
self
,
xmltree
):
# find the first valid track
"""Find the first valid track."""
return
self
.
_get_first_external
(
xmltree
,
'track'
)
def
_get_first_external
(
self
,
xmltree
,
tag
):
...
...
@@ -68,59 +75,44 @@ class VideoModule(VideoFields, XModule):
break
return
result
def
_
get_timeframe
(
self
,
xmltree
):
def
get_timeframe
(
self
,
xmltree
):
""" Converts 'from' and 'to' parameters in video tag to seconds.
If there are no parameters, returns empty string. """
def
parse_time
(
s
):
def
parse_time
(
s
tr_time
):
"""Converts s in '12:34:45' format to seconds. If s is
None, returns empty string"""
if
s
is
None
:
if
s
tr_time
is
None
:
return
''
else
:
x
=
time
.
strptime
(
s
,
'
%
H:
%
M:
%
S'
)
return
datetime
.
timedelta
(
hours
=
x
.
tm_hour
,
minutes
=
x
.
tm_min
,
seconds
=
x
.
tm_sec
)
.
total_seconds
()
obj_time
=
time
.
strptime
(
str_time
,
'
%
H:
%
M:
%
S'
)
return
datetime
.
timedelta
(
hours
=
obj_time
.
tm_hour
,
minutes
=
obj_time
.
tm_min
,
seconds
=
obj_time
.
tm_sec
)
.
total_seconds
()
return
parse_time
(
xmltree
.
get
(
'from'
)),
parse_time
(
xmltree
.
get
(
'to'
))
def
handle_ajax
(
self
,
dispatch
,
get
):
'''
Handle ajax calls to this video.
TODO (vshnayder): This is not being called right now, so the position
is not being saved.
'''
"""This is not being called right now and we raise 404 error."""
log
.
debug
(
u"GET {0}"
.
format
(
get
))
log
.
debug
(
u"DISPATCH {0}"
.
format
(
dispatch
))
if
dispatch
==
'goto_position'
:
self
.
position
=
int
(
float
(
get
[
'position'
]))
log
.
info
(
u"NEW POSITION {0}"
.
format
(
self
.
position
))
return
json
.
dumps
({
'success'
:
True
})
raise
Http404
()
def
get_progress
(
self
):
''' TODO (vshnayder): Get and save duration of youtube video, then return
fraction watched.
(Be careful to notice when video link changes and update)
For now, we have no way of knowing if the video has even been watched, so
just return None.
'''
return
None
def
get_instance_state
(
self
):
#log.debug(u"STATE POSITION {0}".format(self.position))
"""Return information about state (position)."""
return
json
.
dumps
({
'position'
:
self
.
position
})
def
video_list
(
self
):
"""Return video list."""
return
self
.
youtube
def
get_html
(
self
):
# We normally let JS parse this, but in the case that we need a hacked
# out <object> player because YouTube has broken their <iframe> API for
# the third time in a year, we need to extract it server side.
normal_speed_video_id
=
None
# The 1.0 speed video
normal_speed_video_id
=
None
# The 1.0 speed video
# video_list() example:
# "0.75:nugHYNiD3fI,1.0:7m8pab1MfYY,1.25:3CxdPGXShq8,1.50:F-D7bOFCnXA"
...
...
@@ -144,6 +136,7 @@ class VideoModule(VideoFields, XModule):
class
VideoDescriptor
(
VideoFields
,
RawDescriptor
):
"""Descriptor for `VideoModule`."""
module_class
=
VideoModule
stores_state
=
True
template_dir_name
=
"video"
lms/djangoapps/courseware/tests/__init__.py
View file @
b5ba7b82
"""
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.tests
import
test_system
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. MODEL_DATA
4. 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
=
''
MODEL_DATA
=
{
'data'
:
'<some_module></some_module>'
}
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
)
self
.
item_descriptor
=
ItemFactory
.
create
(
parent_location
=
section
.
location
,
template
=
self
.
TEMPLATE_NAME
,
data
=
self
.
DATA
)
location
=
self
.
item_descriptor
.
location
system
=
test_system
()
system
.
render_template
=
lambda
template
,
context
:
context
self
.
item_module
=
self
.
item_descriptor
.
module_class
(
system
,
location
,
self
.
item_descriptor
,
self
.
MODEL_DATA
)
self
.
item_url
=
Location
(
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 item 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
()
lms/djangoapps/courseware/tests/test_video_mongo.py
0 → 100644
View file @
b5ba7b82
# -*- coding: utf-8 -*-
"""Video xmodule tests in mongo."""
from
.
import
BaseTestXmodule
class
TestVideo
(
BaseTestXmodule
):
"""Integration tests: web client + mongo."""
TEMPLATE_NAME
=
"i4x://edx/templates/video/default"
DATA
=
'<video youtube="0.75:JMD_ifUUfsU,1.0:OEoXaMPEzfM,1.25:AKqURZnYqpk,1.50:DYpADpL7jAY"/>'
def
test_handle_ajax_dispatch
(
self
):
responses
=
{
user
.
username
:
self
.
clients
[
user
.
username
]
.
post
(
self
.
get_url
(
'whatever'
),
{},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
)
for
user
in
self
.
users
}
self
.
assertEqual
(
set
([
response
.
status_code
for
_
,
response
in
responses
.
items
()
])
.
pop
(),
404
)
lms/djangoapps/courseware/tests/test_video_xml.py
0 → 100644
View file @
b5ba7b82
# -*- coding: utf-8 -*-
"""Test for Video Xmodule functional logic.
These tests data readed from xml, not from mongo.
We have a ModuleStoreTestCase class defined in
common/lib/xmodule/xmodule/modulestore/tests/django_utils.py.
You can search for usages of this in the cms and lms tests for examples.
You use this so that it will do things like point the modulestore
setting to mongo, flush the contentstore before and after, load the
templates, etc.
You can then use the CourseFactory and XModuleItemFactory as defined in
common/lib/xmodule/xmodule/modulestore/tests/factories.py to create the
course, section, subsection, unit, etc.
"""
import
json
import
unittest
from
mock
import
Mock
from
lxml
import
etree
from
xmodule.video_module
import
VideoDescriptor
,
VideoModule
from
xmodule.modulestore
import
Location
from
xmodule.tests
import
test_system
from
xmodule.tests.test_logic
import
LogicTest
class
VideoFactory
(
object
):
"""A helper class to create video modules with various parameters
for testing.
"""
# tag that uses youtube videos
sample_problem_xml_youtube
=
"""
<video show_captions="true"
youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
data_dir=""
caption_asset_path=""
autoplay="true"
from="01:00:03" to="01:00:10"
>
<source src=".../mit-3091x/M-3091X-FA12-L21-3_100.mp4"/>
</video>
"""
@staticmethod
def
create
():
"""Method return Video Xmodule instance."""
location
=
Location
([
"i4x"
,
"edX"
,
"video"
,
"default"
,
"SampleProblem1"
])
model_data
=
{
'data'
:
VideoFactory
.
sample_problem_xml_youtube
}
descriptor
=
Mock
(
weight
=
"1"
)
system
=
test_system
()
system
.
render_template
=
lambda
template
,
context
:
context
module
=
VideoModule
(
system
,
location
,
descriptor
,
model_data
)
return
module
class
VideoModuleLogicTest
(
LogicTest
):
"""Tests for logic of Video Xmodule."""
descriptor_class
=
VideoDescriptor
raw_model_data
=
{
'data'
:
'<video />'
}
def
test_get_timeframe_no_parameters
(
self
):
"""Make sure that timeframe() works correctly w/o parameters"""
xmltree
=
etree
.
fromstring
(
'<video>test</video>'
)
output
=
self
.
xmodule
.
get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
''
,
''
))
def
test_get_timeframe_with_one_parameter
(
self
):
"""Make sure that timeframe() works correctly with one parameter"""
xmltree
=
etree
.
fromstring
(
'<video from="00:04:07">test</video>'
)
output
=
self
.
xmodule
.
get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
247
,
''
))
def
test_get_timeframe_with_two_parameters
(
self
):
"""Make sure that timeframe() works correctly with two parameters"""
xmltree
=
etree
.
fromstring
(
'''<video
from="00:04:07"
to="13:04:39"
>test</video>'''
)
output
=
self
.
xmodule
.
get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
247
,
47079
))
class
VideoModuleUnitTest
(
unittest
.
TestCase
):
"""Unit tests for Video Xmodule."""
def
test_video_constructor
(
self
):
"""Make sure that all parameters extracted correclty from xml"""
module
=
VideoFactory
.
create
()
# `get_html` return only context, cause we
# overwrite `system.render_template`
context
=
module
.
get_html
()
expected_context
=
{
'track'
:
None
,
'show_captions'
:
'true'
,
'display_name'
:
'SampleProblem1'
,
'id'
:
module
.
location
.
html_id
(),
'end'
:
3610.0
,
'caption_asset_path'
:
'/static/subs/'
,
'source'
:
'.../mit-3091x/M-3091X-FA12-L21-3_100.mp4'
,
'streams'
:
'0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
,
'normal_speed_video_id'
:
'ZwkTiUPN0mg'
,
'position'
:
0
,
'start'
:
3603.0
}
self
.
assertDictEqual
(
context
,
expected_context
)
self
.
assertEqual
(
module
.
youtube
,
'0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
)
self
.
assertEqual
(
module
.
video_list
(),
module
.
youtube
)
self
.
assertEqual
(
module
.
position
,
0
)
self
.
assertDictEqual
(
json
.
loads
(
module
.
get_instance_state
()),
{
'position'
:
0
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment