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
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
380 additions
and
126 deletions
+380
-126
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
+51
-8
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,
...
@@ -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
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
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
Blades: Change the track field to a dropdown that will allow students
to download the transcript of the video without timecodes. BLD-368.
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):
...
@@ -40,12 +40,12 @@ def correct_video_settings(_step):
# advanced
# advanced
[
'Display Name'
,
'Video'
,
False
],
[
'Display Name'
,
'Video'
,
False
],
[
'Download Video'
,
''
,
False
],
[
'End Time'
,
'00:00:00'
,
False
],
[
'End Time'
,
'00:00:00'
,
False
],
[
'HTML5 Transcript'
,
''
,
False
],
[
'HTML5 Transcript'
,
''
,
False
],
[
'Show Transcript'
,
'True'
,
False
],
[
'Show Transcript'
,
'True'
,
False
],
[
'Start Time'
,
'00:00:00'
,
False
],
[
'Start Time'
,
'00:00:00'
,
False
],
[
'Transcript Download Allowed'
,
'False'
,
False
],
[
'Transcript Download Allowed'
,
'False'
,
False
],
[
'Video Download Allowed'
,
'False'
,
False
],
[
'Video Sources'
,
''
,
False
],
[
'Video Sources'
,
''
,
False
],
[
'Youtube ID'
,
'OEoXaMPEzfM'
,
False
],
[
'Youtube ID'
,
'OEoXaMPEzfM'
,
False
],
[
'Youtube ID for .75x speed'
,
''
,
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) {
...
@@ -106,7 +106,6 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
}
}
},
},
getValueFromEditor
:
function
()
{
getValueFromEditor
:
function
()
{
return
this
.
$el
.
find
(
'#'
+
this
.
uniqueId
).
val
();
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):
...
@@ -187,6 +187,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
show_captions="false"
show_captions="false"
download_track="true"
download_track="true"
download_video="true"
start_time="00:00:01"
start_time="00:00:01"
end_time="00:01:00">
end_time="00:01:00">
<source src="http://www.example.com/source.mp4"/>
<source src="http://www.example.com/source.mp4"/>
...
@@ -207,6 +208,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -207,6 +208,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'youtube_id_1_0'
:
'p2Q6BrNhdh8'
,
'youtube_id_1_0'
:
'p2Q6BrNhdh8'
,
'youtube_id_1_25'
:
'1EeWXzPdhSA'
,
'youtube_id_1_25'
:
'1EeWXzPdhSA'
,
'youtube_id_1_5'
:
'rABDYkeK0x8'
,
'youtube_id_1_5'
:
'rABDYkeK0x8'
,
'download_video'
:
True
,
'show_captions'
:
False
,
'show_captions'
:
False
,
'start_time'
:
datetime
.
timedelta
(
seconds
=
1
),
'start_time'
:
datetime
.
timedelta
(
seconds
=
1
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
60
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
60
),
...
@@ -224,6 +226,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -224,6 +226,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
show_captions="false"
show_captions="false"
download_track="false"
download_track="false"
start_time="00:00:01"
start_time="00:00:01"
download_video="false"
end_time="00:01:00">
end_time="00:01:00">
<source src="http://www.example.com/source.mp4"/>
<source src="http://www.example.com/source.mp4"/>
<track src="http://www.example.com/track"/>
<track src="http://www.example.com/track"/>
...
@@ -240,7 +243,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -240,7 +243,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
60
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
60
),
'track'
:
'http://www.example.com/track'
,
'track'
:
'http://www.example.com/track'
,
'download_track'
:
False
,
'download_track'
:
False
,
'
source'
:
'http://www.example.com/source.mp4'
,
'
download_video'
:
False
,
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'data'
:
''
'data'
:
''
})
})
...
@@ -269,7 +272,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -269,7 +272,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
''
,
'track'
:
''
,
'download_track'
:
False
,
'download_track'
:
False
,
'
source'
:
'http://www.example.com/source.mp4'
,
'
download_video'
:
False
,
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'data'
:
''
'data'
:
''
})
})
...
@@ -291,7 +294,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -291,7 +294,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
''
,
'track'
:
''
,
'download_track'
:
False
,
'download_track'
:
False
,
'
source'
:
''
,
'
download_video'
:
False
,
'html5_sources'
:
[],
'html5_sources'
:
[],
'data'
:
''
'data'
:
''
})
})
...
@@ -306,7 +309,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -306,7 +309,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
<video display_name=""display_name""
<video display_name=""display_name""
html5_sources="["source_1", "source_2"]"
html5_sources="["source_1", "source_2"]"
show_captions="false"
show_captions="false"
source=""http://download_video"
"
download_video="true
"
sub=""html5_subtitles""
sub=""html5_subtitles""
track=""http://download_track""
track=""http://download_track""
download_track="true"
download_track="true"
...
@@ -327,7 +330,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -327,7 +330,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
'http://download_track'
,
'track'
:
'http://download_track'
,
'download_track'
:
True
,
'download_track'
:
True
,
'
source'
:
'http://download_video'
,
'
download_video'
:
True
,
'html5_sources'
:
[
"source_1"
,
"source_2"
],
'html5_sources'
:
[
"source_1"
,
"source_2"
],
'data'
:
''
'data'
:
''
})
})
...
@@ -350,7 +353,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -350,7 +353,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'end_time'
:
datetime
.
timedelta
(
seconds
=
0.0
),
'track'
:
''
,
'track'
:
''
,
'download_track'
:
False
,
'download_track'
:
False
,
'
source'
:
''
,
'
download_video'
:
False
,
'html5_sources'
:
[],
'html5_sources'
:
[],
'data'
:
''
'data'
:
''
})
})
...
@@ -364,6 +367,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -364,6 +367,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
<video display_name="Test Video"
<video display_name="Test Video"
youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
show_captions="false"
show_captions="false"
source="http://www.example.com/source.mp4"
from="00:00:01"
from="00:00:01"
to="00:01:00">
to="00:01:00">
<source src="http://www.example.com/source.mp4"/>
<source src="http://www.example.com/source.mp4"/>
...
@@ -382,7 +386,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -382,7 +386,7 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'track'
:
'http://www.example.com/track'
,
'track'
:
'http://www.example.com/track'
,
'download_track'
:
True
,
'download_track'
:
True
,
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'html5_sources'
:
[
'http://www.example.com/source.mp4'
],
'data'
:
''
'data'
:
''
,
})
})
def
test_old_video_data
(
self
):
def
test_old_video_data
(
self
):
...
@@ -473,10 +477,11 @@ class VideoExportTestCase(unittest.TestCase):
...
@@ -473,10 +477,11 @@ class VideoExportTestCase(unittest.TestCase):
desc
.
track
=
'http://www.example.com/track'
desc
.
track
=
'http://www.example.com/track'
desc
.
download_track
=
True
desc
.
download_track
=
True
desc
.
html5_sources
=
[
'http://www.example.com/source.mp4'
,
'http://www.example.com/source.ogg'
]
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
xml
=
desc
.
definition_to_xml
(
None
)
# We don't use the `resource_fs` parameter
expected
=
etree
.
fromstring
(
'''
\
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.mp4"/>
<source src="http://www.example.com/source.ogg"/>
<source src="http://www.example.com/source.ogg"/>
<track src="http://www.example.com/track"/>
<track src="http://www.example.com/track"/>
...
@@ -501,10 +506,11 @@ class VideoExportTestCase(unittest.TestCase):
...
@@ -501,10 +506,11 @@ class VideoExportTestCase(unittest.TestCase):
desc
.
track
=
'http://www.example.com/track'
desc
.
track
=
'http://www.example.com/track'
desc
.
download_track
=
True
desc
.
download_track
=
True
desc
.
html5_sources
=
[
'http://www.example.com/source.mp4'
,
'http://www.example.com/source.ogg'
]
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
xml
=
desc
.
definition_to_xml
(
None
)
# We don't use the `resource_fs` parameter
expected
=
etree
.
fromstring
(
'''
\
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.mp4"/>
<source src="http://www.example.com/source.ogg"/>
<source src="http://www.example.com/source.ogg"/>
<track src="http://www.example.com/track"/>
<track src="http://www.example.com/track"/>
...
...
common/lib/xmodule/xmodule/video_module.py
View file @
5bacfcc3
...
@@ -98,12 +98,20 @@ class VideoFields(object):
...
@@ -98,12 +98,20 @@ class VideoFields(object):
)
)
#front-end code of video player checks logical validity of (start_time, end_time) pair.
#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
(
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"
,
display_name
=
"Download Video"
,
scope
=
Scope
.
settings
,
scope
=
Scope
.
settings
,
default
=
""
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
(
html5_sources
=
List
(
help
=
"A list of filenames to be used with HTML5 video. The first supported filetype will be displayed."
,
help
=
"A list of filenames to be used with HTML5 video. The first supported filetype will be displayed."
,
display_name
=
"Video Sources"
,
display_name
=
"Video Sources"
,
...
@@ -181,7 +189,12 @@ class VideoModule(VideoFields, XModule):
...
@@ -181,7 +189,12 @@ class VideoModule(VideoFields, XModule):
get_ext
=
lambda
filename
:
filename
.
rpartition
(
'.'
)[
-
1
]
get_ext
=
lambda
filename
:
filename
.
rpartition
(
'.'
)[
-
1
]
sources
=
{
get_ext
(
src
):
src
for
src
in
self
.
html5_sources
}
sources
=
{
get_ext
(
src
):
src
for
src
in
self
.
html5_sources
}
sources
[
'main'
]
=
self
.
source
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
.
download_track
:
if
self
.
track
:
if
self
.
track
:
...
@@ -281,6 +294,14 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -281,6 +294,14 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
If `track` field exists show `track` field on front-end as not-editable
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
but clearable. Dropdown `download_track` is a new field and it has value
True.
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
)
super
(
VideoDescriptor
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
# For backwards compatibility -- if we've got XML data, parse
# For backwards compatibility -- if we've got XML data, parse
...
@@ -290,21 +311,43 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -290,21 +311,43 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
self
.
_field_data
.
set_many
(
self
,
field_data
)
self
.
_field_data
.
set_many
(
self
,
field_data
)
del
self
.
data
del
self
.
data
editable_fields
=
self
.
editable_metadata_fields
self
.
track_visible
=
False
self
.
track_visible
=
False
if
self
.
track
:
if
self
.
track
:
self
.
track_visible
=
True
self
.
track_visible
=
True
download_track
=
self
.
editable_metadata
_fields
[
'download_track'
]
download_track
=
editable
_fields
[
'download_track'
]
if
not
download_track
[
'explicitly_set'
]:
if
not
download_track
[
'explicitly_set'
]:
self
.
download_track
=
True
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
@property
def
editable_metadata_fields
(
self
):
def
editable_metadata_fields
(
self
):
editable_fields
=
super
(
VideoDescriptor
,
self
)
.
editable_metadata_fields
editable_fields
=
super
(
VideoDescriptor
,
self
)
.
editable_metadata_fields
if
self
.
track_visible
:
if
hasattr
(
self
,
'track_visible'
):
editable_fields
[
'track'
][
'non_editable'
]
=
True
if
self
.
track_visible
:
else
:
editable_fields
[
'track'
][
'non_editable'
]
=
True
editable_fields
.
pop
(
'track'
)
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
return
editable_fields
...
@@ -359,6 +402,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -359,6 +402,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
'end_time'
:
self
.
end_time
,
'end_time'
:
self
.
end_time
,
'sub'
:
self
.
sub
,
'sub'
:
self
.
sub
,
'download_track'
:
json
.
dumps
(
self
.
download_track
),
'download_track'
:
json
.
dumps
(
self
.
download_track
),
'download_video'
:
json
.
dumps
(
self
.
download_video
),
}
}
for
key
,
value
in
attrs
.
items
():
for
key
,
value
in
attrs
.
items
():
# Mild workaround to ensure that tests pass -- if a field
# Mild workaround to ensure that tests pass -- if a field
...
@@ -468,7 +512,6 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -468,7 +512,6 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
sources
=
xml
.
findall
(
'source'
)
sources
=
xml
.
findall
(
'source'
)
if
sources
:
if
sources
:
field_data
[
'html5_sources'
]
=
[
ele
.
get
(
'src'
)
for
ele
in
sources
]
field_data
[
'html5_sources'
]
=
[
ele
.
get
(
'src'
)
for
ele
in
sources
]
field_data
[
'source'
]
=
field_data
[
'html5_sources'
][
0
]
track
=
xml
.
find
(
'track'
)
track
=
xml
.
find
(
'track'
)
if
track
is
not
None
:
if
track
is
not
None
:
...
...
lms/djangoapps/courseware/tests/test_video_mongo.py
View file @
5bacfcc3
...
@@ -47,7 +47,7 @@ class TestVideoYouTube(TestVideo):
...
@@ -47,7 +47,7 @@ class TestVideoYouTube(TestVideo):
METADATA
=
{}
METADATA
=
{}
def
test_video_constructor
(
self
):
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
context
=
self
.
item_module
.
render
(
'student_view'
)
.
content
sources
=
{
sources
=
{
...
@@ -70,7 +70,7 @@ class TestVideoYouTube(TestVideo):
...
@@ -70,7 +70,7 @@ class TestVideoYouTube(TestVideo):
'youtube_streams'
:
_create_youtube_string
(
self
.
item_module
),
'youtube_streams'
:
_create_youtube_string
(
self
.
item_module
),
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
False
),
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
False
),
'yt_test_timeout'
:
1500
,
'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
(
self
.
assertEqual
(
...
@@ -81,11 +81,11 @@ class TestVideoYouTube(TestVideo):
...
@@ -81,11 +81,11 @@ class TestVideoYouTube(TestVideo):
class
TestVideoNonYouTube
(
TestVideo
):
class
TestVideoNonYouTube
(
TestVideo
):
"""Integration tests: web client + mongo."""
"""Integration tests: web client + mongo."""
DATA
=
"""
DATA
=
"""
<video show_captions="true"
<video show_captions="true"
display_name="A Name"
display_name="A Name"
sub="a_sub_file.srt.sjson"
sub="a_sub_file.srt.sjson"
download_video="true"
start_time="01:00:03" end_time="01:00:10"
start_time="01:00:03" end_time="01:00:10"
>
>
<source src="example.mp4"/>
<source src="example.mp4"/>
...
@@ -96,7 +96,6 @@ class TestVideoNonYouTube(TestVideo):
...
@@ -96,7 +96,6 @@ class TestVideoNonYouTube(TestVideo):
'data'
:
DATA
'data'
:
DATA
}
}
METADATA
=
{}
METADATA
=
{}
def
test_video_constructor
(
self
):
def
test_video_constructor
(
self
):
"""Make sure that if the 'youtube' attribute is omitted in XML, then
"""Make sure that if the 'youtube' attribute is omitted in XML, then
the template generates an empty string for the YouTube streams.
the template generates an empty string for the YouTube streams.
...
@@ -123,7 +122,7 @@ class TestVideoNonYouTube(TestVideo):
...
@@ -123,7 +122,7 @@ class TestVideoNonYouTube(TestVideo):
'youtube_streams'
:
'1.00:OEoXaMPEzfM'
,
'youtube_streams'
:
'1.00:OEoXaMPEzfM'
,
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
True
),
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
True
),
'yt_test_timeout'
:
1500
,
'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
(
self
.
assertEqual
(
...
@@ -132,104 +131,10 @@ class TestVideoNonYouTube(TestVideo):
...
@@ -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
):
class
TestGetHtmlMethod
(
BaseTestXmodule
):
"""
'''
Make sure that `get_html` works correctly.
Make sure that `get_html` works correctly.
"""
'''
CATEGORY
=
"video"
CATEGORY
=
"video"
DATA
=
SOURCE_XML
DATA
=
SOURCE_XML
METADATA
=
{}
METADATA
=
{}
...
@@ -274,7 +179,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
...
@@ -274,7 +179,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
'track'
:
u'<track src="http://www.example.com/track"/>'
,
'track'
:
u'<track src="http://www.example.com/track"/>'
,
'sub'
:
u'a_sub_file.srt.sjson'
,
'sub'
:
u'a_sub_file.srt.sjson'
,
'expected_track_url'
:
None
,
'expected_track_url'
:
None
,
}
}
,
]
]
expected_context
=
{
expected_context
=
{
...
@@ -285,7 +190,6 @@ class TestGetHtmlMethod(BaseTestXmodule):
...
@@ -285,7 +190,6 @@ class TestGetHtmlMethod(BaseTestXmodule):
'end'
:
3610.0
,
'end'
:
3610.0
,
'id'
:
None
,
'id'
:
None
,
'sources'
:
{
'sources'
:
{
'main'
:
u'example.mp4'
,
u'mp4'
:
u'example.mp4'
,
u'mp4'
:
u'example.mp4'
,
u'webm'
:
u'example.webm'
u'webm'
:
u'example.webm'
},
},
...
@@ -295,14 +199,14 @@ class TestGetHtmlMethod(BaseTestXmodule):
...
@@ -295,14 +199,14 @@ class TestGetHtmlMethod(BaseTestXmodule):
'youtube_streams'
:
'1.00:OEoXaMPEzfM'
,
'youtube_streams'
:
'1.00:OEoXaMPEzfM'
,
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
True
),
'autoplay'
:
settings
.
FEATURES
.
get
(
'AUTOPLAY_VIDEOS'
,
True
),
'yt_test_timeout'
:
1500
,
'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
:
for
data
in
cases
:
DATA
=
SOURCE_XML
.
format
(
DATA
=
SOURCE_XML
.
format
(
download_track
=
data
[
'download_track'
],
download_track
=
data
[
'download_track'
],
track
=
data
[
'track'
],
track
=
data
[
'track'
],
sub
=
data
[
'sub'
]
,
sub
=
data
[
'sub'
]
)
)
self
.
initialize_module
(
data
=
DATA
)
self
.
initialize_module
(
data
=
DATA
)
...
@@ -320,6 +224,104 @@ class TestGetHtmlMethod(BaseTestXmodule):
...
@@ -320,6 +224,104 @@ class TestGetHtmlMethod(BaseTestXmodule):
self
.
item_module
.
xmodule_runtime
.
render_template
(
'video.html'
,
expected_context
)
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
):
class
TestVideoDescriptorInitialization
(
BaseTestXmodule
):
"""
"""
...
@@ -332,6 +334,105 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
...
@@ -332,6 +334,105 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
setup_course
();
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
):
def
test_track_is_not_empty
(
self
):
metatdata
=
{
metatdata
=
{
'track'
:
'http://example.org/track'
,
'track'
:
'http://example.org/track'
,
...
@@ -359,7 +460,7 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
...
@@ -359,7 +460,7 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
'options'
:
[
'options'
:
[
{
'display_name'
:
"True"
,
"value"
:
True
},
{
'display_name'
:
"True"
,
"value"
:
True
},
{
'display_name'
:
"False"
,
"value"
:
False
}
{
'display_name'
:
"False"
,
"value"
:
False
}
]
]
,
},
},
'track'
:
{
'track'
:
{
'default_value'
:
''
,
'default_value'
:
''
,
...
@@ -369,10 +470,21 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
...
@@ -369,10 +470,21 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
'type'
:
'Generic'
,
'type'
:
'Generic'
,
'value'
:
u'http://example.org/track'
,
'value'
:
u'http://example.org/track'
,
'field_name'
:
'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
=
{
metadata
=
{
'source'
:
''
,
'track'
:
'http://example.org/track'
,
'track'
:
'http://example.org/track'
,
}
}
...
@@ -399,6 +511,96 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
...
@@ -399,6 +511,96 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
self
.
assertFalse
(
self
.
item_module
.
track_visible
)
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
):
def
_clear_assets
(
location
):
store
=
contentstore
()
store
=
contentstore
()
...
...
lms/djangoapps/courseware/tests/test_video_xml.py
View file @
5bacfcc3
...
@@ -31,6 +31,7 @@ SOURCE_XML = """
...
@@ -31,6 +31,7 @@ SOURCE_XML = """
display_name="A Name"
display_name="A Name"
youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
sub="a_sub_file.srt.sjson"
sub="a_sub_file.srt.sjson"
download_video="true"
start_time="01:00:03" end_time="01:00:10"
start_time="01:00:03" end_time="01:00:10"
>
>
<source src="example.mp4"/>
<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