Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-val
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-val
Commits
d0fbbb6c
Commit
d0fbbb6c
authored
Aug 28, 2017
by
muhammad-ammar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
import and export transcripts
EDUCATOR-1216
parent
f52b3d00
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
309 additions
and
31 deletions
+309
-31
edxval/api.py
+94
-17
edxval/tests/constants.py
+8
-0
edxval/tests/test_api.py
+207
-14
No files found.
edxval/api.py
View file @
d0fbbb6c
...
@@ -7,6 +7,7 @@ import logging
...
@@ -7,6 +7,7 @@ import logging
from
enum
import
Enum
from
enum
import
Enum
from
django.core.exceptions
import
ObjectDoesNotExist
,
ValidationError
from
django.core.exceptions
import
ObjectDoesNotExist
,
ValidationError
from
lxml
import
etree
from
lxml.etree
import
Element
,
SubElement
from
lxml.etree
import
Element
,
SubElement
from
edxval.exceptions
import
(
InvalidTranscriptFormat
,
from
edxval.exceptions
import
(
InvalidTranscriptFormat
,
...
@@ -683,13 +684,19 @@ def copy_course_videos(source_course_id, destination_course_id):
...
@@ -683,13 +684,19 @@ def copy_course_videos(source_course_id, destination_course_id):
)
)
def
export_to_xml
(
edx_video_id
,
course_id
=
Non
e
):
def
export_to_xml
(
video_ids
,
course_id
=
None
,
external
=
Fals
e
):
"""
"""
Exports data
about the given edx_video_id into the give
n xml object.
Exports data
for a video into a
n xml object.
Args:
NOTE: For external video ids, only transcripts information will be added into xml.
edx_video_id (str): The ID of the video to export
If external=False, then edx_video_id is going to be on first index of the list.
Arguments:
video_ids (list): It can contain edx_video_id and/or multiple external video ids.
We are passing all video ids associated with a video component
so that we can export transcripts for each video id.
course_id (str): The ID of the course with which this video is associated
course_id (str): The ID of the course with which this video is associated
external (bool): True if first video id in `video_ids` is not edx_video_id else False
Returns:
Returns:
An lxml video_asset element containing export data
An lxml video_asset element containing export data
...
@@ -697,8 +704,16 @@ def export_to_xml(edx_video_id, course_id=None):
...
@@ -697,8 +704,16 @@ def export_to_xml(edx_video_id, course_id=None):
Raises:
Raises:
ValVideoNotFoundError: if the video does not exist
ValVideoNotFoundError: if the video does not exist
"""
"""
# val does not store external videos, so construct transcripts information only.
if
external
:
video_el
=
Element
(
'video_asset'
)
return
create_transcripts_xml
(
video_ids
,
video_el
)
# for an internal video, first video id must be edx_video_id
video_id
=
video_ids
[
0
]
video_image_name
=
''
video_image_name
=
''
video
=
_get_video
(
edx_
video_id
)
video
=
_get_video
(
video_id
)
try
:
try
:
course_video
=
CourseVideo
.
objects
.
select_related
(
'video_image'
)
.
get
(
course_id
=
course_id
,
video
=
video
)
course_video
=
CourseVideo
.
objects
.
select_related
(
'video_image'
)
.
get
(
course_id
=
course_id
,
video
=
video
)
...
@@ -723,23 +738,57 @@ def export_to_xml(edx_video_id, course_id=None):
...
@@ -723,23 +738,57 @@ def export_to_xml(edx_video_id, course_id=None):
for
name
in
[
'profile'
,
'url'
,
'file_size'
,
'bitrate'
]
for
name
in
[
'profile'
,
'url'
,
'file_size'
,
'bitrate'
]
}
}
)
)
# Note: we are *not* exporting Subtitle data since it is not currently updated by VEDA or used
# by LMS/Studio.
return
create_transcripts_xml
(
video_ids
,
video_el
)
def
create_transcripts_xml
(
video_ids
,
video_el
):
"""
Create xml for transcripts.
Arguments:
video_ids (list): It can contain edx_video_id and/or multiple external video ids
video_el (Element): lxml Element object
Returns:
lxml Element object with transcripts information
"""
video_transcripts
=
VideoTranscript
.
objects
.
filter
(
video_id__in
=
video_ids
)
# create transcripts node only when we have transcripts for a video
if
video_transcripts
.
exists
():
transcripts_el
=
SubElement
(
video_el
,
'transcripts'
)
exported_language_codes
=
[]
for
video_transcript
in
video_transcripts
:
if
video_transcript
.
language_code
not
in
exported_language_codes
:
SubElement
(
transcripts_el
,
'transcript'
,
{
'video_id'
:
video_transcript
.
video_id
,
'file_name'
:
video_transcript
.
transcript
.
name
,
'language_code'
:
video_transcript
.
language_code
,
'file_format'
:
video_transcript
.
file_format
,
'provider'
:
video_transcript
.
provider
,
}
)
exported_language_codes
.
append
(
video_transcript
.
language_code
)
return
video_el
return
video_el
def
import_from_xml
(
xml
,
edx_video_id
,
course_id
=
Non
e
):
def
import_from_xml
(
xml
,
video_id
,
course_id
=
None
,
external
=
Fals
e
):
"""
"""
Imports data from a video_asset element about the given
edx_
video_id.
Imports data from a video_asset element about the given video_id.
If the edx_video_id already exists, then no changes are made. If an unknown
If the edx_video_id already exists, then no changes are made. If an unknown
profile is referenced by an encoded video, that encoding will be ignored.
profile is referenced by an encoded video, that encoding will be ignored.
Args:
Arg
ument
s:
xml: An lxml video_asset element containing import data
xml
(Element)
: An lxml video_asset element containing import data
edx_video_id (str): The ID for the video content
video_id (str): It can be an edx_video_id or empty string
course_id (str): The ID of a course to associate the video with
course_id (str): The ID of a course to associate the video with
(optional)
external (bool): False if `video_id` is an edx_video_id else True
Raises:
Raises:
ValCannotCreateError: if there is an error importing the video
ValCannotCreateError: if there is an error importing the video
...
@@ -747,12 +796,16 @@ def import_from_xml(xml, edx_video_id, course_id=None):
...
@@ -747,12 +796,16 @@ def import_from_xml(xml, edx_video_id, course_id=None):
if
xml
.
tag
!=
'video_asset'
:
if
xml
.
tag
!=
'video_asset'
:
raise
ValCannotCreateError
(
'Invalid XML'
)
raise
ValCannotCreateError
(
'Invalid XML'
)
# if edx_video_id does not exist then create video transcripts only
if
external
:
return
create_transcript_objects
(
xml
)
# If video with edx_video_id already exists, associate it with the given course_id.
# If video with edx_video_id already exists, associate it with the given course_id.
try
:
try
:
video
=
Video
.
objects
.
get
(
edx_video_id
=
edx_
video_id
)
video
=
Video
.
objects
.
get
(
edx_video_id
=
video_id
)
logger
.
info
(
logger
.
info
(
"edx_video_id '
%
s' present in course '
%
s' not imported because it exists in VAL."
,
"edx_video_id '
%
s' present in course '
%
s' not imported because it exists in VAL."
,
edx_
video_id
,
video_id
,
course_id
,
course_id
,
)
)
if
course_id
:
if
course_id
:
...
@@ -762,6 +815,9 @@ def import_from_xml(xml, edx_video_id, course_id=None):
...
@@ -762,6 +815,9 @@ def import_from_xml(xml, edx_video_id, course_id=None):
if
image_file_name
:
if
image_file_name
:
VideoImage
.
create_or_update
(
course_video
,
image_file_name
)
VideoImage
.
create_or_update
(
course_video
,
image_file_name
)
# import transcripts
create_transcript_objects
(
xml
)
return
return
except
ValidationError
as
err
:
except
ValidationError
as
err
:
logger
.
exception
(
err
.
message
)
logger
.
exception
(
err
.
message
)
...
@@ -771,7 +827,7 @@ def import_from_xml(xml, edx_video_id, course_id=None):
...
@@ -771,7 +827,7 @@ def import_from_xml(xml, edx_video_id, course_id=None):
# Video with edx_video_id did not exist, so create one from xml data.
# Video with edx_video_id did not exist, so create one from xml data.
data
=
{
data
=
{
'edx_video_id'
:
edx_
video_id
,
'edx_video_id'
:
video_id
,
'client_video_id'
:
xml
.
get
(
'client_video_id'
),
'client_video_id'
:
xml
.
get
(
'client_video_id'
),
'duration'
:
xml
.
get
(
'duration'
),
'duration'
:
xml
.
get
(
'duration'
),
'status'
:
'imported'
,
'status'
:
'imported'
,
...
@@ -785,7 +841,7 @@ def import_from_xml(xml, edx_video_id, course_id=None):
...
@@ -785,7 +841,7 @@ def import_from_xml(xml, edx_video_id, course_id=None):
except
Profile
.
DoesNotExist
:
except
Profile
.
DoesNotExist
:
logger
.
info
(
logger
.
info
(
"Imported edx_video_id '
%
s' contains unknown profile '
%
s'."
,
"Imported edx_video_id '
%
s' contains unknown profile '
%
s'."
,
edx_
video_id
,
video_id
,
profile_name
profile_name
)
)
continue
continue
...
@@ -796,3 +852,24 @@ def import_from_xml(xml, edx_video_id, course_id=None):
...
@@ -796,3 +852,24 @@ def import_from_xml(xml, edx_video_id, course_id=None):
'bitrate'
:
encoded_video_el
.
get
(
'bitrate'
),
'bitrate'
:
encoded_video_el
.
get
(
'bitrate'
),
})
})
create_video
(
data
)
create_video
(
data
)
create_transcript_objects
(
xml
)
def
create_transcript_objects
(
xml
):
"""
Create VideoTranscript objects.
Arguments:
xml (Element): lxml Element object
"""
for
transcript
in
xml
.
findall
(
'.//transcripts/transcript'
):
try
:
VideoTranscript
.
create_or_update
(
transcript
.
attrib
[
'video_id'
],
transcript
.
attrib
[
'language_code'
],
transcript
.
attrib
[
'file_name'
],
transcript
.
attrib
[
'file_format'
],
transcript
.
attrib
[
'provider'
],
)
except
KeyError
:
logger
.
warn
(
"VAL: Required attributes are missing from xml, xml=[
%
s]"
,
etree
.
tostring
(
transcript
)
.
strip
())
edxval/tests/constants.py
View file @
d0fbbb6c
...
@@ -413,6 +413,14 @@ VIDEO_TRANSCRIPT_3PLAY = dict(
...
@@ -413,6 +413,14 @@ VIDEO_TRANSCRIPT_3PLAY = dict(
file_format
=
TranscriptFormat
.
SJSON
,
file_format
=
TranscriptFormat
.
SJSON
,
)
)
VIDEO_TRANSCRIPT_CUSTOM
=
dict
(
video_id
=
'external_video_id'
,
language_code
=
'de'
,
transcript
=
'wow.srt'
,
provider
=
TranscriptProviderType
.
CUSTOM
,
file_format
=
TranscriptFormat
.
SRT
,
)
TRANSCRIPT_PREFERENCES_CIELO24
=
dict
(
TRANSCRIPT_PREFERENCES_CIELO24
=
dict
(
course_id
=
'edX/DemoX/Demo_Course'
,
course_id
=
'edX/DemoX/Demo_Course'
,
provider
=
TranscriptProviderType
.
CIELO24
,
provider
=
TranscriptProviderType
.
CIELO24
,
...
...
edxval/tests/test_api.py
View file @
d0fbbb6c
...
@@ -905,6 +905,17 @@ class ExportTest(TestCase):
...
@@ -905,6 +905,17 @@ class ExportTest(TestCase):
**
constants
.
ENCODED_VIDEO_DICT_HLS
**
constants
.
ENCODED_VIDEO_DICT_HLS
)
)
# create external video transcripts
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_CUSTOM
)
video_transcript
=
dict
(
constants
.
VIDEO_TRANSCRIPT_CUSTOM
,
language_code
=
u'ar'
)
VideoTranscript
.
objects
.
create
(
**
video_transcript
)
video_transcript
=
dict
(
constants
.
VIDEO_TRANSCRIPT_CUSTOM
,
video_id
=
u'external_video_id2'
,
language_code
=
u'fr'
)
VideoTranscript
.
objects
.
create
(
**
video_transcript
)
# create internal video transcripts
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_CIELO24
)
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_3PLAY
)
def
assert_xml_equal
(
self
,
left
,
right
):
def
assert_xml_equal
(
self
,
left
,
right
):
"""
"""
Assert that the given XML fragments have the same attributes, text, and
Assert that the given XML fragments have the same attributes, text, and
...
@@ -930,7 +941,7 @@ class ExportTest(TestCase):
...
@@ -930,7 +941,7 @@ class ExportTest(TestCase):
<video_asset client_video_id="TWINKLE TWINKLE" duration="122.0" image=""/>
<video_asset client_video_id="TWINKLE TWINKLE" duration="122.0" image=""/>
"""
)
"""
)
self
.
assert_xml_equal
(
self
.
assert_xml_equal
(
api
.
export_to_xml
(
constants
.
VIDEO_DICT_STAR
[
"edx_video_id"
]),
api
.
export_to_xml
(
[
constants
.
VIDEO_DICT_STAR
[
"edx_video_id"
]
]),
expected
expected
)
)
...
@@ -945,17 +956,73 @@ class ExportTest(TestCase):
...
@@ -945,17 +956,73 @@ class ExportTest(TestCase):
<encoded_video url="http://www.meowmix.com" file_size="11" bitrate="22" profile="mobile"/>
<encoded_video url="http://www.meowmix.com" file_size="11" bitrate="22" profile="mobile"/>
<encoded_video url="http://www.meowmagic.com" file_size="33" bitrate="44" profile="desktop"/>
<encoded_video url="http://www.meowmagic.com" file_size="33" bitrate="44" profile="desktop"/>
<encoded_video url="https://www.tmnt.com/tmnt101.m3u8" file_size="100" bitrate="0" profile="hls"/>
<encoded_video url="https://www.tmnt.com/tmnt101.m3u8" file_size="100" bitrate="0" profile="hls"/>
<transcripts>
<transcript file_format="sjson" file_name="wow.sjson" language_code="de" provider="3PlayMedia" video_id="super-soaker"/>
<transcript file_format="srt" file_name="wow.srt" language_code="en" provider="Cielo24" video_id="super-soaker" />
</transcripts>
</video_asset>
</video_asset>
"""
.
format
(
image
=
image
))
"""
.
format
(
image
=
image
,
video_id
=
constants
.
VIDEO_DICT_FISH
[
'edx_video_id'
]
))
self
.
assert_xml_equal
(
self
.
assert_xml_equal
(
api
.
export_to_xml
(
constants
.
VIDEO_DICT_FISH
[
'edx_video_id'
],
course_id
),
api
.
export_to_xml
(
[
constants
.
VIDEO_DICT_FISH
[
'edx_video_id'
]
],
course_id
),
expected
expected
)
)
def
test_unknown_video
(
self
):
def
test_unknown_video
(
self
):
with
self
.
assertRaises
(
ValVideoNotFoundError
):
with
self
.
assertRaises
(
ValVideoNotFoundError
):
api
.
export_to_xml
(
"unknown_video"
)
api
.
export_to_xml
([
"unknown_video"
])
def
test_external_video_transcript
(
self
):
"""
Verify that transcript export for multiple external videos is working as expected.
"""
video_ids
=
[
'missing'
,
'external_video_id'
,
'missing2'
,
'external_video_id2'
]
expected
=
self
.
parse_xml
(
"""
<video_asset>
<transcripts>
<transcript file_format="srt" file_name="wow.srt" language_code="ar" provider="Custom" video_id="external_video_id"/>
<transcript file_format="srt" file_name="wow.srt" language_code="de" provider="Custom" video_id="external_video_id"/>
<transcript file_format="srt" file_name="wow.srt" language_code="fr" provider="Custom" video_id="external_video_id2"/>
</transcripts>
</video_asset>
"""
.
format
(
video_id
=
''
))
self
.
assert_xml_equal
(
api
.
export_to_xml
(
video_ids
,
external
=
True
),
expected
)
def
test_with_multiple_video_ids
(
self
):
"""
Verify that transcript export with multiple video ids is working as expected.
"""
video_ids
=
[
'super-soaker'
,
'external_video_id'
]
expected
=
self
.
parse_xml
(
"""
<video_asset client_video_id="Shallow Swordfish" duration="122.0" image="">
<encoded_video bitrate="22" file_size="11" profile="mobile" url="http://www.meowmix.com" />
<encoded_video bitrate="44" file_size="33" profile="desktop" url="http://www.meowmagic.com" />
<encoded_video bitrate="0" file_size="100" profile="hls" url="https://www.tmnt.com/tmnt101.m3u8" />
<transcripts>
<transcript file_format="srt" file_name="wow.srt" language_code="ar" provider="Custom" video_id="external_video_id" />
<transcript file_format="srt" file_name="wow.srt" language_code="de" provider="Custom" video_id="external_video_id"/>
<transcript file_format="srt" file_name="wow.srt" language_code="en" provider="Cielo24" video_id="super-soaker" />
</transcripts>
</video_asset>
"""
)
self
.
assert_xml_equal
(
api
.
export_to_xml
(
video_ids
),
expected
)
def
test_external_no_video_transcript
(
self
):
"""
Verify that transcript export for external video working as expected when there is no transcript.
"""
self
.
assert_xml_equal
(
api
.
export_to_xml
([
'external_video_no_transcript'
],
external
=
True
),
self
.
parse_xml
(
'<video_asset/>'
)
)
@ddt
@ddt
...
@@ -973,7 +1040,11 @@ class ImportTest(TestCase):
...
@@ -973,7 +1040,11 @@ class ImportTest(TestCase):
)
)
CourseVideo
.
objects
.
create
(
video
=
video
,
course_id
=
'existing_course_id'
)
CourseVideo
.
objects
.
create
(
video
=
video
,
course_id
=
'existing_course_id'
)
def
make_import_xml
(
self
,
video_dict
,
encoded_video_dicts
=
None
,
image
=
None
):
self
.
transcript_data1
=
dict
(
constants
.
VIDEO_TRANSCRIPT_CIELO24
,
video_id
=
'little-star'
)
self
.
transcript_data2
=
dict
(
constants
.
VIDEO_TRANSCRIPT_3PLAY
,
video_id
=
'little-star'
)
self
.
transcript_data3
=
dict
(
self
.
transcript_data2
,
video_id
=
'super-soaker'
)
def
make_import_xml
(
self
,
video_dict
,
encoded_video_dicts
=
None
,
image
=
None
,
video_transcripts
=
None
):
import_xml
=
etree
.
Element
(
import_xml
=
etree
.
Element
(
"video_asset"
,
"video_asset"
,
attrib
=
{
attrib
=
{
...
@@ -994,6 +1065,22 @@ class ImportTest(TestCase):
...
@@ -994,6 +1065,22 @@ class ImportTest(TestCase):
for
key
,
val
in
encoding_dict
.
items
()
for
key
,
val
in
encoding_dict
.
items
()
}
}
)
)
if
video_transcripts
:
transcripts_el
=
etree
.
SubElement
(
import_xml
,
'transcripts'
)
for
video_transcript
in
video_transcripts
:
etree
.
SubElement
(
transcripts_el
,
'transcript'
,
{
'video_id'
:
video_transcript
[
'video_id'
],
'file_name'
:
video_transcript
[
'transcript'
],
'language_code'
:
video_transcript
[
'language_code'
],
'file_format'
:
video_transcript
[
'file_format'
],
'provider'
:
video_transcript
[
'provider'
],
}
)
return
import_xml
return
import_xml
def
assert_obj_matches_dict_for_keys
(
self
,
obj
,
dict_
,
keys
):
def
assert_obj_matches_dict_for_keys
(
self
,
obj
,
dict_
,
keys
):
...
@@ -1020,18 +1107,44 @@ class ImportTest(TestCase):
...
@@ -1020,18 +1107,44 @@ class ImportTest(TestCase):
api
.
import_from_xml
(
xml
,
edx_video_id
,
course_id
)
api
.
import_from_xml
(
xml
,
edx_video_id
,
course_id
)
self
.
assertFalse
(
Video
.
objects
.
filter
(
edx_video_id
=
edx_video_id
)
.
exists
())
self
.
assertFalse
(
Video
.
objects
.
filter
(
edx_video_id
=
edx_video_id
)
.
exists
())
def
assert_transcripts
(
self
,
video_id
,
expected_transcripts
):
"""
Compare `received` with `expected` and assert if not equal
"""
# Verify total number of expected transcripts for a video
video_transcripts
=
VideoTranscript
.
objects
.
filter
(
video_id
=
video_id
)
self
.
assertEqual
(
video_transcripts
.
count
(),
len
(
expected_transcripts
))
# Verify data for each transcript
for
expected_transcript
in
expected_transcripts
:
language_code
=
expected_transcript
[
'language_code'
]
expected_transcript
[
'name'
]
=
expected_transcript
.
pop
(
'transcript'
)
# get the imported transcript and rename `url` key
received
=
api
.
TranscriptSerializer
(
VideoTranscript
.
objects
.
get
(
video_id
=
video_id
,
language_code
=
language_code
)
)
.
data
received
[
'name'
]
=
received
.
pop
(
'url'
)
self
.
assertDictEqual
(
received
,
expected_transcript
)
def
test_new_video_full
(
self
):
def
test_new_video_full
(
self
):
new_course_id
=
"new_course_id"
new_course_id
=
'new_course_id'
xml
=
self
.
make_import_xml
(
xml
=
self
.
make_import_xml
(
video_dict
=
constants
.
VIDEO_DICT_STAR
,
video_dict
=
constants
.
VIDEO_DICT_STAR
,
encoded_video_dicts
=
[
constants
.
ENCODED_VIDEO_DICT_STAR
,
constants
.
ENCODED_VIDEO_DICT_FISH_HLS
],
encoded_video_dicts
=
[
constants
.
ENCODED_VIDEO_DICT_STAR
,
constants
.
ENCODED_VIDEO_DICT_FISH_HLS
],
image
=
self
.
image_name
image
=
self
.
image_name
,
video_transcripts
=
[
self
.
transcript_data1
,
self
.
transcript_data2
]
)
)
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_STAR
[
"edx_video_id"
],
new_course_id
)
# there must not be any transcript before import
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
])
video
=
Video
.
objects
.
get
(
edx_video_id
=
constants
.
VIDEO_DICT_STAR
[
"edx_video_id"
])
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
],
new_course_id
)
video
=
Video
.
objects
.
get
(
edx_video_id
=
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
])
self
.
assert_video_matches_dict
(
video
,
constants
.
VIDEO_DICT_STAR
)
self
.
assert_video_matches_dict
(
video
,
constants
.
VIDEO_DICT_STAR
)
self
.
assert_encoded_video_matches_dict
(
self
.
assert_encoded_video_matches_dict
(
video
.
encoded_videos
.
get
(
profile__profile_name
=
constants
.
PROFILE_MOBILE
),
video
.
encoded_videos
.
get
(
profile__profile_name
=
constants
.
PROFILE_MOBILE
),
...
@@ -1044,6 +1157,11 @@ class ImportTest(TestCase):
...
@@ -1044,6 +1157,11 @@ class ImportTest(TestCase):
course_video
=
video
.
courses
.
get
(
course_id
=
new_course_id
)
course_video
=
video
.
courses
.
get
(
course_id
=
new_course_id
)
self
.
assertTrue
(
course_video
.
video_image
.
image
.
name
,
self
.
image_name
)
self
.
assertTrue
(
course_video
.
video_image
.
image
.
name
,
self
.
image_name
)
self
.
assert_transcripts
(
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
],
[
self
.
transcript_data1
,
self
.
transcript_data2
]
)
def
test_new_video_minimal
(
self
):
def
test_new_video_minimal
(
self
):
edx_video_id
=
"test_edx_video_id"
edx_video_id
=
"test_edx_video_id"
...
@@ -1061,11 +1179,13 @@ class ImportTest(TestCase):
...
@@ -1061,11 +1179,13 @@ class ImportTest(TestCase):
@data
(
@data
(
# import into another course, where the video already exists, but is not associated with the course.
# import into another course, where the video already exists, but is not associated with the course.
"new_course_id"
,
{
'course_id'
:
'new_course_id'
,
'language_code'
:
'fr'
}
,
# re-import case, where the video and course association already exists.
# re-import case, where the video and course association already exists.
"existing_course_id"
{
'course_id'
:
'existing_course_id'
,
'language_code'
:
'nl'
}
)
)
def
test_existing_video
(
self
,
course_id
):
@unpack
def
test_existing_video
(
self
,
course_id
,
language_code
):
transcript_data
=
dict
(
self
.
transcript_data3
,
language_code
=
language_code
)
xml
=
self
.
make_import_xml
(
xml
=
self
.
make_import_xml
(
video_dict
=
{
video_dict
=
{
"client_video_id"
:
"new_client_video_id"
,
"client_video_id"
:
"new_client_video_id"
,
...
@@ -1080,8 +1200,14 @@ class ImportTest(TestCase):
...
@@ -1080,8 +1200,14 @@ class ImportTest(TestCase):
"profile"
:
"mobile"
,
"profile"
:
"mobile"
,
},
},
],
],
image
=
self
.
image_name
image
=
self
.
image_name
,
video_transcripts
=
[
transcript_data
]
)
)
# there must not be any transcript before import
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
])
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
course_id
)
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
course_id
)
video
=
Video
.
objects
.
get
(
edx_video_id
=
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
])
video
=
Video
.
objects
.
get
(
edx_video_id
=
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
])
...
@@ -1097,11 +1223,15 @@ class ImportTest(TestCase):
...
@@ -1097,11 +1223,15 @@ class ImportTest(TestCase):
course_video
=
video
.
courses
.
get
(
course_id
=
course_id
)
course_video
=
video
.
courses
.
get
(
course_id
=
course_id
)
self
.
assertTrue
(
course_video
.
video_image
.
image
.
name
,
self
.
image_name
)
self
.
assertTrue
(
course_video
.
video_image
.
image
.
name
,
self
.
image_name
)
self
.
assert_transcripts
(
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
[
transcript_data
]
)
def
test_existing_video_with_invalid_course_id
(
self
):
def
test_existing_video_with_invalid_course_id
(
self
):
xml
=
self
.
make_import_xml
(
video_dict
=
constants
.
VIDEO_DICT_FISH
)
xml
=
self
.
make_import_xml
(
video_dict
=
constants
.
VIDEO_DICT_FISH
)
with
self
.
assertRaises
(
ValCannotCreateError
):
with
self
.
assertRaises
(
ValCannotCreateError
):
api
.
import_from_xml
(
xml
,
edx_
video_id
=
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
course_id
=
"x"
*
300
)
api
.
import_from_xml
(
xml
,
video_id
=
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
course_id
=
"x"
*
300
)
def
test_unknown_profile
(
self
):
def
test_unknown_profile
(
self
):
profile
=
"unknown_profile"
profile
=
"unknown_profile"
...
@@ -1157,6 +1287,69 @@ class ImportTest(TestCase):
...
@@ -1157,6 +1287,69 @@ class ImportTest(TestCase):
xml
=
self
.
make_import_xml
(
video_dict
=
constants
.
VIDEO_DICT_FISH
)
xml
=
self
.
make_import_xml
(
video_dict
=
constants
.
VIDEO_DICT_FISH
)
self
.
assert_invalid_import
(
xml
,
"x"
*
300
)
self
.
assert_invalid_import
(
xml
,
"x"
*
300
)
def
test_external_video_transcript
(
self
):
"""
Verify that transcript import for external video working as expected.
"""
external_video_id
=
'little-star'
xml
=
etree
.
fromstring
(
"""
<video_asset>
<transcripts>
<transcript file_name="wow.srt" language_code="en" file_format="srt" provider='Cielo24' video_id="{video_id}"/>
<transcript file_name="wow.sjson" language_code="de" file_format="sjson" provider='3PlayMedia' video_id="{video_id}"/>
</transcripts>
</video_asset>
"""
.
format
(
video_id
=
external_video_id
))
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
external_video_id
)
api
.
import_from_xml
(
xml
,
external_video_id
,
external
=
True
)
self
.
assert_transcripts
(
external_video_id
,
[
self
.
transcript_data1
,
self
.
transcript_data2
])
def
test_external_no_video_transcript
(
self
):
"""
Verify that transcript import for external video working as expected when there is no transcript.
"""
api
.
import_from_xml
(
etree
.
fromstring
(
'<video_asset/>'
),
'does_not_exist_id'
,
external
=
True
)
self
.
assertEqual
(
VideoTranscript
.
objects
.
count
(),
0
)
@patch
(
'edxval.api.logger'
)
def
test_video_transcript_missing_attribute
(
self
,
mock_logger
):
"""
Verify that video transcript import working as expected if transcript xml data is missing.
"""
video_id
=
'little-star'
transcript_xml
=
'<transcript file_name="wow.srt" language_code="en" file_format="srt" provider="Cielo24"/>'
xml
=
etree
.
fromstring
(
"""
<video_asset>
<transcripts>
{transcript_xml}
<transcript file_name="wow.sjson" language_code="de" file_format="sjson" provider='3PlayMedia' video_id="{video_id}"/>
</transcripts>
</video_asset>
"""
.
format
(
transcript_xml
=
transcript_xml
,
video_id
=
video_id
))
# there should be no video transcript before import
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
video_id
)
api
.
create_transcript_objects
(
xml
)
mock_logger
.
warn
.
assert_called_with
(
"VAL: Required attributes are missing from xml, xml=[
%
s]"
,
transcript_xml
)
self
.
assert_transcripts
(
video_id
,
[
self
.
transcript_data2
])
class
GetCourseVideoRemoveTest
(
TestCase
):
class
GetCourseVideoRemoveTest
(
TestCase
):
"""
"""
...
...
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