Include VAL data in video module export/import
This is required so that an a video module exported by one Open edX deployment and imported by another will work correctly if it contains an edx_video_id but does not populate other URL fields. JIRA: MA-110
This commit is contained in:
@@ -40,20 +40,7 @@ class VideoUploadTestMixin(object):
|
||||
"course_video_upload_token": self.test_token,
|
||||
}
|
||||
self.save_course()
|
||||
self.profiles = [
|
||||
{
|
||||
"profile_name": "profile1",
|
||||
"extension": "mp4",
|
||||
"width": 640,
|
||||
"height": 480,
|
||||
},
|
||||
{
|
||||
"profile_name": "profile2",
|
||||
"extension": "mp4",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
},
|
||||
]
|
||||
self.profiles = ["profile1", "profile2"]
|
||||
self.previous_uploads = [
|
||||
{
|
||||
"edx_video_id": "test1",
|
||||
|
||||
@@ -15,20 +15,21 @@ the course, section, subsection, unit, etc.
|
||||
import unittest
|
||||
import datetime
|
||||
from uuid import uuid4
|
||||
from mock import Mock, patch
|
||||
|
||||
from . import LogicTest
|
||||
from lxml import etree
|
||||
from mock import ANY, Mock, patch
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from xmodule.video_module import VideoDescriptor, create_youtube_string, get_video_from_cdn
|
||||
from .test_import import DummySystem
|
||||
from xblock.field_data import DictFieldData
|
||||
from xblock.fields import ScopeIds
|
||||
|
||||
from xmodule.tests import get_test_descriptor_system
|
||||
from xmodule.video_module import VideoDescriptor, create_youtube_string, get_video_from_cdn
|
||||
from xmodule.video_module.transcripts_utils import download_youtube_subs, save_to_store
|
||||
|
||||
from django.conf import settings
|
||||
from . import LogicTest
|
||||
from .test_import import DummySystem
|
||||
|
||||
SRT_FILEDATA = '''
|
||||
0
|
||||
@@ -89,6 +90,19 @@ def instantiate_descriptor(**field_data):
|
||||
)
|
||||
|
||||
|
||||
# Because of the way xmodule.video_module.video_module imports edxval.api, we
|
||||
# must mock the entire module, which requires making mock exception classes.
|
||||
|
||||
class _MockValVideoNotFoundError(Exception):
|
||||
"""Mock ValVideoNotFoundError exception"""
|
||||
pass
|
||||
|
||||
|
||||
class _MockValCannotCreateError(Exception):
|
||||
"""Mock ValCannotCreateError exception"""
|
||||
pass
|
||||
|
||||
|
||||
class VideoModuleTest(LogicTest):
|
||||
"""Logic tests for Video Xmodule."""
|
||||
descriptor_class = VideoDescriptor
|
||||
@@ -176,6 +190,21 @@ class VideoDescriptorTestBase(unittest.TestCase):
|
||||
super(VideoDescriptorTestBase, self).setUp()
|
||||
self.descriptor = instantiate_descriptor()
|
||||
|
||||
def assertXmlEqual(self, expected, xml):
|
||||
"""
|
||||
Assert that the given XML fragments have the same attributes, text, and
|
||||
(recursively) children
|
||||
"""
|
||||
def get_child_tags(elem):
|
||||
"""Extract the list of tag names for children of elem"""
|
||||
return [child.tag for child in elem]
|
||||
|
||||
for attr in ['tag', 'attrib', 'text', 'tail']:
|
||||
self.assertEqual(getattr(expected, attr), getattr(xml, attr))
|
||||
self.assertEqual(get_child_tags(expected), get_child_tags(xml))
|
||||
for left, right in zip(expected, xml):
|
||||
self.assertXmlEqual(left, right)
|
||||
|
||||
|
||||
class TestCreateYoutubeString(VideoDescriptorTestBase):
|
||||
"""
|
||||
@@ -522,21 +551,61 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
|
||||
'data': ''
|
||||
})
|
||||
|
||||
@patch('xmodule.video_module.video_module.edxval_api')
|
||||
def test_import_val_data(self, mock_val_api):
|
||||
def mock_val_import(xml, edx_video_id):
|
||||
"""Mock edxval.api.import_from_xml"""
|
||||
self.assertEqual(xml.tag, 'video_asset')
|
||||
self.assertEqual(dict(xml.items()), {'mock_attr': ''})
|
||||
self.assertEqual(edx_video_id, 'test_edx_video_id')
|
||||
|
||||
mock_val_api.import_from_xml = Mock(wraps=mock_val_import)
|
||||
module_system = DummySystem(load_error_modules=True)
|
||||
|
||||
# import new edx_video_id
|
||||
xml_data = """
|
||||
<video edx_video_id="test_edx_video_id">
|
||||
<video_asset mock_attr=""/>
|
||||
</video>
|
||||
"""
|
||||
video = VideoDescriptor.from_xml(xml_data, module_system, id_generator=Mock())
|
||||
|
||||
self.assert_attributes_equal(video, {'edx_video_id': 'test_edx_video_id'})
|
||||
mock_val_api.import_from_xml.assert_called_once_with(ANY, 'test_edx_video_id')
|
||||
|
||||
@patch('xmodule.video_module.video_module.edxval_api')
|
||||
def test_import_val_data_invalid(self, mock_val_api):
|
||||
mock_val_api.ValCannotCreateError = _MockValCannotCreateError
|
||||
mock_val_api.import_from_xml = Mock(side_effect=mock_val_api.ValCannotCreateError)
|
||||
module_system = DummySystem(load_error_modules=True)
|
||||
|
||||
# Negative duration is invalid
|
||||
xml_data = """
|
||||
<video edx_video_id="test_edx_video_id">
|
||||
<video_asset client_video_id="test_client_video_id" duration="-1"/>
|
||||
</video>
|
||||
"""
|
||||
with self.assertRaises(mock_val_api.ValCannotCreateError):
|
||||
VideoDescriptor.from_xml(xml_data, module_system, id_generator=Mock())
|
||||
|
||||
|
||||
class VideoExportTestCase(VideoDescriptorTestBase):
|
||||
"""
|
||||
Make sure that VideoDescriptor can export itself to XML correctly.
|
||||
"""
|
||||
def assertXmlEqual(self, expected, xml):
|
||||
for attr in ['tag', 'attrib', 'text', 'tail']:
|
||||
self.assertEqual(getattr(expected, attr), getattr(xml, attr))
|
||||
for left, right in zip(expected, xml):
|
||||
self.assertXmlEqual(left, right)
|
||||
|
||||
def test_export_to_xml(self):
|
||||
@patch('xmodule.video_module.video_module.edxval_api')
|
||||
def test_export_to_xml(self, mock_val_api):
|
||||
"""
|
||||
Test that we write the correct XML on export.
|
||||
"""
|
||||
def mock_val_export(edx_video_id):
|
||||
"""Mock edxval.api.export_to_xml"""
|
||||
return etree.Element( # pylint:disable=no-member
|
||||
'video_asset',
|
||||
attrib={'export_edx_video_id': edx_video_id}
|
||||
)
|
||||
|
||||
mock_val_api.export_to_xml = mock_val_export
|
||||
self.descriptor.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
@@ -550,6 +619,7 @@ class VideoExportTestCase(VideoDescriptorTestBase):
|
||||
self.descriptor.html5_sources = ['http://www.example.com/source.mp4', 'http://www.example.com/source.ogg']
|
||||
self.descriptor.download_video = True
|
||||
self.descriptor.transcripts = {'ua': 'ukrainian_translation.srt', 'ge': 'german_translation.srt'}
|
||||
self.descriptor.edx_video_id = 'test_edx_video_id'
|
||||
|
||||
xml = self.descriptor.definition_to_xml(None) # We don't use the `resource_fs` parameter
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
@@ -561,11 +631,25 @@ class VideoExportTestCase(VideoDescriptorTestBase):
|
||||
<handout src="http://www.example.com/handout"/>
|
||||
<transcript language="ge" src="german_translation.srt" />
|
||||
<transcript language="ua" src="ukrainian_translation.srt" />
|
||||
<video_asset export_edx_video_id="test_edx_video_id"/>
|
||||
</video>
|
||||
'''
|
||||
expected = etree.XML(xml_string, parser=parser)
|
||||
self.assertXmlEqual(expected, xml)
|
||||
|
||||
@patch('xmodule.video_module.video_module.edxval_api')
|
||||
def test_export_to_xml_val_error(self, mock_val_api):
|
||||
# Export should succeed without VAL data if video does not exist
|
||||
mock_val_api.ValVideoNotFoundError = _MockValVideoNotFoundError
|
||||
mock_val_api.export_to_xml = Mock(side_effect=mock_val_api.ValVideoNotFoundError)
|
||||
self.descriptor.edx_video_id = 'test_edx_video_id'
|
||||
|
||||
xml = self.descriptor.definition_to_xml(None)
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
xml_string = '<video url_name="SampleProblem" download_video="false"/>'
|
||||
expected = etree.XML(xml_string, parser=parser)
|
||||
self.assertXmlEqual(expected, xml)
|
||||
|
||||
def test_export_to_xml_empty_end_time(self):
|
||||
"""
|
||||
Test that we write the correct XML on export.
|
||||
|
||||
@@ -404,8 +404,7 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
|
||||
xml_data: A string of xml that will be translated into data and children for
|
||||
this module
|
||||
system: A DescriptorSystem for interacting with external resources
|
||||
org and course are optional strings that will be used in the generated modules
|
||||
url identifiers
|
||||
id_generator is used to generate course-specific urls and identifiers
|
||||
"""
|
||||
xml_object = etree.fromstring(xml_data)
|
||||
url_name = xml_object.get('url_name', xml_object.get('slug'))
|
||||
@@ -478,6 +477,12 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
|
||||
ele.set('src', self.transcripts[transcript_language])
|
||||
xml.append(ele)
|
||||
|
||||
if self.edx_video_id and edxval_api:
|
||||
try:
|
||||
xml.append(edxval_api.export_to_xml(self.edx_video_id))
|
||||
except edxval_api.ValVideoNotFoundError:
|
||||
pass
|
||||
|
||||
return xml
|
||||
|
||||
def get_context(self):
|
||||
@@ -621,6 +626,15 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
|
||||
if 'download_track' not in field_data and track is not None:
|
||||
field_data['download_track'] = True
|
||||
|
||||
video_asset_elem = xml.find('video_asset')
|
||||
if (
|
||||
edxval_api and
|
||||
video_asset_elem is not None and
|
||||
'edx_video_id' in field_data
|
||||
):
|
||||
# Allow ValCannotCreateError to escape
|
||||
edxval_api.import_from_xml(video_asset_elem, field_data['edx_video_id'])
|
||||
|
||||
return field_data
|
||||
|
||||
def index_dictionary(self):
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -396,7 +396,7 @@ CREATE TABLE `auth_permission` (
|
||||
UNIQUE KEY `content_type_id` (`content_type_id`,`codename`),
|
||||
KEY `auth_permission_e4470c6e` (`content_type_id`),
|
||||
CONSTRAINT `content_type_id_refs_id_728de91f` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=499 DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=511 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `auth_registration`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
@@ -623,6 +623,20 @@ CREATE TABLE `certificates_certificategenerationcoursesetting` (
|
||||
KEY `certificates_certificategenerationcoursesetting_b4b47e7a` (`course_key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `certificates_certificatehtmlviewconfiguration`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `certificates_certificatehtmlviewconfiguration` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`change_date` datetime NOT NULL,
|
||||
`changed_by_id` int(11) DEFAULT NULL,
|
||||
`enabled` tinyint(1) NOT NULL,
|
||||
`configuration` longtext NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `certificates_certificatehtmlviewconfiguration_16905482` (`changed_by_id`),
|
||||
CONSTRAINT `changed_by_id_refs_id_8584db17` FOREIGN KEY (`changed_by_id`) REFERENCES `auth_user` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `certificates_certificatewhitelist`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
@@ -772,6 +786,31 @@ CREATE TABLE `course_creators_coursecreator` (
|
||||
CONSTRAINT `user_id_refs_id_6a0e6044` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `course_groups_coursecohort`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `course_groups_coursecohort` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`course_user_group_id` int(11) NOT NULL,
|
||||
`assignment_type` varchar(20) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `course_user_group_id` (`course_user_group_id`),
|
||||
CONSTRAINT `course_user_group_id_refs_id_8febc00f` FOREIGN KEY (`course_user_group_id`) REFERENCES `course_groups_courseusergroup` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `course_groups_coursecohortssettings`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `course_groups_coursecohortssettings` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`is_cohorted` tinyint(1) NOT NULL,
|
||||
`course_id` varchar(255) NOT NULL,
|
||||
`cohorted_discussions` longtext,
|
||||
`always_cohort_inline_discussions` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `course_id` (`course_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `course_groups_courseusergroup`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
@@ -1031,8 +1070,8 @@ CREATE TABLE `django_admin_log` (
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `django_admin_log_fbfc09f1` (`user_id`),
|
||||
KEY `django_admin_log_e4470c6e` (`content_type_id`),
|
||||
CONSTRAINT `user_id_refs_id_c8665aa` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`),
|
||||
CONSTRAINT `content_type_id_refs_id_288599e6` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`)
|
||||
CONSTRAINT `content_type_id_refs_id_288599e6` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`),
|
||||
CONSTRAINT `user_id_refs_id_c8665aa` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `django_comment_client_permission`;
|
||||
@@ -1094,7 +1133,7 @@ CREATE TABLE `django_content_type` (
|
||||
`model` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `app_label` (`app_label`,`model`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=166 DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=170 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `django_openid_auth_association`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
@@ -1294,9 +1333,9 @@ DROP TABLE IF EXISTS `edxval_profile`;
|
||||
CREATE TABLE `edxval_profile` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`profile_name` varchar(50) NOT NULL,
|
||||
`extension` varchar(10) NOT NULL,
|
||||
`width` int(10) unsigned NOT NULL,
|
||||
`height` int(10) unsigned NOT NULL,
|
||||
`extension` varchar(10) DEFAULT 'mp4',
|
||||
`width` int(10) unsigned DEFAULT '1',
|
||||
`height` int(10) unsigned DEFAULT '1',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `profile_name` (`profile_name`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
|
||||
@@ -1650,6 +1689,20 @@ CREATE TABLE `milestones_usermilestone` (
|
||||
CONSTRAINT `milestone_id_refs_id_af7fa460` FOREIGN KEY (`milestone_id`) REFERENCES `milestones_milestone` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `mobile_api_mobileapiconfig`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `mobile_api_mobileapiconfig` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`change_date` datetime NOT NULL,
|
||||
`changed_by_id` int(11) DEFAULT NULL,
|
||||
`enabled` tinyint(1) NOT NULL,
|
||||
`video_profiles` longtext NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `mobile_api_mobileapiconfig_16905482` (`changed_by_id`),
|
||||
CONSTRAINT `changed_by_id_refs_id_97c2f4c8` FOREIGN KEY (`changed_by_id`) REFERENCES `auth_user` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `notes_note`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
@@ -2245,7 +2298,7 @@ CREATE TABLE `south_migrationhistory` (
|
||||
`migration` varchar(255) NOT NULL,
|
||||
`applied` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=222 DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=228 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `splash_splashconfig`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
|
||||
@@ -2,15 +2,21 @@
|
||||
"""Video xmodule tests in mongo."""
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
from mock import patch, MagicMock
|
||||
|
||||
from lxml import etree
|
||||
from mock import patch, MagicMock, Mock
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
|
||||
from xmodule.video_module import create_youtube_string
|
||||
from xmodule.video_module import create_youtube_string, VideoDescriptor
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
from xmodule.tests.test_video import VideoDescriptorTestBase
|
||||
from xmodule.tests.test_import import DummySystem
|
||||
|
||||
from edxval.api import create_profile, create_video
|
||||
from edxval.api import (
|
||||
create_profile, create_video, get_video_info, ValCannotCreateError, ValVideoNotFoundError
|
||||
)
|
||||
|
||||
from . import BaseTestXmodule
|
||||
from .test_video_xml import SOURCE_XML
|
||||
@@ -520,15 +526,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
|
||||
# create test profiles and their encodings
|
||||
encoded_videos = []
|
||||
for profile, extension in [("desktop_webm", "webm"), ("desktop_mp4", "mp4")]:
|
||||
result = create_profile(
|
||||
dict(
|
||||
profile_name=profile,
|
||||
extension=extension,
|
||||
width=200,
|
||||
height=2001
|
||||
)
|
||||
)
|
||||
self.assertEqual(result, profile)
|
||||
create_profile(profile)
|
||||
encoded_videos.append(
|
||||
dict(
|
||||
url=u"http://fake-video.edx.org/thundercats.{}".format(extension),
|
||||
@@ -831,7 +829,7 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
|
||||
self.assertFalse(self.item_descriptor.download_video)
|
||||
|
||||
|
||||
class VideoDescriptorTest(VideoDescriptorTestBase):
|
||||
class VideoDescriptorTest(TestCase, VideoDescriptorTestBase):
|
||||
"""
|
||||
Tests for video descriptor that requires access to django settings.
|
||||
"""
|
||||
@@ -859,3 +857,79 @@ class VideoDescriptorTest(VideoDescriptorTestBase):
|
||||
]
|
||||
rendered_context = self.descriptor.get_context()
|
||||
self.assertListEqual(rendered_context['tabs'], correct_tabs)
|
||||
|
||||
def test_export_val_data(self):
|
||||
self.descriptor.edx_video_id = 'test_edx_video_id'
|
||||
create_profile('mobile')
|
||||
create_video({
|
||||
'edx_video_id': self.descriptor.edx_video_id,
|
||||
'client_video_id': 'test_client_video_id',
|
||||
'duration': 111,
|
||||
'status': 'dummy',
|
||||
'encoded_videos': [{
|
||||
'profile': 'mobile',
|
||||
'url': 'http://example.com/video',
|
||||
'file_size': 222,
|
||||
'bitrate': 333,
|
||||
}],
|
||||
})
|
||||
|
||||
actual = self.descriptor.definition_to_xml(resource_fs=None)
|
||||
expected_str = """
|
||||
<video download_video="false" url_name="SampleProblem">
|
||||
<video_asset client_video_id="test_client_video_id" duration="111.0">
|
||||
<encoded_video profile="mobile" url="http://example.com/video" file_size="222" bitrate="333"/>
|
||||
</video_asset>
|
||||
</video>
|
||||
"""
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
expected = etree.XML(expected_str, parser=parser)
|
||||
self.assertXmlEqual(expected, actual)
|
||||
|
||||
def test_export_val_data_not_found(self):
|
||||
self.descriptor.edx_video_id = 'nonexistent'
|
||||
actual = self.descriptor.definition_to_xml(resource_fs=None)
|
||||
expected_str = """<video download_video="false" url_name="SampleProblem"/>"""
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
expected = etree.XML(expected_str, parser=parser)
|
||||
self.assertXmlEqual(expected, actual)
|
||||
|
||||
def test_import_val_data(self):
|
||||
create_profile('mobile')
|
||||
module_system = DummySystem(load_error_modules=True)
|
||||
|
||||
xml_data = """
|
||||
<video edx_video_id="test_edx_video_id">
|
||||
<video_asset client_video_id="test_client_video_id" duration="111.0">
|
||||
<encoded_video profile="mobile" url="http://example.com/video" file_size="222" bitrate="333"/>
|
||||
</video_asset>
|
||||
</video>
|
||||
"""
|
||||
video = VideoDescriptor.from_xml(xml_data, module_system, id_generator=Mock())
|
||||
self.assertEqual(video.edx_video_id, 'test_edx_video_id')
|
||||
video_data = get_video_info(video.edx_video_id)
|
||||
self.assertEqual(video_data['client_video_id'], 'test_client_video_id')
|
||||
self.assertEqual(video_data['duration'], 111)
|
||||
self.assertEqual(video_data['status'], 'imported')
|
||||
self.assertEqual(video_data['courses'], [])
|
||||
self.assertEqual(video_data['encoded_videos'][0]['profile'], 'mobile')
|
||||
self.assertEqual(video_data['encoded_videos'][0]['url'], 'http://example.com/video')
|
||||
self.assertEqual(video_data['encoded_videos'][0]['file_size'], 222)
|
||||
self.assertEqual(video_data['encoded_videos'][0]['bitrate'], 333)
|
||||
|
||||
def test_import_val_data_invalid(self):
|
||||
create_profile('mobile')
|
||||
module_system = DummySystem(load_error_modules=True)
|
||||
|
||||
# Negative file_size is invalid
|
||||
xml_data = """
|
||||
<video edx_video_id="test_edx_video_id">
|
||||
<video_asset client_video_id="test_client_video_id" duration="111.0">
|
||||
<encoded_video profile="mobile" url="http://example.com/video" file_size="-222" bitrate="333"/>
|
||||
</video_asset>
|
||||
</video>
|
||||
"""
|
||||
with self.assertRaises(ValCannotCreateError):
|
||||
VideoDescriptor.from_xml(xml_data, module_system, id_generator=Mock())
|
||||
with self.assertRaises(ValVideoNotFoundError):
|
||||
get_video_info("test_edx_video_id")
|
||||
|
||||
@@ -63,24 +63,9 @@ class TestVideoAPITestCase(MobileAPITestCase):
|
||||
self.youtube_url = 'http://val.edx.org/val/youtube.mp4'
|
||||
self.html5_video_url = 'http://video.edx.org/html5/video.mp4'
|
||||
|
||||
api.create_profile({
|
||||
'profile_name': 'youtube',
|
||||
'extension': 'mp4',
|
||||
'width': 1280,
|
||||
'height': 720
|
||||
})
|
||||
api.create_profile({
|
||||
'profile_name': 'mobile_high',
|
||||
'extension': 'mp4',
|
||||
'width': 750,
|
||||
'height': 590
|
||||
})
|
||||
api.create_profile({
|
||||
'profile_name': 'mobile_low',
|
||||
'extension': 'mp4',
|
||||
'width': 640,
|
||||
'height': 480
|
||||
})
|
||||
api.create_profile('youtube')
|
||||
api.create_profile('mobile_high')
|
||||
api.create_profile('mobile_low')
|
||||
|
||||
# create the video in VAL
|
||||
api.create_video({
|
||||
|
||||
@@ -35,7 +35,7 @@ git+https://github.com/mitocw/django-cas.git@60a5b8e5a62e63e0d5d224a87f0b489201a
|
||||
-e git+https://github.com/edx/ease.git@97de68448e5495385ba043d3091f570a699d5b5f#egg=ease
|
||||
-e git+https://github.com/edx/i18n-tools.git@193cebd9aa784f8899ef496f2aa050b08eff402b#egg=i18n-tools
|
||||
-e git+https://github.com/edx/edx-oauth2-provider.git@0.4.2#egg=oauth2-provider
|
||||
-e git+https://github.com/edx/edx-val.git@64aa7637e3459fb3000a85a9e156880a40307dd1#egg=edx-val
|
||||
-e git+https://github.com/edx/edx-val.git@cb9cf1a37124ad8e589734b36d4e8199e0082a02#egg=edx-val
|
||||
-e git+https://github.com/pmitros/RecommenderXBlock.git@9b07e807c89ba5761827d0387177f71aa57ef056#egg=recommender-xblock
|
||||
-e git+https://github.com/edx/edx-milestones.git@547f2250ee49e73ce8d7ff4e78ecf1b049892510#egg=edx-milestones
|
||||
-e git+https://github.com/edx/edx-search.git@21ac6b06b3bfe789dcaeaf4e2ab5b00a688324d4#egg=edx-search
|
||||
|
||||
Reference in New Issue
Block a user