Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
runs-on: ${{ matrix.os-version }}
strategy:
matrix:
fail-fast: false
python-version:
- "3.11"
- "3.12"
Expand Down
99 changes: 17 additions & 82 deletions cms/djangoapps/contentstore/tests/test_transcripts_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import tempfile
import textwrap
import unittest
from unittest.mock import Mock, patch
from unittest.mock import patch
from uuid import uuid4

import ddt
Expand All @@ -30,6 +30,19 @@
TEST_DATA_CONTENTSTORE['DOC_STORE_CONFIG']['db'] = 'test_xcontent_%s' % uuid4().hex


def save_subs_to_store(subs, subs_id, item, language='en'):
"""
Save transcripts into `StaticContent`.
Args:
`subs_id`: str, subtitles id
`item`: video block instance
`language`: two chars str ('uk'), language of translation of transcripts
Returns: location of saved subtitles.
"""
filedata = json.dumps(subs, indent=2).encode('utf-8')
filename = transcripts_utils.subs_filename(subs_id, language)
return transcripts_utils.save_to_store(filedata, filename, 'application/json', item.location)

class TestGenerateSubs(unittest.TestCase):
"""Tests for `generate_subs` function."""
def setUp(self):
Expand Down Expand Up @@ -142,18 +155,11 @@ def setUp(self):
self.addCleanup(self.clear_subs_content)
self.clear_subs_content()

def test_save_unicode_filename(self):
# Mock a video item
item = Mock(location=Mock(course_key=self.course.id))
transcripts_utils.save_subs_to_store(self.subs, self.subs_id, self.course)
transcripts_utils.copy_or_rename_transcript(self.subs_copied_id, self.subs_id, item)
self.assertTrue(contentstore().find(self.content_copied_location))

def test_save_subs_to_store(self):
with self.assertRaises(NotFoundError):
contentstore().find(self.content_location)

