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
450dfe17
Commit
450dfe17
authored
Apr 09, 2014
by
Valera Rozuvan
Committed by
Valera Rozuvan
Apr 23, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TESTS: Add tests for fix of end-time in the video player.
BLD-662
parent
dc373f22
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
291 additions
and
93 deletions
+291
-93
common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js
+1
-1
common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
+27
-11
common/lib/xmodule/xmodule/js/src/video/01_initialize.js
+5
-0
common/lib/xmodule/xmodule/js/src/video/02_html5_video.js
+2
-1
common/lib/xmodule/xmodule/js/src/video/03_video_player.js
+105
-35
common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js
+13
-2
lms/djangoapps/courseware/features/common.py
+1
-1
lms/djangoapps/courseware/features/video.feature
+112
-30
lms/djangoapps/courseware/features/video.py
+25
-12
No files found.
common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js
View file @
450dfe17
...
...
@@ -117,7 +117,7 @@
runs
(
function
()
{
expect
(
state
.
videoPlayer
.
player
.
getPlayerState
())
.
toBe
(
STATUS
.
PLAY
ING
);
.
toBe
(
STATUS
.
BUFFER
ING
);
});
});
...
...
common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
View file @
450dfe17
...
...
@@ -366,19 +366,22 @@ function (VideoPlayer) {
});
it
(
'Slider event causes log update'
,
function
()
{
runs
(
function
()
{
var
currentTime
=
state
.
videoPlayer
.
currentTime
;
spyOn
(
state
.
videoPlayer
,
'log'
);
state
.
videoProgressSlider
.
onSlide
(
jQuery
.
Event
(
'slide'
),
{
value
:
2
}
);
});
waitsFor
(
function
()
{
return
state
.
videoPlayer
.
currentTime
>=
2
;
},
'currentTime is less than 2 seconds'
,
WAIT_TIMEOUT
);
runs
(
function
()
{
expect
(
state
.
videoPlayer
.
log
).
toHaveBeenCalledWith
(
'seek_video'
,
{
old_time
:
currentTime
,
old_time
:
jasmine
.
any
(
Number
)
,
new_time
:
2
,
type
:
'onSlideSeek'
}
...
...
@@ -388,25 +391,37 @@ function (VideoPlayer) {
it
(
'seek the player'
,
function
()
{
runs
(
function
()
{
spyOn
(
state
.
videoPlayer
.
player
,
'seekTo'
);
spyOn
(
state
.
videoPlayer
.
player
,
'seekTo'
)
.
andCallThrough
()
;
state
.
videoProgressSlider
.
onSlide
(
jQuery
.
Event
(
'slide'
),
{
value
:
6
0
}
jQuery
.
Event
(
'slide'
),
{
value
:
3
0
}
);
});
waitsFor
(
function
()
{
return
state
.
videoPlayer
.
currentTime
>=
30
;
},
'currentTime is less than 30 seconds'
,
WAIT_TIMEOUT
);
runs
(
function
()
{
expect
(
state
.
videoPlayer
.
player
.
seekTo
)
.
toHaveBeenCalledWith
(
6
0
,
true
);
.
toHaveBeenCalledWith
(
3
0
,
true
);
});
});
it
(
'call updatePlayTime on player'
,
function
()
{
runs
(
function
()
{
spyOn
(
state
.
videoPlayer
,
'updatePlayTime'
);
spyOn
(
state
.
videoPlayer
,
'updatePlayTime'
)
.
andCallThrough
()
;
state
.
videoProgressSlider
.
onSlide
(
jQuery
.
Event
(
'slide'
),
{
value
:
6
0
}
jQuery
.
Event
(
'slide'
),
{
value
:
3
0
}
);
});
waitsFor
(
function
()
{
return
state
.
videoPlayer
.
currentTime
>=
30
;
},
'currentTime is less than 30 seconds'
,
WAIT_TIMEOUT
);
runs
(
function
()
{
expect
(
state
.
videoPlayer
.
updatePlayTime
)
.
toHaveBeenCalledWith
(
60
);
.
toHaveBeenCalledWith
(
jasmine
.
any
(
Number
)
);
});
});
...
...
@@ -1070,6 +1085,7 @@ function (VideoPlayer) {
youtubeId
:
jasmine
.
createSpy
().
andReturn
(
'videoId'
),
isFlashMode
:
jasmine
.
createSpy
().
andReturn
(
false
),
isHtml5Mode
:
jasmine
.
createSpy
().
andReturn
(
true
),
isYoutubeType
:
jasmine
.
createSpy
().
andReturn
(
true
),
setPlayerMode
:
jasmine
.
createSpy
(),
videoPlayer
:
{
currentTime
:
60
,
...
...
@@ -1104,12 +1120,12 @@ function (VideoPlayer) {
});
it
(
'in HTML5 mode'
,
function
()
{
state
.
isYoutubeType
.
andReturn
(
false
);
VideoPlayer
.
prototype
.
setPlaybackRate
.
call
(
state
,
'0.75'
);
expect
(
state
.
videoPlayer
.
player
.
setPlaybackRate
).
toHaveBeenCalledWith
(
'0.75'
);
});
it
(
'Youtube video in FF, with new speed equal 1.0'
,
function
()
{
state
.
videoType
=
'youtube'
;
state
.
browserIsFirefox
=
true
;
state
.
videoPlayer
.
isPlaying
.
andReturn
(
false
);
...
...
common/lib/xmodule/xmodule/js/src/video/01_initialize.js
View file @
450dfe17
...
...
@@ -68,6 +68,7 @@ function (VideoPlayer, VideoStorage) {
initialize
:
initialize
,
isHtml5Mode
:
isHtml5Mode
,
isFlashMode
:
isFlashMode
,
isYoutubeType
:
isYoutubeType
,
parseSpeed
:
parseSpeed
,
parseVideoSources
:
parseVideoSources
,
parseYoutubeStreams
:
parseYoutubeStreams
,
...
...
@@ -847,6 +848,10 @@ function (VideoPlayer, VideoStorage) {
return
this
.
getPlayerMode
()
===
'html5'
;
}
function
isYoutubeType
()
{
return
this
.
videoType
===
'youtube'
;
}
function
speedToString
(
speed
)
{
return
parseFloat
(
speed
).
toFixed
(
2
).
replace
(
/
\.
00$/
,
'.0'
);
}
...
...
common/lib/xmodule/xmodule/js/src/video/02_html5_video.js
View file @
450dfe17
...
...
@@ -275,12 +275,13 @@ function () {
// Register the 'play' event.
this
.
video
.
addEventListener
(
'play'
,
function
()
{
_this
.
playerState
=
HTML5Video
.
PlayerState
.
PLAY
ING
;
_this
.
playerState
=
HTML5Video
.
PlayerState
.
BUFFER
ING
;
_this
.
callStateChangeCallback
();
},
false
);
this
.
video
.
addEventListener
(
'playing'
,
function
()
{
_this
.
playerState
=
HTML5Video
.
PlayerState
.
PLAYING
;
_this
.
callStateChangeCallback
();
},
false
);
// Register the 'pause' event.
...
...
common/lib/xmodule/xmodule/js/src/video/03_video_player.js
View file @
450dfe17
...
...
@@ -17,13 +17,24 @@ function (HTML5Video, Resizer) {
methodsDict
=
{
duration
:
duration
,
handlePlaybackQualityChange
:
handlePlaybackQualityChange
,
// Added for finer graded seeking control.
// Please see:
// https://developers.google.com/youtube/js_api_reference#Events
isBuffering
:
isBuffering
,
// https://developers.google.com/youtube/js_api_reference#cueVideoById
isCued
:
isCued
,
isEnded
:
isEnded
,
isPlaying
:
isPlaying
,
isUnstarted
:
isUnstarted
,
log
:
log
,
onCaptionSeek
:
onSeek
,
onEnded
:
onEnded
,
onPause
:
onPause
,
onPlay
:
onPlay
,
runTimer
:
runTimer
,
stopTimer
:
stopTimer
,
onPlaybackQualityChange
:
onPlaybackQualityChange
,
onReady
:
onReady
,
onSlideSeek
:
onSeek
,
...
...
@@ -54,7 +65,17 @@ function (HTML5Video, Resizer) {
// Functions which will be accessible via 'state' object. When called,
// these functions will get the 'state' object as a context.
function
_makeFunctionsPublic
(
state
)
{
var
debouncedF
=
_
.
debounce
(
function
(
params
)
{
return
onSeek
.
call
(
this
,
params
);
}.
bind
(
state
),
300
);
state
.
bindTo
(
methodsDict
,
state
.
videoPlayer
,
state
);
state
.
videoPlayer
.
onSlideSeek
=
debouncedF
;
state
.
videoPlayer
.
onCaptionSeek
=
debouncedF
;
}
// function _initialize(state)
...
...
@@ -79,10 +100,10 @@ function (HTML5Video, Resizer) {
state
.
videoPlayer
.
player
.
setVolume
(
state
.
currentVolume
);
});
if
(
state
.
videoType
===
'youtube'
)
{
if
(
state
.
isYoutubeType
()
)
{
state
.
videoPlayer
.
PlayerState
=
YT
.
PlayerState
;
state
.
videoPlayer
.
PlayerState
.
UNSTARTED
=
-
1
;
}
else
{
// if (state.videoType === 'html5') {
}
else
{
state
.
videoPlayer
.
PlayerState
=
HTML5Video
.
PlayerState
;
}
...
...
@@ -139,7 +160,7 @@ function (HTML5Video, Resizer) {
_updateVcrAndRegion
(
state
);
},
false
);
}
else
{
// if (state.videoType === 'youtube') {
}
else
{
youTubeId
=
state
.
youtubeId
();
state
.
videoPlayer
.
player
=
new
YT
.
Player
(
state
.
id
,
{
...
...
@@ -305,8 +326,8 @@ function (HTML5Video, Resizer) {
// This function gets the video's current play position in time
// (currentTime) and its duration.
// It is called at a regular interval when the video is playing.
function
update
()
{
this
.
videoPlayer
.
currentTime
=
this
.
videoPlayer
.
player
.
getCurrentTime
();
function
update
(
time
)
{
this
.
videoPlayer
.
currentTime
=
t
ime
||
t
his
.
videoPlayer
.
player
.
getCurrentTime
();
if
(
isFinite
(
this
.
videoPlayer
.
currentTime
))
{
this
.
videoPlayer
.
updatePlayTime
(
this
.
videoPlayer
.
currentTime
);
...
...
@@ -339,7 +360,7 @@ function (HTML5Video, Resizer) {
!
(
this
.
browserIsFirefox
&&
newSpeed
===
'1.0'
&&
this
.
videoType
===
'youtube'
this
.
isYoutubeType
()
)
)
{
this
.
videoPlayer
.
player
.
setPlaybackRate
(
newSpeed
);
...
...
@@ -404,6 +425,7 @@ function (HTML5Video, Resizer) {
return
;
}
this
.
el
.
off
(
'play.seek'
);
this
.
videoPlayer
.
log
(
'seek_video'
,
{
...
...
@@ -420,24 +442,49 @@ function (HTML5Video, Resizer) {
this
.
videoPlayer
.
stopAtEndTime
=
false
;
}
this
.
videoPlayer
.
player
.
seekTo
(
newTime
,
true
);
if
(
this
.
videoPlayer
.
isPlaying
())
{
clearInterval
(
this
.
videoPlayer
.
updateInterval
);
this
.
videoPlayer
.
updateInterval
=
setInterval
(
this
.
videoPlayer
.
update
,
200
);
setTimeout
(
this
.
videoPlayer
.
update
,
0
);
this
.
videoPlayer
.
stopTimer
();
}
else
{
this
.
videoPlayer
.
currentTime
=
newTime
;
}
var
isUnplayed
=
this
.
videoPlayer
.
isUnstarted
()
||
this
.
videoPlayer
.
isCued
();
this
.
videoPlayer
.
updatePlayTime
(
newTime
);
// Use `cueVideoById` method for youtube video that is not played before.
if
(
isUnplayed
&&
this
.
isYoutubeType
())
{
this
.
videoPlayer
.
player
.
cueVideoById
(
this
.
youtubeId
(),
newTime
);
}
else
{
// Youtube video cannot be rewinded during bufferization, so wait to
// finish bufferization and then rewind the video.
if
(
this
.
isYoutubeType
()
&&
this
.
videoPlayer
.
isBuffering
())
{
this
.
el
.
on
(
'play.seek'
,
function
()
{
this
.
videoPlayer
.
player
.
seekTo
(
newTime
,
true
);
}.
bind
(
this
));
}
else
{
// Otherwise, just seek the video
this
.
videoPlayer
.
player
.
seekTo
(
newTime
,
true
);
}
}
this
.
videoPlayer
.
updatePlayTime
(
newTime
,
true
);
this
.
el
.
trigger
(
'seek'
,
arguments
);
}
function
runTimer
()
{
if
(
!
this
.
videoPlayer
.
updateInterval
)
{
this
.
videoPlayer
.
updateInterval
=
window
.
setInterval
(
this
.
videoPlayer
.
update
,
200
);
this
.
videoPlayer
.
update
();
}
}
function
stopTimer
()
{
window
.
clearInterval
(
this
.
videoPlayer
.
updateInterval
);
delete
this
.
videoPlayer
.
updateInterval
;
}
function
onEnded
()
{
var
time
=
this
.
videoPlayer
.
duration
();
...
...
@@ -466,8 +513,7 @@ function (HTML5Video, Resizer) {
}
);
clearInterval
(
this
.
videoPlayer
.
updateInterval
);
delete
this
.
videoPlayer
.
updateInterval
;
this
.
videoPlayer
.
stopTimer
();
this
.
trigger
(
'videoControl.pause'
,
null
);
this
.
saveState
(
true
);
...
...
@@ -482,14 +528,7 @@ function (HTML5Video, Resizer) {
}
);
if
(
!
this
.
videoPlayer
.
updateInterval
)
{
this
.
videoPlayer
.
updateInterval
=
setInterval
(
this
.
videoPlayer
.
update
,
200
);
this
.
videoPlayer
.
update
();
}
this
.
videoPlayer
.
runTimer
();
this
.
trigger
(
'videoControl.play'
,
null
);
this
.
trigger
(
'videoProgressSlider.notifyThroughHandleEnd'
,
{
end
:
false
...
...
@@ -558,7 +597,7 @@ function (HTML5Video, Resizer) {
// https://github.com/edx/edx-platform/pull/2841
if
(
(
this
.
isHtml5Mode
()
||
availablePlaybackRates
.
length
>
1
)
&&
this
.
videoType
===
'youtube'
this
.
isYoutubeType
()
)
{
if
(
availablePlaybackRates
.
length
===
1
&&
!
this
.
isTouch
)
{
// This condition is needed in cases when Firefox version is
...
...
@@ -620,20 +659,34 @@ function (HTML5Video, Resizer) {
}
function
onStateChange
(
event
)
{
this
.
el
.
removeClass
([
'is-unstarted'
,
'is-playing'
,
'is-paused'
,
'is-buffered'
,
'is-ended'
,
'is-cued'
].
join
(
' '
));
switch
(
event
.
data
)
{
case
this
.
videoPlayer
.
PlayerState
.
UNSTARTED
:
this
.
el
.
addClass
(
'is-unstarted'
);
this
.
videoPlayer
.
onUnstarted
();
break
;
case
this
.
videoPlayer
.
PlayerState
.
PLAYING
:
this
.
el
.
addClass
(
'is-playing'
);
this
.
videoPlayer
.
onPlay
();
break
;
case
this
.
videoPlayer
.
PlayerState
.
PAUSED
:
this
.
el
.
addClass
(
'is-paused'
);
this
.
videoPlayer
.
onPause
();
break
;
case
this
.
videoPlayer
.
PlayerState
.
BUFFERING
:
this
.
el
.
addClass
(
'is-buffered'
);
this
.
el
.
trigger
(
'buffering'
);
break
;
case
this
.
videoPlayer
.
PlayerState
.
ENDED
:
this
.
el
.
addClass
(
'is-ended'
);
this
.
videoPlayer
.
onEnded
();
break
;
case
this
.
videoPlayer
.
PlayerState
.
CUED
:
this
.
el
.
addClass
(
'is-cued'
);
this
.
videoPlayer
.
player
.
seekTo
(
this
.
videoPlayer
.
seekToTimeOnCued
,
true
);
// We need to call play() explicitly because after the call
// to functions cueVideoById() followed by seekTo() the video
...
...
@@ -711,12 +764,12 @@ function (HTML5Video, Resizer) {
return
time
;
}
function
updatePlayTime
(
time
)
{
function
updatePlayTime
(
time
,
skip_seek
)
{
var
videoPlayer
=
this
.
videoPlayer
,
duration
=
this
.
videoPlayer
.
duration
(),
youTubeId
;
if
(
duration
>
0
&&
videoPlayer
.
goToStartTime
)
{
if
(
duration
>
0
&&
videoPlayer
.
goToStartTime
&&
!
skip_seek
)
{
videoPlayer
.
goToStartTime
=
false
;
// The duration might have changed. Update the start-end time region to
...
...
@@ -746,7 +799,7 @@ function (HTML5Video, Resizer) {
//
// HTML5 video sources play fine from start-time in both Chrome
// and Firefox.
if
(
this
.
browserIsFirefox
&&
this
.
videoType
===
'youtube'
)
{
if
(
this
.
browserIsFirefox
&&
this
.
isYoutubeType
()
)
{
youTubeId
=
this
.
youtubeId
();
// When we will call cueVideoById() for some strange reason
...
...
@@ -794,10 +847,27 @@ function (HTML5Video, Resizer) {
}
function
isPlaying
()
{
var
playerState
=
this
.
videoPlayer
.
player
.
getPlayerState
(),
PLAYING
=
this
.
videoPlayer
.
PlayerState
.
PLAYING
;
var
playerState
=
this
.
videoPlayer
.
player
.
getPlayerState
();
return
playerState
===
this
.
videoPlayer
.
PlayerState
.
PLAYING
;
}
return
playerState
===
PLAYING
;
function
isBuffering
()
{
var
playerState
=
this
.
videoPlayer
.
player
.
getPlayerState
();
return
playerState
===
this
.
videoPlayer
.
PlayerState
.
BUFFERING
;
}
function
isCued
()
{
var
playerState
=
this
.
videoPlayer
.
player
.
getPlayerState
();
return
playerState
===
this
.
videoPlayer
.
PlayerState
.
CUED
;
}
function
isUnstarted
()
{
var
playerState
=
this
.
videoPlayer
.
player
.
getPlayerState
();
return
playerState
===
this
.
videoPlayer
.
PlayerState
.
UNSTARTED
;
}
/*
...
...
@@ -844,7 +914,7 @@ function (HTML5Video, Resizer) {
// might differ by one or two seconds against the actual time as will
// be reported later on by the player.getDuration() API function.
if
(
!
isFinite
(
dur
)
||
dur
<=
0
)
{
if
(
this
.
videoType
===
'youtube'
)
{
if
(
this
.
isYoutubeType
()
)
{
dur
=
this
.
getDuration
();
}
}
...
...
@@ -873,9 +943,9 @@ function (HTML5Video, Resizer) {
});
}
if
(
this
.
videoType
===
'youtube'
)
{
if
(
this
.
isYoutubeType
()
)
{
logInfo
.
code
=
this
.
youtubeId
();
}
else
if
(
this
.
videoType
===
'html5'
)
{
}
else
{
logInfo
.
code
=
'html5'
;
}
...
...
common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js
View file @
450dfe17
...
...
@@ -177,15 +177,26 @@ function () {
}
function
onSlide
(
event
,
ui
)
{
var
time
=
ui
.
value
,
duration
=
this
.
videoPlayer
.
duration
();
this
.
videoProgressSlider
.
frozen
=
true
;
// Remember the seek to value so that we don't repeat ourselves on the
// 'stop' slider event.
this
.
videoProgressSlider
.
lastSeekValue
=
ui
.
value
;
this
.
videoProgressSlider
.
lastSeekValue
=
time
;
this
.
trigger
(
'videoControl.updateVcrVidTime'
,
{
time
:
time
,
duration
:
duration
}
);
this
.
trigger
(
'videoPlayer.onSlideSeek'
,
{
'type'
:
'onSlideSeek'
,
'time'
:
ui
.
valu
e
}
{
'type'
:
'onSlideSeek'
,
'time'
:
tim
e
}
);
// ARIA
...
...
lms/djangoapps/courseware/features/common.py
View file @
450dfe17
...
...
@@ -35,7 +35,7 @@ def configure_screenshots_for_all_steps(_step, action):
else
:
raise
ValueError
(
'Parameter `action` should be one of "enable" or "disable".'
)
@world.absorb
def
capture_screenshot_before_after
(
func
):
"""
A decorator that will take a screenshot before and after the applied
...
...
lms/djangoapps/courseware/features/video.feature
View file @
450dfe17
...
...
@@ -2,18 +2,6 @@
Feature
:
LMS.Video component
As a student, I want to view course videos in LMS
# 1 Disabled 4/8/14 after intermittent failures in master
#Scenario: Video component stores position correctly when page is reloaded
# Given the course has a Video component in "Youtube" mode
# When the video has rendered in "Youtube" mode
# And I click video button "play"
# And I click video button "pause"
# Then I seek video to "10" seconds
# And I click video button "play"
# And I click video button "pause"
# And I reload the page with video
# Then I see video slider at "10" seconds
# 1
Scenario
:
Video component is fully rendered in the LMS in HTML5 mode
Given
the course has a Video component in
"HTML5"
mode
...
...
@@ -267,7 +255,106 @@ Feature: LMS.Video component
Then
the video has rendered in
"HTML5"
mode
And
the video does not show the captions
# 20 Disabled 4/8/14 after intermittent failures in master
# 20
Scenario
:
Start time works for Youtube video
Given
I am registered for the course
"test_course"
And it has a video in "Youtube" mode
:
|
start_time
|
|
00:00:10
|
And
I click video button
"play"
Then I see video slider at "0
:
10"
position
# 21
Scenario
:
End time works for Youtube video
Given
I am registered for the course
"test_course"
And it has a video in "Youtube" mode
:
|
end_time
|
|
00:00:02
|
And
I click video button
"play"
And
I wait
"5"
seconds
Then I see video slider at "0
:
02"
position
# 22
Scenario
:
Youtube video with end-time at 1
:
00 and the video starts playing at 0
:
58
Given
I am registered for the course
"test_course"
And it has a video in "Youtube" mode
:
|
end_time
|
|
00:01:00
|
And
I wait for video controls appear
And I seek video to "0
:
58"
position
And
I click video button
"play"
And
I wait
"5"
seconds
Then I see video slider at "1
:
00"
position
# 23
Scenario
:
Start time and end time work together for Youtube video
Given
I am registered for the course
"test_course"
And it has a video in "Youtube" mode
:
|
start_time
|
end_time
|
|
00:00:10
|
00:00:12
|
And
I click video button
"play"
Then I see video slider at "0
:
10"
position
And
I wait
"5"
seconds
Then I see video slider at "0
:
12"
position
# 24
Scenario
:
Youtube video after pausing at end time video plays to the end from end time
Given
I am registered for the course
"test_course"
And it has a video in "Youtube" mode
:
|
start_time
|
end_time
|
|
00:01:51
|
00:01:52
|
And
I click video button
"play"
And
I wait
"5"
seconds
# The end time is 00:01:52.
Then I see video slider at "1
:
52"
position
And
I click video button
"play"
And
I wait
"8"
seconds
# The default video length is 00:01:55.
Then I see video slider at "1
:
55"
position
# 25
Scenario
:
Youtube video with end-time at 0
:
32 and start-time at 0
:
30, the video starts playing from 0
:
28
Given
I am registered for the course
"test_course"
And it has a video in "Youtube" mode
:
|
start_time
|
end_time
|
|
00:00:30
|
00:00:32
|
And
I wait for video controls appear
And I seek video to "0
:
28"
position
And
I click video button
"play"
And
I wait
"8"
seconds
Then I see video slider at "0
:
32"
position
# 26
Scenario
:
Youtube video with end-time at 1
:
00, the video starts playing from 1
:
52
Given
I am registered for the course
"test_course"
And it has a video in "Youtube" mode
:
|
end_time
|
|
00:01:00
|
And
I wait for video controls appear
And I seek video to "1
:
52"
position
And
I click video button
"play"
And
I wait
"5"
seconds
# Video stops at the end.
Then I see video slider at "1
:
55"
position
# 27
@skip_firefox
Scenario
:
Quality button appears on play
Given
the course has a Video component in
"Youtube"
mode
Then
I see video button
"quality"
is hidden
And
I click video button
"play"
Then
I see video button
"quality"
is visible
# 28
@skip_firefox
Scenario
:
Quality button works correctly
Given
the course has a Video component in
"Youtube"
mode
And
I click video button
"play"
And
I see video button
"quality"
is inactive
And
I click video button
"quality"
Then
I see video button
"quality"
is active
# 29 Disabled 4/8/14 after intermittent failures in master
#Scenario: Transcripts are available on different speeds of Flash mode
# Given I am registered for the course "test_course"
# And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
...
...
@@ -282,7 +369,7 @@ Feature: LMS.Video component
# Then I select the "1.25" speed
# And I see "Hi, welcome to Edx." text in the captions
#
21
Disabled 4/8/14 after intermittent failures in master
#
30
Disabled 4/8/14 after intermittent failures in master
#Scenario: Elapsed time calculates correctly on different speeds of Flash mode
# Given I am registered for the course "test_course"
# And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
...
...
@@ -298,19 +385,14 @@ Feature: LMS.Video component
# And I click video button "pause"
# And I click on caption line "2", video module shows elapsed time "4"
# 27
@skip_firefox
Scenario
:
Quality button appears on play
Given
the course has a Video component in
"Youtube"
mode
Then
I see video button
"quality"
is hidden
And
I click video button
"play"
Then
I see video button
"quality"
is visible
# 28
@skip_firefox
Scenario
:
Quality button works correctly
Given
the course has a Video component in
"Youtube"
mode
And
I click video button
"play"
And
I see video button
"quality"
is inactive
And
I click video button
"quality"
Then
I see video button
"quality"
is active
# 31 Disabled 4/8/14 after intermittent failures in master
#Scenario: Video component stores position correctly when page is reloaded
# Given the course has a Video component in "Youtube" mode
# When the video has rendered in "Youtube" mode
# And I click video button "play"
# And I click video button "pause"
# Then I seek video to "0:10" position
# And I click video button "play"
# And I click video button "pause"
# And I reload the page with video
# Then I see video slider at "0:10" position
lms/djangoapps/courseware/features/video.py
View file @
450dfe17
...
...
@@ -482,6 +482,7 @@ def check_captions(_step):
@step
(
'I select language with code "([^"]*)"$'
)
def
select_language
(
_step
,
code
):
world
.
wait_for_visible
(
'.video-controls'
)
# Make sure that all ajax requests that affects the language menu are finished.
# For example, request to get new translation etc.
world
.
wait_for_ajax_complete
()
...
...
@@ -506,16 +507,19 @@ def select_language(_step, code):
@step
(
'I click video button "([^"]*)"$'
)
def
click_button
(
_step
,
button
):
world
.
css_click
(
VIDEO_BUTTONS
[
button
])
world
.
wait_for_ajax_complete
()
if
button
==
"play"
:
# Needs to wait for video buffrization
world
.
wait_for
(
func
=
lambda
_
:
world
.
css_has_class
(
'.video'
,
'is-playing'
)
and
world
.
is_css_present
(
VIDEO_BUTTONS
[
'pause'
]),
timeout
=
30
)
world
.
wait_for_ajax_complete
()
@step
(
'I see video slider at "([^"]*)" seconds$'
)
def
start_playing_video_from_n_seconds
(
_step
,
position
):
world
.
wait_for
(
func
=
lambda
_
:
elapsed_time
()
>
0
,
timeout
=
30
)
@step
(
'I see video slider at "([^"]*)" position$'
)
def
start_playing_video_from_n_seconds
(
_step
,
time_str
):
position
=
parse_time_str
(
time_str
)
actual_position
=
elapsed_time
()
assert_equal
(
actual_position
,
int
(
position
),
"Current position is {}, but should be {}"
.
format
(
actual_position
,
position
))
...
...
@@ -530,12 +534,21 @@ def i_see_duration(_step, position):
assert
duration
()
==
parse_time_str
(
position
)
@step
(
'I seek video to "([^"]*)" seconds$'
)
def
seek_video_to_n_seconds
(
_step
,
seconds
):
time
=
float
(
seconds
.
strip
())
jsCode
=
"$('.video').data('video-player-state').videoPlayer.onSlideSeek({{time: {0:f}}})"
.
format
(
time
)
@step
(
'I wait for video controls appear$'
)
def
controls_appear
(
_step
):
world
.
wait_for_visible
(
'.video-controls'
)
@step
(
'I seek video to "([^"]*)" position$'
)
def
seek_video_to_n_seconds
(
_step
,
time_str
):
time
=
parse_time_str
(
time_str
)
jsCode
=
"$('.video').data('video-player-state').videoPlayer.onSlideSeek({{time: {0}}})"
.
format
(
time
)
world
.
browser
.
execute_script
(
jsCode
)
_step
.
given
(
'I see video slider at "{}" seconds'
.
format
(
seconds
))
world
.
wait_for
(
func
=
lambda
_
:
world
.
retry_on_exception
(
lambda
:
elapsed_time
()
==
time
and
not
world
.
css_has_class
(
'.video'
,
'is-buffering'
)),
timeout
=
30
)
_step
.
given
(
'I see video slider at "{0}" position'
.
format
(
time_str
))
@step
(
'I have a "([^"]*)" transcript file in assets$'
)
...
...
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