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
5bacfcc3
Commit
5bacfcc3
authored
Jan 23, 2014
by
Anton Stupak
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2045 from edx/anton/video-merge-fields
Merge "video sources" and "download video" into the same field
parents
636122c0
645007f9
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
375 additions
and
121 deletions
+375
-121
CHANGELOG.rst
+3
-0
cms/djangoapps/contentstore/features/video-editor.py
+1
-1
cms/static/js/views/metadata.js
+0
-1
common/lib/xmodule/xmodule/tests/test_video.py
+15
-9
common/lib/xmodule/xmodule/video_module.py
+46
-3
lms/djangoapps/courseware/tests/test_video_mongo.py
+309
-107
lms/djangoapps/courseware/tests/test_video_xml.py
+1
-0
No files found.
CHANGELOG.rst
View file @
5bacfcc3
...
...
@@ -5,6 +5,9 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
Blades: Change the download video field to a dropdown that will allow students
to download the first source listed in the alternate sources. BLD-364.
Blades: Change the track field to a dropdown that will allow students
to download the transcript of the video without timecodes. BLD-368.
...
...
cms/djangoapps/contentstore/features/video-editor.py
View file @
5bacfcc3
...
...
@@ -40,12 +40,12 @@ def correct_video_settings(_step):
# advanced
[
'Display Name'
,
'Video'
,
False
],
[
'Download Video'
,
''
,
False
],
[
'End Time'
,
'00:00:00'
,
False
],
[
'HTML5 Transcript'
,
''
,
False
],
[
'Show Transcript'
,
'True'
,
False
],
[
'Start Time'
,
'00:00:00'
,
False
],
[
'Transcript Download Allowed'
,
'False'
,
False
],
[
'Video Download Allowed'
,
'False'
,
False
],
[
'Video Sources'
,
''
,
False
],
[
'Youtube ID'
,
'OEoXaMPEzfM'
,
False
],
[
'Youtube ID for .75x speed'
,
''
,
False
],
...
...
cms/static/js/views/metadata.js
View file @
5bacfcc3
...
...
@@ -106,7 +106,6 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
}
},
getValueFromEditor
:
function
()
{
return
this
.
$el
.
find
(
'#'
+
this
.
uniqueId
).
val
();
},
...
...
common/lib/xmodule/xmodule/tests/test_video.py
View file @
5bacfcc3
...
...
@@ -187,6 +187,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
show_captions="false"
download_track="true"
download_video="true"
start_time="00:00:01"
end_time="00:01:00">
<source src="http://www.example.com/source.mp4"/>
...
...
@@ -207,6 +208,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'youtube_id_1_0'
:
'p2Q6BrNhdh8'
,
'youtube_id_1_25'
:
'1EeWXzPdhSA'
,
'youtube_id_1_5'
:
'rABDYkeK0x8'
,
'download_video'
:
True
,
'show_captions'
:
False
,
'start_time'
:
datetime
.
timedelta
(
seconds
=
1
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
60
),
...
...
@@ -224,6 +226,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
show_captions="false"
download_track="false"
start_time="00:00:01"
download_video="false"
end_time="00:01:00">
<source src="http://www.example.com/source.mp4"/>
<track src="http://www.example.com/track"/>
...
...
@@ -240,7 +243,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
60
),
'track'
:
'http://www.example.com/track'
,
'download_track'
:
False
,
'
source'
:
'http://www.example.com/source.mp4'
,
'
download_video'
:
False
,
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'data'
:
''
})
...
...
@@ -269,7 +272,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
''
,
'download_track'
:
False
,
'
source'
:
'http://www.example.com/source.mp4'
,
'
download_video'
:
False
,
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'data'
:
''
})
...
...
@@ -291,7 +294,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
''
,
'download_track'
:
False
,
'
source'
:
''
,
'
download_video'
:
False
,
'html5_sources'
:
[],
'data'
:
''
})
...
...
@@ -306,7 +309,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
<video display_name=""display_name""
html5_sources="["source_1", "source_2"]"
show_captions="false"
source=""http://download_video"
"
download_video="true
"
sub=""html5_subtitles""
track=""http://download_track""
download_track="true"
...
...
@@ -327,7 +330,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
'http://download_track'
,
'download_track'
:
True
,
'
source'
:
'http://download_video'
,
'
download_video'
:
True
,
'html5_sources'
:
[
"source_1"
,
"source_2"
],
'data'
:
''
})
...
...
@@ -350,7 +353,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
''
,
'download_track'
:
False
,
'
source'
:
''
,
'
download_video'
:
False
,
'html5_sources'
:
[],
'data'
:
''
})
...
...
@@ -364,6 +367,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
<video display_name="Test Video"
youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
show_captions="false"
source="http://www.example.com/source.mp4"
from="00:00:01"
to="00:01:00">
<source src="http://www.example.com/source.mp4"/>
...
...
@@ -382,7 +386,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'track'
:
'http://www.example.com/track'
,
'download_track'
:
True
,
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'data'
:
''
'data'
:
''
,
})
def
test_old_video_data
(
self
):
...
...
@@ -473,10 +477,11 @@ class VideoExportTestCase(unittest.TestCase):
desc
.
track
=
'http://www.example.com/track'
desc
.
download_track
=
True
desc
.
html5_sources
=
[
'http://www.example.com/source.mp4'
,
'http://www.example.com/source.ogg'
]
desc
.
download_video
=
True
xml
=
desc
.
definition_to_xml
(
None
)
# We don't use the `resource_fs` parameter
expected
=
etree
.
fromstring
(
'''
\
<video url_name="SampleProblem1" start_time="0:00:01" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" end_time="0:01:00" download_track="true">
<video url_name="SampleProblem1" start_time="0:00:01" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" end_time="0:01:00" download_
video="true" download_
track="true">
<source src="http://www.example.com/source.mp4"/>
<source src="http://www.example.com/source.ogg"/>
<track src="http://www.example.com/track"/>
...
...
@@ -501,10 +506,11 @@ class VideoExportTestCase(unittest.TestCase):
desc
.
track
=
'http://www.example.com/track'
desc
.
download_track
=
True
desc
.
html5_sources
=
[
'http://www.example.com/source.mp4'
,
'http://www.example.com/source.ogg'
]
desc
.
download_video
=
True
xml
=
desc
.
definition_to_xml
(
None
)
# We don't use the `resource_fs` parameter
expected
=
etree
.
fromstring
(
'''
\
<video url_name="SampleProblem1" start_time="0:00:05" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" download_track="true">
<video url_name="SampleProblem1" start_time="0:00:05" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" download_
video="true" download_
track="true">
<source src="http://www.example.com/source.mp4"/>
<source src="http://www.example.com/source.ogg"/>
<track src="http://www.example.com/track"/>
...
...
common/lib/xmodule/xmodule/video_module.py
View file @
5bacfcc3
...
...
@@ -98,12 +98,20 @@ class VideoFields(object):
)
#front-end code of video player checks logical validity of (start_time, end_time) pair.
# `source` is deprecated field and should not be used in future.
# `download_video` is used instead.
source
=
String
(
help
=
"The external URL to download the video.
This appears as a link beneath the video.
"
,
help
=
"The external URL to download the video."
,
display_name
=
"Download Video"
,
scope
=
Scope
.
settings
,
default
=
""
)
download_video
=
Boolean
(
help
=
"Show a link beneath the video to allow students to download the video. Note: You must add at least one video source below."
,
display_name
=
"Video Download Allowed"
,
scope
=
Scope
.
settings
,
default
=
False
)
html5_sources
=
List
(
help
=
"A list of filenames to be used with HTML5 video. The first supported filetype will be displayed."
,
display_name
=
"Video Sources"
,
...
...
@@ -181,7 +189,12 @@ class VideoModule(VideoFields, XModule):
get_ext
=
lambda
filename
:
filename
.
rpartition
(
'.'
)[
-
1
]
sources
=
{
get_ext
(
src
):
src
for
src
in
self
.
html5_sources
}
if
self
.
download_video
:
if
self
.
source
:
sources
[
'main'
]
=
self
.
source
elif
self
.
html5_sources
:
sources
[
'main'
]
=
self
.
html5_sources
[
0
]
if
self
.
download_track
:
if
self
.
track
:
...
...
@@ -281,6 +294,14 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
If `track` field exists show `track` field on front-end as not-editable
but clearable. Dropdown `download_track` is a new field and it has value
True.
`source` is deprecated field.
a) If `source` exists and `source` is not `html5_sources`: show `source`
field on front-end as not-editable but clearable. Dropdown is a new
field `download_video` and it has value True.
b) If `source` is cleared it is not shown anymore.
c) If `source` exists and `source` in `html5_sources`, do not show `source`
field. `download_video` field has value True.
'''
super
(
VideoDescriptor
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
# For backwards compatibility -- if we've got XML data, parse
...
...
@@ -290,22 +311,44 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
self
.
_field_data
.
set_many
(
self
,
field_data
)
del
self
.
data
editable_fields
=
self
.
editable_metadata_fields
self
.
track_visible
=
False
if
self
.
track
:
self
.
track_visible
=
True
download_track
=
self
.
editable_metadata
_fields
[
'download_track'
]
download_track
=
editable
_fields
[
'download_track'
]
if
not
download_track
[
'explicitly_set'
]:
self
.
download_track
=
True
self
.
source_visible
=
False
if
self
.
source
:
# If `source` field value exist in the `html5_sources` field values,
# then delete `source` field value and use value from `html5_sources` field.
if
self
.
source
in
self
.
html5_sources
:
self
.
source
=
''
# Delete source field value.
self
.
download_video
=
True
else
:
# Otherwise, `source` field value will be used.
self
.
source_visible
=
True
download_video
=
editable_fields
[
'download_video'
]
if
not
download_video
[
'explicitly_set'
]:
self
.
download_video
=
True
@property
def
editable_metadata_fields
(
self
):
editable_fields
=
super
(
VideoDescriptor
,
self
)
.
editable_metadata_fields
if
hasattr
(
self
,
'track_visible'
):
if
self
.
track_visible
:
editable_fields
[
'track'
][
'non_editable'
]
=
True
else
:
editable_fields
.
pop
(
'track'
)
if
hasattr
(
self
,
'source_visible'
):
if
self
.
source_visible
:
editable_fields
[
'source'
][
'non_editable'
]
=
True
else
:
editable_fields
.
pop
(
'source'
)
return
editable_fields
@classmethod
...
...
@@ -359,6 +402,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
'end_time'
:
self
.
end_time
,
'sub'
:
self
.
sub
,
'download_track'
:
json
.
dumps
(
self
.
download_track
),
'download_video'
:
json
.
dumps
(
self
.
download_video
),
}
for
key
,
value
in
attrs
.
items
():
# Mild workaround to ensure that tests pass -- if a field
...
...
@@ -468,7 +512,6 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
sources
=
xml
.
findall
(
'source'
)
if
sources
:
field_data
[
'html5_sources'
]
=
[
ele
.
get
(
'src'
)
for
ele
in
sources
]
field_data
[
'source'
]
=
field_data
[
'html5_sources'
][
0
]
track
=
xml
.
find
(
'track'
)
if
track
is
not
None
:
...
...
lms/djangoapps/courseware/tests/test_video_mongo.py
View file @
5bacfcc3
...
...
@@ -47,7 +47,7 @@ class TestVideoYouTube(TestVideo):
METADATA
=
{}
def
test_video_constructor
(
self
):
"""Make sure that all parameters extracted correc
lt
y from xml"""
"""Make sure that all parameters extracted correc
tl
y from xml"""
context
=
self
.
item_module
.
render
(
'student_view'
)
.
content
sources
=
{
...
...
@@ -70,7 +70,7 @@ class TestVideoYouTube(TestVideo):
'youtube_streams'
:
_create_youtube_string
(
self
.
item_module
),
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
False
),
'yt_test_timeout'
:
1500
,
'yt_test_url'
:
'https://gdata.youtube.com/feeds/api/videos/'
'yt_test_url'
:
'https://gdata.youtube.com/feeds/api/videos/'
,
}
self
.
assertEqual
(
...
...
@@ -81,11 +81,11 @@ class TestVideoYouTube(TestVideo):
class
TestVideoNonYouTube
(
TestVideo
):
"""Integration tests: web client + mongo."""
DATA
=
"""
<video show_captions="true"
display_name="A Name"
sub="a_sub_file.srt.sjson"
download_video="true"
start_time="01:00:03" end_time="01:00:10"
>
<source src="example.mp4"/>
...
...
@@ -96,7 +96,6 @@ class TestVideoNonYouTube(TestVideo):
'data'
:
DATA
}
METADATA
=
{}
def
test_video_constructor
(
self
):
"""Make sure that if the 'youtube' attribute is omitted in XML, then
the template generates an empty string for the YouTube streams.
...
...
@@ -123,7 +122,7 @@ class TestVideoNonYouTube(TestVideo):
'youtube_streams'
:
'1.00:OEoXaMPEzfM'
,
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
True
),
'yt_test_timeout'
:
1500
,
'yt_test_url'
:
'https://gdata.youtube.com/feeds/api/videos/'
'yt_test_url'
:
'https://gdata.youtube.com/feeds/api/videos/'
,
}
self
.
assertEqual
(
...
...
@@ -132,104 +131,10 @@ class TestVideoNonYouTube(TestVideo):
)
class
TestVideoGetTranscriptsMethod
(
TestVideo
):
"""
Make sure that `get_transcript` method works correctly
"""
DATA
=
"""
<video show_captions="true"
display_name="A Name"
>
<source src="example.mp4"/>
<source src="example.webm"/>
</video>
"""
MODEL_DATA
=
{
'data'
:
DATA
}
METADATA
=
{}
def
test_good_transcript
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
good_sjson
=
_create_file
(
content
=
"""
{
"start": [
270,
2720
],
"end": [
2720,
5430
],
"text": [
"Hi, welcome to Edx.",
"Let's start with what is on your screen right now."
]
}
"""
)
_upload_file
(
good_sjson
,
self
.
item_module
.
location
)
subs_id
=
_get_subs_id
(
good_sjson
.
name
)
text
=
item
.
get_transcript
(
subs_id
)
expected_text
=
"Hi, welcome to Edx.
\n
Let's start with what is on your screen right now."
self
.
assertEqual
(
text
,
expected_text
)
def
test_not_found_error
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
with
self
.
assertRaises
(
NotFoundError
):
item
.
get_transcript
(
'wrong'
)
def
test_value_error
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
good_sjson
=
_create_file
(
content
=
"""
bad content
"""
)
_upload_file
(
good_sjson
,
self
.
item_module
.
location
)
subs_id
=
_get_subs_id
(
good_sjson
.
name
)
with
self
.
assertRaises
(
ValueError
):
item
.
get_transcript
(
subs_id
)
def
test_key_error
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
good_sjson
=
_create_file
(
content
=
"""
{
"start": [
270,
2720
],
"end": [
2720,
5430
]
}
"""
)
_upload_file
(
good_sjson
,
self
.
item_module
.
location
)
subs_id
=
_get_subs_id
(
good_sjson
.
name
)
with
self
.
assertRaises
(
KeyError
):
item
.
get_transcript
(
subs_id
)
class
TestGetHtmlMethod
(
BaseTestXmodule
):
"""
'''
Make sure that `get_html` works correctly.
"""
'''
CATEGORY
=
"video"
DATA
=
SOURCE_XML
METADATA
=
{}
...
...
@@ -274,7 +179,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
'track'
:
u'<track src="http://www.example.com/track"/>'
,
'sub'
:
u'a_sub_file.srt.sjson'
,
'expected_track_url'
:
None
,
}
}
,
]
expected_context
=
{
...
...
@@ -285,7 +190,6 @@ class TestGetHtmlMethod(BaseTestXmodule):
'end'
:
3610.0
,
'id'
:
None
,
'sources'
:
{
'main'
:
u'example.mp4'
,
u'mp4'
:
u'example.mp4'
,
u'webm'
:
u'example.webm'
},
...
...
@@ -295,14 +199,14 @@ class TestGetHtmlMethod(BaseTestXmodule):
'youtube_streams'
:
'1.00:OEoXaMPEzfM'
,
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
True
),
'yt_test_timeout'
:
1500
,
'yt_test_url'
:
'https://gdata.youtube.com/feeds/api/videos/'
'yt_test_url'
:
'https://gdata.youtube.com/feeds/api/videos/'
,
}
for
data
in
cases
:
DATA
=
SOURCE_XML
.
format
(
download_track
=
data
[
'download_track'
],
track
=
data
[
'track'
],
sub
=
data
[
'sub'
]
,
sub
=
data
[
'sub'
]
)
self
.
initialize_module
(
data
=
DATA
)
...
...
@@ -320,6 +224,104 @@ class TestGetHtmlMethod(BaseTestXmodule):
self
.
item_module
.
xmodule_runtime
.
render_template
(
'video.html'
,
expected_context
)
)
def
test_get_html_source
(
self
):
SOURCE_XML
=
"""
<video show_captions="true"
display_name="A Name"
sub="a_sub_file.srt.sjson" source="{source}"
download_video="{download_video}"
start_time="01:00:03" end_time="01:00:10"
>
{sources}
</video>
"""
cases
=
[
# self.download_video == True
{
'download_video'
:
'true'
,
'source'
:
'example_source.mp4'
,
'sources'
:
"""
<source src="example.mp4"/>
<source src="example.webm"/>
"""
,
'result'
:
{
'main'
:
u'example_source.mp4'
,
u'mp4'
:
u'example.mp4'
,
u'webm'
:
u'example.webm'
,
},
},
{
'download_video'
:
'true'
,
'source'
:
''
,
'sources'
:
"""
<source src="example.mp4"/>
<source src="example.webm"/>
"""
,
'result'
:
{
'main'
:
u'example.mp4'
,
u'mp4'
:
u'example.mp4'
,
u'webm'
:
u'example.webm'
,
},
},
{
'download_video'
:
'true'
,
'source'
:
''
,
'sources'
:
[],
'result'
:
{},
},
# self.download_video == False
{
'download_video'
:
'false'
,
'source'
:
'example_source.mp4'
,
'sources'
:
"""
<source src="example.mp4"/>
<source src="example.webm"/>
"""
,
'result'
:
{
u'mp4'
:
u'example.mp4'
,
u'webm'
:
u'example.webm'
,
},
},
]
expected_context
=
{
'data_dir'
:
getattr
(
self
,
'data_dir'
,
None
),
'caption_asset_path'
:
'/static/subs/'
,
'show_captions'
:
'true'
,
'display_name'
:
u'A Name'
,
'end'
:
3610.0
,
'id'
:
None
,
'sources'
:
None
,
'start'
:
3603.0
,
'sub'
:
u'a_sub_file.srt.sjson'
,
'track'
:
None
,
'youtube_streams'
:
'1.00:OEoXaMPEzfM'
,
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
True
),
'yt_test_timeout'
:
1500
,
'yt_test_url'
:
'https://gdata.youtube.com/feeds/api/videos/'
,
}
for
data
in
cases
:
DATA
=
SOURCE_XML
.
format
(
download_video
=
data
[
'download_video'
],
source
=
data
[
'source'
],
sources
=
data
[
'sources'
]
)
self
.
initialize_module
(
data
=
DATA
)
expected_context
.
update
({
'sources'
:
data
[
'result'
],
'id'
:
self
.
item_module
.
location
.
html_id
(),
})
context
=
self
.
item_module
.
render
(
'student_view'
)
.
content
self
.
assertEqual
(
context
,
self
.
item_module
.
xmodule_runtime
.
render_template
(
'video.html'
,
expected_context
)
)
class
TestVideoDescriptorInitialization
(
BaseTestXmodule
):
"""
...
...
@@ -332,6 +334,105 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
def
setUp
(
self
):
self
.
setup_course
();
def
test_source_not_in_html5sources
(
self
):
metadata
=
{
'source'
:
'http://example.org/video.mp4'
,
'html5_sources'
:
[
'http://youtu.be/OEoXaMPEzfM.mp4'
],
}
self
.
initialize_module
(
metadata
=
metadata
)
fields
=
self
.
item_descriptor
.
editable_metadata_fields
self
.
assertIn
(
'source'
,
fields
)
self
.
assertEqual
(
self
.
item_module
.
source
,
'http://example.org/video.mp4'
)
self
.
assertTrue
(
self
.
item_module
.
download_video
)
self
.
assertTrue
(
self
.
item_module
.
source_visible
)
def
test_source_in_html5sources
(
self
):
metadata
=
{
'source'
:
'http://example.org/video.mp4'
,
'html5_sources'
:
[
'http://example.org/video.mp4'
],
}
self
.
initialize_module
(
metadata
=
metadata
)
fields
=
self
.
item_descriptor
.
editable_metadata_fields
self
.
assertNotIn
(
'source'
,
fields
)
self
.
assertTrue
(
self
.
item_module
.
download_video
)
self
.
assertFalse
(
self
.
item_module
.
source_visible
)
@patch
(
'xmodule.x_module.XModuleDescriptor.editable_metadata_fields'
,
new_callable
=
PropertyMock
)
def
test_download_video_is_explicitly_set
(
self
,
mock_editable_fields
):
mock_editable_fields
.
return_value
=
{
'download_video'
:
{
'default_value'
:
False
,
'explicitly_set'
:
True
,
'display_name'
:
'Video Download Allowed'
,
'help'
:
'Show a link beneath the video to allow students to download the video.'
,
'type'
:
'Boolean'
,
'value'
:
False
,
'field_name'
:
'download_video'
,
'options'
:
[
{
'display_name'
:
"True"
,
"value"
:
True
},
{
'display_name'
:
"False"
,
"value"
:
False
}
],
},
'html5_sources'
:
{
'default_value'
:
[],
'explicitly_set'
:
False
,
'display_name'
:
'Video Sources'
,
'help'
:
'A list of filenames to be used with HTML5 video.'
,
'type'
:
'List'
,
'value'
:
[
u'http://youtu.be/OEoXaMPEzfM.mp4'
],
'field_name'
:
'html5_sources'
,
'options'
:
[],
},
'source'
:
{
'default_value'
:
''
,
'explicitly_set'
:
False
,
'display_name'
:
'Download Video'
,
'help'
:
'The external URL to download the video.'
,
'type'
:
'Generic'
,
'value'
:
u'http://example.org/video.mp4'
,
'field_name'
:
'source'
,
'options'
:
[],
},
'track'
:
{
'default_value'
:
''
,
'explicitly_set'
:
False
,
'display_name'
:
'Download Transcript'
,
'help'
:
'The external URL to download the timed transcript track.'
,
'type'
:
'Generic'
,
'value'
:
u''
,
'field_name'
:
'track'
,
'options'
:
[],
},
}
metadata
=
{
'track'
:
''
,
'source'
:
'http://example.org/video.mp4'
,
'html5_sources'
:
[
'http://youtu.be/OEoXaMPEzfM.mp4'
],
}
self
.
initialize_module
(
metadata
=
metadata
)
fields
=
self
.
item_descriptor
.
editable_metadata_fields
self
.
assertIn
(
'source'
,
fields
)
self
.
assertFalse
(
self
.
item_module
.
download_video
)
self
.
assertTrue
(
self
.
item_module
.
source_visible
)
def
test_source_is_empty
(
self
):
metadata
=
{
'source'
:
''
,
'html5_sources'
:
[
'http://youtu.be/OEoXaMPEzfM.mp4'
],
}
self
.
initialize_module
(
metadata
=
metadata
)
fields
=
self
.
item_descriptor
.
editable_metadata_fields
self
.
assertNotIn
(
'source'
,
fields
)
self
.
assertFalse
(
self
.
item_module
.
download_video
)
def
test_track_is_not_empty
(
self
):
metatdata
=
{
'track'
:
'http://example.org/track'
,
...
...
@@ -359,7 +460,7 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
'options'
:
[
{
'display_name'
:
"True"
,
"value"
:
True
},
{
'display_name'
:
"False"
,
"value"
:
False
}
]
]
,
},
'track'
:
{
'default_value'
:
''
,
...
...
@@ -369,10 +470,21 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
'type'
:
'Generic'
,
'value'
:
u'http://example.org/track'
,
'field_name'
:
'track'
,
'options'
:
[]
'options'
:
[],
},
'source'
:
{
'default_value'
:
''
,
'explicitly_set'
:
False
,
'display_name'
:
'Download Video'
,
'help'
:
'The external URL to download the video.'
,
'type'
:
'Generic'
,
'value'
:
u''
,
'field_name'
:
'source'
,
'options'
:
[],
},
}
metadata
=
{
'source'
:
''
,
'track'
:
'http://example.org/track'
,
}
...
...
@@ -399,6 +511,96 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
self
.
assertFalse
(
self
.
item_module
.
track_visible
)
class
TestVideoGetTranscriptsMethod
(
TestVideo
):
"""
Make sure that `get_transcript` method works correctly
"""
DATA
=
"""
<video show_captions="true"
display_name="A Name"
>
<source src="example.mp4"/>
<source src="example.webm"/>
</video>
"""
MODEL_DATA
=
{
'data'
:
DATA
}
METADATA
=
{}
def
test_good_transcript
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
good_sjson
=
_create_file
(
content
=
"""
{
"start": [
270,
2720
],
"end": [
2720,
5430
],
"text": [
"Hi, welcome to Edx.",
"Let's start with what is on your screen right now."
]
}
"""
)
_upload_file
(
good_sjson
,
self
.
item_module
.
location
)
subs_id
=
_get_subs_id
(
good_sjson
.
name
)
text
=
item
.
get_transcript
(
subs_id
)
expected_text
=
"Hi, welcome to Edx.
\n
Let's start with what is on your screen right now."
self
.
assertEqual
(
text
,
expected_text
)
def
test_not_found_error
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
with
self
.
assertRaises
(
NotFoundError
):
item
.
get_transcript
(
'wrong'
)
def
test_value_error
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
good_sjson
=
_create_file
(
content
=
'bad content'
)
_upload_file
(
good_sjson
,
self
.
item_module
.
location
)
subs_id
=
_get_subs_id
(
good_sjson
.
name
)
with
self
.
assertRaises
(
ValueError
):
item
.
get_transcript
(
subs_id
)
def
test_key_error
(
self
):
self
.
item_module
.
render
(
'student_view'
)
item
=
self
.
item_descriptor
.
xmodule_runtime
.
xmodule_instance
good_sjson
=
_create_file
(
content
=
"""
{
"start": [
270,
2720
],
"end": [
2720,
5430
]
}
"""
)
_upload_file
(
good_sjson
,
self
.
item_module
.
location
)
subs_id
=
_get_subs_id
(
good_sjson
.
name
)
with
self
.
assertRaises
(
KeyError
):
item
.
get_transcript
(
subs_id
)
def
_clear_assets
(
location
):
store
=
contentstore
()
...
...
lms/djangoapps/courseware/tests/test_video_xml.py
View file @
5bacfcc3
...
...
@@ -31,6 +31,7 @@ SOURCE_XML = """
display_name="A Name"
youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
sub="a_sub_file.srt.sjson"
download_video="true"
start_time="01:00:03" end_time="01:00:10"
>
<source src="example.mp4"/>
...
...
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