def test_parse_youtube_key_format(self): """ Make sure that inconsistent speed keys are parsed correctly. """ youtube_str = '1.00:p2Q6BrNhdh8' youtube_str_hack = '1.0:p2Q6BrNhdh8' self.assertEqual(VideoBlock._parse_youtube(youtube_str), VideoBlock._parse_youtube(youtube_str_hack))
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): VideoBlock.from_xml(xml_data, module_system, id_generator=Mock())
def test_import_with_float_times(self): """ Ensure that Video is able to read VideoBlock's model data. """ module_system = DummySystem(load_error_modules=True) xml_data = """ <video display_name="Test Video" youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8" show_captions="false" from="1.0" to="60.0"> <source src="http://www.example.com/source.mp4"/> <track src="http://www.example.com/track"/> </video> """ video = VideoBlock.from_xml(xml_data, module_system, Mock()) self.assert_attributes_equal(video, { 'youtube_id_0_75': 'izygArpw-Qo', 'youtube_id_1_0': 'p2Q6BrNhdh8', 'youtube_id_1_25': '1EeWXzPdhSA', 'youtube_id_1_5': 'rABDYkeK0x8', 'show_captions': False, 'start_time': datetime.timedelta(seconds=1), 'end_time': datetime.timedelta(seconds=60), 'track': 'http://www.example.com/track', # 'download_track': True, 'html5_sources': ['http://www.example.com/source.mp4'], 'data': '' })
def test_old_video_format(self): """ Test backwards compatibility with VideoBlock's XML format. """ module_system = DummySystem(load_error_modules=True) xml_data = """ <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"/> <track src="http://www.example.com/track"/> </video> """ output = VideoBlock.from_xml(xml_data, module_system, Mock()) self.assert_attributes_equal(output, { 'youtube_id_0_75': 'izygArpw-Qo', 'youtube_id_1_0': 'p2Q6BrNhdh8', 'youtube_id_1_25': '1EeWXzPdhSA', 'youtube_id_1_5': 'rABDYkeK0x8', 'show_captions': False, 'start_time': datetime.timedelta(seconds=1), 'end_time': datetime.timedelta(seconds=60), 'track': 'http://www.example.com/track', # 'download_track': True, 'html5_sources': ['http://www.example.com/source.mp4'], 'data': '', })
def test_from_xml(self): module_system = DummySystem(load_error_modules=True) xml_data = ''' <video display_name="Test Video" youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8" 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"/> <handout src="http://www.example.com/handout"/> <transcript language="uk" src="ukrainian_translation.srt" /> <transcript language="de" src="german_translation.srt" /> </video> ''' output = VideoBlock.from_xml(xml_data, module_system, Mock()) self.assert_attributes_equal(output, { 'youtube_id_0_75': 'izygArpw-Qo', 'youtube_id_1_0': 'p2Q6BrNhdh8', 'youtube_id_1_25': '1EeWXzPdhSA', 'youtube_id_1_5': 'rABDYkeK0x8', 'show_captions': False, 'start_time': datetime.timedelta(seconds=1), 'end_time': datetime.timedelta(seconds=60), 'track': 'http://www.example.com/track', 'handout': 'http://www.example.com/handout', 'download_track': False, 'download_video': False, 'html5_sources': ['http://www.example.com/source.mp4'], 'data': '', 'transcripts': {'uk': 'ukrainian_translation.srt', 'de': 'german_translation.srt'}, })
def test_from_xml_missing_download_track(self): """ Ensure that attributes have the right values if they aren't explicitly set in XML. """ module_system = DummySystem(load_error_modules=True) xml_data = ''' <video display_name="Test Video" youtube="1.0:p2Q6BrNhdh8,1.25:1EeWXzPdhSA" show_captions="true"> <source src="http://www.example.com/source.mp4"/> <track src="http://www.example.com/track"/> </video> ''' output = VideoBlock.from_xml(xml_data, module_system, Mock()) self.assert_attributes_equal(output, { 'youtube_id_0_75': '', 'youtube_id_1_0': 'p2Q6BrNhdh8', 'youtube_id_1_25': '1EeWXzPdhSA', 'youtube_id_1_5': '', 'show_captions': True, 'start_time': datetime.timedelta(seconds=0.0), 'end_time': datetime.timedelta(seconds=0.0), 'track': 'http://www.example.com/track', 'download_track': True, 'download_video': False, 'html5_sources': ['http://www.example.com/source.mp4'], 'data': '', 'transcripts': {}, })
def test_parse_youtube(self): """Test parsing old-style Youtube ID strings into a dict.""" youtube_str = '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg' output = VideoBlock._parse_youtube(youtube_str) self.assertEqual(output, {'0.75': 'jNCf2gIqpeE', '1.00': 'ZwkTiUPN0mg', '1.25': 'rsq9auxASqI', '1.50': 'kMyNdzVHHgg'})
def test_parse_youtube_one_video(self): """ Ensure that all keys are present and missing speeds map to the empty string. """ youtube_str = '0.75:jNCf2gIqpeE' output = VideoBlock._parse_youtube(youtube_str) self.assertEqual(output, {'0.75': 'jNCf2gIqpeE', '1.00': '', '1.25': '', '1.50': ''})
def test_parse_youtube_empty(self): """ Some courses have empty youtube attributes, so we should handle that well. """ self.assertEqual(VideoBlock._parse_youtube(''), { '0.75': '', '1.00': '', '1.25': '', '1.50': '' })
def instantiate_descriptor(**field_data): """ Instantiate descriptor with most properties. """ if field_data.get('data', None): field_data = VideoBlock.parse_video_xml(field_data['data']) system = get_test_descriptor_system() course_key = CourseLocator('org', 'course', 'run') usage_key = course_key.make_usage_key('video', 'SampleProblem') return system.construct_xblock_from_class( VideoBlock, scope_ids=ScopeIds(None, None, usage_key, usage_key), field_data=DictFieldData(field_data), )
def test_parse_youtube_invalid(self): """Ensure that ids that are invalid return an empty dict""" # invalid id youtube_str = 'thisisaninvalidid' output = VideoBlock._parse_youtube(youtube_str) self.assertEqual(output, {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}) # another invalid id youtube_str = ',::,:,,' output = VideoBlock._parse_youtube(youtube_str) self.assertEqual(output, {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}) # and another one, partially invalid youtube_str = '0.75_BAD!!!,1.0:AXdE34_U,1.25:KLHF9K_Y,1.5:VO3SxfeD,' output = VideoBlock._parse_youtube(youtube_str) self.assertEqual(output, {'0.75': '', '1.00': 'AXdE34_U', '1.25': 'KLHF9K_Y', '1.50': 'VO3SxfeD'})
def test_import_val_data(self, mock_val_api): """ Test that `from_xml` works method works as expected. """ def mock_val_import(xml, edx_video_id, resource_fs, static_dir, external_transcripts, course_id): """Mock edxval.api.import_from_xml""" self.assertEqual(xml.tag, 'video_asset') self.assertEqual(dict(list(xml.items())), {'mock_attr': ''}) self.assertEqual(edx_video_id, 'test_edx_video_id') self.assertEqual(static_dir, EXPORT_IMPORT_STATIC_DIR) self.assertIsNotNone(resource_fs) self.assertEqual(external_transcripts, {u'en': [u'subs_3_yD_cEKoCk.srt.sjson']}) self.assertEqual(course_id, 'test_course_id') return edx_video_id 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) # Create static directory in import file system and place transcript files inside it. module_system.resources_fs.makedirs(EXPORT_IMPORT_STATIC_DIR, recreate=True) # import new edx_video_id xml_data = """ <video edx_video_id="{edx_video_id}"> <video_asset mock_attr=""/> </video> """.format( edx_video_id=edx_video_id ) id_generator = Mock() id_generator.target_course_id = 'test_course_id' video = VideoBlock.from_xml(xml_data, module_system, id_generator) self.assert_attributes_equal(video, {'edx_video_id': edx_video_id}) mock_val_api.import_from_xml.assert_called_once_with( ANY, edx_video_id, module_system.resources_fs, EXPORT_IMPORT_STATIC_DIR, {u'en': [u'subs_3_yD_cEKoCk.srt.sjson']}, course_id='test_course_id' )
def test_from_xml_when_handout_is_course_asset(self, course_id_string, expected_handout_link): """ Test that if handout link is course_asset then it will contain targeted course_id in handout link. """ module_system = DummySystem(load_error_modules=True) course_id = CourseKey.from_string(course_id_string) xml_data = ''' <video display_name="Test Video" youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8" 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"/> <handout src="/asset-v1:test_org_1+test_course_1+test_run_1+type@[email protected]"/> <transcript language="uk" src="ukrainian_translation.srt" /> <transcript language="de" src="german_translation.srt" /> </video> ''' id_generator = Mock() id_generator.target_course_id = course_id output = VideoBlock.from_xml(xml_data, module_system, id_generator) self.assert_attributes_equal(output, { 'youtube_id_0_75': 'izygArpw-Qo', 'youtube_id_1_0': 'p2Q6BrNhdh8', 'youtube_id_1_25': '1EeWXzPdhSA', 'youtube_id_1_5': 'rABDYkeK0x8', 'show_captions': False, 'start_time': datetime.timedelta(seconds=1), 'end_time': datetime.timedelta(seconds=60), 'track': 'http://www.example.com/track', 'handout': expected_handout_link, 'download_track': False, 'download_video': False, 'html5_sources': ['http://www.example.com/source.mp4'], 'data': '', 'transcripts': {'uk': 'ukrainian_translation.srt', 'de': 'german_translation.srt'}, })
def test_from_xml_no_attributes(self): """ Make sure settings are correct if none are explicitly set in XML. """ module_system = DummySystem(load_error_modules=True) xml_data = '<video></video>' output = VideoBlock.from_xml(xml_data, module_system, Mock()) self.assert_attributes_equal(output, { 'youtube_id_0_75': '', 'youtube_id_1_0': '3_yD_cEKoCk', 'youtube_id_1_25': '', 'youtube_id_1_5': '', 'show_captions': True, 'start_time': datetime.timedelta(seconds=0.0), 'end_time': datetime.timedelta(seconds=0.0), 'track': '', 'handout': None, 'download_track': False, 'download_video': False, 'html5_sources': [], 'data': '', 'transcripts': {}, })
def test_from_xml_double_quote_concatenated_youtube(self): module_system = DummySystem(load_error_modules=True) xml_data = ''' <video display_name="Test Video" youtube="1.0:"p2Q6BrNhdh8",1.25:"1EeWXzPdhSA""> </video> ''' output = VideoBlock.from_xml(xml_data, module_system, Mock()) self.assert_attributes_equal(output, { 'youtube_id_0_75': '', 'youtube_id_1_0': 'p2Q6BrNhdh8', 'youtube_id_1_25': '1EeWXzPdhSA', 'youtube_id_1_5': '', 'show_captions': True, 'start_time': datetime.timedelta(seconds=0.0), 'end_time': datetime.timedelta(seconds=0.0), 'track': '', 'handout': None, 'download_track': False, 'download_video': False, 'html5_sources': [], 'data': '' })
def test_from_xml_double_quotes(self): """ Make sure we can handle the double-quoted string format (which was used for exporting for a few weeks). """ module_system = DummySystem(load_error_modules=True) xml_data = ''' <video display_name=""display_name"" html5_sources="["source_1", "source_2"]" show_captions="false" download_video="true" sub=""html5_subtitles"" track=""http://www.example.com/track"" handout=""http://www.example.com/handout"" download_track="true" youtube_id_0_75=""OEoXaMPEzf65"" youtube_id_1_25=""OEoXaMPEzf125"" youtube_id_1_5=""OEoXaMPEzf15"" youtube_id_1_0=""OEoXaMPEzf10"" /> ''' output = VideoBlock.from_xml(xml_data, module_system, Mock()) self.assert_attributes_equal(output, { 'youtube_id_0_75': 'OEoXaMPEzf65', 'youtube_id_1_0': 'OEoXaMPEzf10', 'youtube_id_1_25': 'OEoXaMPEzf125', 'youtube_id_1_5': 'OEoXaMPEzf15', 'show_captions': False, 'start_time': datetime.timedelta(seconds=0.0), 'end_time': datetime.timedelta(seconds=0.0), 'track': 'http://www.example.com/track', 'handout': 'http://www.example.com/handout', 'download_track': True, 'download_video': True, 'html5_sources': ["source_1", "source_2"], 'data': '' })
def setUp(self): """ Common setup. """ super(TestMigrateTranscripts, self).setUp() self.store = modulestore() self.course = CourseFactory.create() self.course_2 = CourseFactory.create() video = { 'edx_video_id': 'test_edx_video_id', 'client_video_id': 'test1.mp4', 'duration': 42.0, 'status': 'upload', 'courses': [six.text_type(self.course.id)], 'encoded_videos': [], 'created': datetime.now(pytz.utc) } api.create_video(video) video_sample_xml = ''' <video display_name="Test Video" edx_video_id="test_edx_video_id" youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8" show_captions="false" download_track="false" start_time="1.0" download_video="false" end_time="60.0"> <source src="http://www.example.com/source.mp4"/> <track src="http://www.example.com/track"/> <handout src="http://www.example.com/handout"/> <transcript language="ge" src="subs_grmtran1.srt" /> <transcript language="hr" src="subs_croatian1.srt" /> </video> ''' video_sample_xml_2 = ''' <video display_name="Test Video 2" edx_video_id="test_edx_video_id_2" youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8" show_captions="false" download_track="false" start_time="1.0" download_video="false" end_time="60.0"> <source src="http://www.example.com/source.mp4"/> <track src="http://www.example.com/track"/> <handout src="http://www.example.com/handout"/> <transcript language="ge" src="not_found.srt" /> </video> ''' self.video_descriptor = ItemFactory.create( parent_location=self.course.location, category='video', **VideoBlock.parse_video_xml(video_sample_xml) ) self.video_descriptor_2 = ItemFactory.create( parent_location=self.course_2.location, category='video', **VideoBlock.parse_video_xml(video_sample_xml_2) ) save_to_store(SRT_FILEDATA, 'subs_grmtran1.srt', 'text/srt', self.video_descriptor.location) save_to_store(CRO_SRT_FILEDATA, 'subs_croatian1.srt', 'text/srt', self.video_descriptor.location)
def set_fields_from_xml(self, item, xml): fields_data = VideoBlock.parse_video_xml(xml) for key, value in fields_data.items(): setattr(item, key, value)
def test_student_video_data(self): module_system = DummySystem(load_error_modules=True) video_field_data = { "display_name": "Video", "youtube": "1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8", "show_captions": False, } video_block_keys = ScopeIds("a_user", "video", "def_id_video", "usage_id_video") video_block = VideoBlock( module_system, scope_ids=video_block_keys, field_data=DictFieldData(video_field_data), ) field_data = { "display_name": "Annotated video", "video_id": video_block.scope_ids.usage_id, "annotations": [ { "id": "715ad1df-1be0-4fe7-b0d0-fc21e2a0d050", "title": "Title", "description": "Description", "image_url": "/static/image.png", "start": 10, } ], } block = self._construct_xblock_mock( self.block_class, self.keys, field_data=DictFieldData(field_data), ) block.children.append(video_block.scope_ids.block_type) def get_block(usage_id): if usage_id == "video": return video_block self.runtime_mock.get_block.side_effect = get_block response = block.student_view_data_and_user_state(request=None) data = response.json self.assertDictEqual( data, { "child_blocks": [ { "block_type": "video", "display_name": "Video", "usage_id": "video", }, ], "display_name": "Annotated video", "video_id": video_block.scope_ids.usage_id, "annotations": [ { "description": "Description", "id": "715ad1df-1be0-4fe7-b0d0-fc21e2a0d050", "start": 10, "title": "Title", "image_url": "/static/image.png", } ], }, )