Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class CourseWaffleFlagsSerializer(serializers.Serializer):
enable_unit_expanded_view = serializers.SerializerMethodField()
enable_outline_component_creation = serializers.SerializerMethodField()
enable_audio_description = serializers.SerializerMethodField()
enable_transcript_editor = serializers.SerializerMethodField()

def get_course_key(self):
"""
Expand Down Expand Up @@ -201,10 +200,3 @@ def get_enable_audio_description(self, obj):
"""
course_key = self.get_course_key()
return toggles.audio_description_enabled(course_key)

def get_enable_transcript_editor(self, obj):
"""
Method to get the contentstore.enable_transcript_editor waffle flag.
"""
course_key = self.get_course_key()
return toggles.transcript_editor_enabled(course_key)
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ class CourseWaffleFlagsViewTest(CourseTestCase):
"enable_unit_expanded_view": False,
"enable_outline_component_creation": False,
"enable_audio_description": False,
"enable_transcript_editor": False,
}

def setUp(self):
Expand Down Expand Up @@ -85,55 +84,3 @@ def test_audio_description_upload_flag_enabled(self):
url = reverse("cms.djangoapps.contentstore:v1:course_waffle_flags")
response = self.client.get(url)
assert response.data["enable_audio_description"] is True

def test_enable_transcript_editor_flag_default_is_false(self):
"""
The contentstore.enable_transcript_editor flag should default to False when not
overridden, both globally and for a specific course.
"""
global_url = reverse("cms.djangoapps.contentstore:v1:course_waffle_flags")
course_url = reverse(
"cms.djangoapps.contentstore:v1:course_waffle_flags",
kwargs={"course_id": self.course.id},
)
for url in (global_url, course_url):
response = self.client.get(url)
assert response.data["enable_transcript_editor"] is False

@override_waffle_flag(toggles.ENABLE_TRANSCRIPT_EDITOR, active=True)
def test_enable_transcript_editor_flag_enabled_globally(self):
"""
When the contentstore.enable_transcript_editor flag is active globally, the
serializer should return True for both the global endpoint and any
course-specific endpoint.
"""
global_url = reverse("cms.djangoapps.contentstore:v1:course_waffle_flags")
course_url = reverse(
"cms.djangoapps.contentstore:v1:course_waffle_flags",
kwargs={"course_id": self.course.id},
)
for url in (global_url, course_url):
response = self.client.get(url)
assert response.data["enable_transcript_editor"] is True

def test_enable_transcript_editor_flag_enabled_per_course(self):
"""
When the contentstore.enable_transcript_editor flag is enabled via a
WaffleFlagCourseOverrideModel entry for a specific course, the
course-scoped endpoint should return True while the global endpoint
should remain False.
"""
WaffleFlagCourseOverrideModel.objects.create(
waffle_flag=toggles.ENABLE_TRANSCRIPT_EDITOR.name,
course_id=self.course.id,
enabled=True,
)
global_url = reverse("cms.djangoapps.contentstore:v1:course_waffle_flags")
course_url = reverse(
"cms.djangoapps.contentstore:v1:course_waffle_flags",
kwargs={"course_id": self.course.id},
)
global_response = self.client.get(global_url)
course_response = self.client.get(course_url)
assert global_response.data["enable_transcript_editor"] is False
assert course_response.data["enable_transcript_editor"] is True
25 changes: 0 additions & 25 deletions cms/djangoapps/contentstore/toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,31 +90,6 @@ def audio_description_enabled(course_key):
return ENABLE_AUDIO_DESCRIPTION.is_enabled(course_key)


# .. toggle_name: contentstore.enable_transcript_editor
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
# .. toggle_description: Enables the in-platform transcript editor in Studio's
# videos page. When enabled, course staff can open an editor modal from the
# transcript row action menu and edit transcript cue text directly in the
# browser; edits are saved via PATCH to a new v1 transcript endpoint. When
# disabled, the "Edit transcript" menu item is hidden and the API endpoint
# returns 404. Existing upload, download, and delete flows are unaffected.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2026-05-05
# .. toggle_tickets: TNL2-608
ENABLE_TRANSCRIPT_EDITOR = CourseWaffleFlag(
'contentstore.enable_transcript_editor',
__name__,
)


def transcript_editor_enabled(course_key):
"""
Return True if the in-platform transcript editor is enabled for the course.
"""
return ENABLE_TRANSCRIPT_EDITOR.is_enabled(course_key)


# .. toggle_name: legacy_studio.exam_settings
# .. toggle_implementation: WaffleFlag
# .. toggle_default: False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,31 @@ def test_transcript_upload_handler(self, mock_create_or_update_video_transcript)
file_data=ANY,
)

@patch('cms.djangoapps.contentstore.transcript_storage_handlers.create_or_update_video_transcript')
@patch(
'cms.djangoapps.contentstore.transcript_storage_handlers.get_available_transcript_languages',
Mock(return_value=['en']),
)
def test_transcript_upload_handler_returns_200_on_replace(self, mock_create_or_update_video_transcript):
"""
Verify that uploading a transcript for a language that already has a
transcript returns 200 (replace) instead of 201 (create).
"""
transcript_file_stream = StringIO('0\n00:00:00,010 --> 00:00:00,100\nHello, edX greets you.\n\n')
response = self.client.post(
self.view_url,
{
'edx_video_id': '123',
'language_code': 'en',
'new_language_code': 'en',
'file': transcript_file_stream,
},
format='multipart'
)

self.assertEqual(response.status_code, 200) # noqa: PT009
mock_create_or_update_video_transcript.assert_called_once()

@ddt.data(
(
{
Expand Down
Loading