result_location = transcripts_utils.save_subs_to_store(
result_location = save_subs_to_store(
self.subs,
self.subs_id,
self.course)
Expand All @@ -169,7 +175,7 @@ def test_save_unjsonable_subs_to_store(self):
contentstore().find(self.content_location_unjsonable)

with self.assertRaises(TypeError):
transcripts_utils.save_subs_to_store(
save_subs_to_store(
self.unjsonable_subs,
self.unjsonable_subs_id,
self.course)
Expand Down Expand Up @@ -295,77 +301,6 @@ def test_success_downloading_chinese_transcripts(self):
self.clear_sub_content(good_youtube_sub)


class TestGenerateSubsFromSource(TestDownloadYoutubeSubs): # lint-amnesty, pylint: disable=test-inherits-tests
"""Tests for `generate_subs_from_source` function."""

def test_success_generating_subs(self):
youtube_subs = {
0.5: 'JMD_ifUUfsU',
1.0: 'hI10vDNYz4M',
2.0: 'AKqURZnYqpk'
}
srt_filedata = textwrap.dedent("""
1
00:00:10,500 --> 00:00:13,000
Elephant's Dream

2
00:00:15,000 --> 00:00:18,000
At the left we can see...
""")
self.clear_subs_content(youtube_subs)

# Check TranscriptsGenerationException not thrown.
# Also checks that uppercase file extensions are supported.
transcripts_utils.generate_subs_from_source(youtube_subs, 'SRT', srt_filedata, self.course)

# Check assets status after importing subtitles.
for subs_id in youtube_subs.values():
filename = f'subs_{subs_id}.srt.sjson'
content_location = StaticContent.compute_location(
self.course.id, filename
)
self.assertTrue(contentstore().find(content_location))

self.clear_subs_content(youtube_subs)

def test_fail_bad_subs_type(self):
youtube_subs = {
0.5: 'JMD_ifUUfsU',
1.0: 'hI10vDNYz4M',
2.0: 'AKqURZnYqpk'
}

srt_filedata = textwrap.dedent("""
1
00:00:10,500 --> 00:00:13,000
Elephant's Dream

2
00:00:15,000 --> 00:00:18,000
At the left we can see...
""")

with self.assertRaises(TranscriptsGenerationException) as cm:
transcripts_utils.generate_subs_from_source(youtube_subs, 'BAD_FORMAT', srt_filedata, self.course)
exception_message = str(cm.exception)
self.assertEqual(exception_message, "We support only SubRip (*.srt) transcripts format.")

def test_fail_bad_subs_filedata(self):
youtube_subs = {
0.5: 'JMD_ifUUfsU',
1.0: 'hI10vDNYz4M',
2.0: 'AKqURZnYqpk'
}

srt_filedata = """BAD_DATA"""

with self.assertRaises(TranscriptsGenerationException) as cm:
transcripts_utils.generate_subs_from_source(youtube_subs, 'srt', srt_filedata, self.course)
exception_message = str(cm.exception)
self.assertEqual(exception_message, "Something wrong with SubRip transcripts file during parsing.")


class TestGenerateSrtFromSjson(TestDownloadYoutubeSubs): # lint-amnesty, pylint: disable=test-inherits-tests
"""Tests for `generate_srt_from_sjson` function."""

Expand Down Expand Up @@ -759,7 +694,7 @@ def create_transcript(self, subs_id, language='en', filename='video.srt', youtub
possible_subs = [subs_id, youtube_id_1_0] + transcripts_utils.get_html5_ids(html5_sources)
for possible_sub in possible_subs:
if possible_sub:
transcripts_utils.save_subs_to_store(
save_subs_to_store(
self.subs_sjson,
possible_sub,
self.video,
Expand Down
16 changes: 3 additions & 13 deletions cms/djangoapps/contentstore/toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,13 @@ def exam_setting_view_enabled(course_key):
return not LEGACY_STUDIO_EXAM_SETTINGS.is_enabled(course_key)


# .. toggle_name: legacy_studio.video_editor
# .. toggle_implementation: WaffleFlag
# .. toggle_default: False
# .. toggle_description: Temporarily fall back to the old Video component (a.k.a. video block) editor.
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2025-03-14
# .. toggle_target_removal_date: 2025-09-14
# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275
# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available.
LEGACY_STUDIO_VIDEO_EDITOR = CourseWaffleFlag('legacy_studio.video_editor', __name__)


def use_new_video_editor(course_key):
"""
TODO: This method and its usage will be removed in the following story:
https://github.com/openedx/public-engineering/issues/464
Returns a boolean = true if new video editor is enabled
"""
return not LEGACY_STUDIO_VIDEO_EDITOR.is_enabled(course_key)
return True


# .. toggle_name: new_core_editors.use_video_gallery_flow
Expand Down
19 changes: 0 additions & 19 deletions lms/djangoapps/courseware/tests/test_video_mongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1526,25 +1526,6 @@ def test_editor_saved_when_html5_sub_not_exist(self):
item.editor_saved(self.user, old_metadata, None)
assert isinstance(Transcript.get_asset(item.location, 'subs_3_yD_cEKoCk.srt.sjson'), StaticContent)

def test_editor_saved_when_youtube_and_html5_subs_exist(self):
"""
When both youtube_sub and html5_sub already exist then no new
sub will be generated by editor_saved function.
"""
self.initialize_block(metadata=self.metadata)
item = self.store.get_item(self.block.location)
with open(self.file_path, "rb") as myfile: # lint-amnesty, pylint: disable=bad-option-value, open-builtin
save_to_store(myfile.read(), self.file_name, 'text/sjson', item.location)
save_to_store(myfile.read(), 'subs_video.srt.sjson', 'text/sjson', item.location)
item.sub = "3_yD_cEKoCk"
# subs_3_yD_cEKoCk.srt.sjson and subs_video.srt.sjson already exist
assert isinstance(Transcript.get_asset(item.location, self.file_name), StaticContent)
assert isinstance(Transcript.get_asset(item.location, 'subs_video.srt.sjson'), StaticContent)
old_metadata = own_metadata(item)
with patch('xmodule.video_block.video_block.manage_video_subtitles_save') as manage_video_subtitles_save:
item.editor_saved(self.user, old_metadata, None)
assert not manage_video_subtitles_save.called

def test_editor_saved_with_unstripped_video_id(self):
"""
Verify editor saved when video id contains spaces/tabs.
Expand Down
Loading