Skip to content

Commit

Permalink
feat: add drf for studio video page (#33528)
Browse files Browse the repository at this point in the history
  • Loading branch information
KristinAoki authored Oct 27, 2023
1 parent 3c50f3e commit 8cfd04f
Show file tree
Hide file tree
Showing 9 changed files with 543 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
)
from .settings import CourseSettingsSerializer
from .xblock import XblockSerializer
from .videos import VideoUploadSerializer, VideoImageSerializer
from .videos import (
CourseVideosSerializer,
VideoUploadSerializer,
VideoImageSerializer,
VideoUsageSerializer
)
from .transcripts import TranscriptSerializer
from .assets import AssetSerializer
85 changes: 85 additions & 0 deletions cms/djangoapps/contentstore/rest_api/v1/serializers/videos.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,91 @@ class FileSpecSerializer(StrictSerializer):
content_type = serializers.ChoiceField(choices=['video/mp4', 'video/webm', 'video/ogg'])


class VideoImageSettingsSerializer(serializers.Serializer):
"""Serializer for image settings"""
video_image_upload_enabled = serializers.BooleanField()
max_size = serializers.IntegerField()
min_size = serializers.IntegerField()
max_width = serializers.IntegerField()
max_height = serializers.IntegerField()
supported_file_formats = serializers.DictField(
child=serializers.CharField()
)


class VideoTranscriptSettingsSerializer(serializers.Serializer):
"""Serializer for transcript settings"""
transcript_download_handler_url = serializers.CharField()
transcript_upload_handler_url = serializers.CharField()
transcript_delete_handler_url = serializers.CharField()
trancript_download_file_format = serializers.CharField()
transcript_preferences_handler_url = serializers.CharField(required=False, allow_null=True)
transcript_credentials_handler_url = serializers.CharField(required=False, allow_null=True)
transcription_plans = serializers.DictField(
child=serializers.DictField(),
required=False,
allow_null=True,
)


class VideoModelSerializer(serializers.Serializer):
"""Serializer for a video"""
client_video_id = serializers.CharField()
course_video_image_url = serializers.CharField()
created = serializers.CharField()
duration = serializers.FloatField()
edx_video_id = serializers.CharField()
error_description = serializers.CharField()
status = serializers.CharField()
file_size = serializers.IntegerField()
download_link = serializers.CharField()
transcript_urls = serializers.DictField(
child=serializers.CharField()
)
transcription_status = serializers.CharField()
transcripts = serializers.ListField(
child=serializers.CharField()
)


class CourseVideosSerializer(serializers.Serializer):
"""Serializer for course videos"""
image_upload_url = serializers.CharField()
video_handler_url = serializers.CharField()
encodings_download_url = serializers.CharField()
default_video_image_url = serializers.CharField()
previous_uploads = VideoModelSerializer(many=True, required=False)
concurrent_upload_limit = serializers.IntegerField()
video_supported_file_formats = serializers.ListField(
child=serializers.CharField()
)
video_upload_max_file_size = serializers.CharField()
video_image_settings = VideoImageSettingsSerializer(required=True, allow_null=False)
is_video_transcript_enabled = serializers.BooleanField()
active_transcript_preferences = serializers.BooleanField(required=False, allow_null=True)
transcript_credentials = serializers.DictField(
child=serializers.CharField()
)
transcript_available_languages = serializers.ListField(
child=serializers.DictField(
child=serializers.CharField()
)
)
video_transcript_settings = VideoTranscriptSettingsSerializer()
pagination_context = serializers.DictField(
child=serializers.CharField(),
required=False,
allow_null=True,
)


class VideoUsageSerializer(serializers.Serializer):
"""Serializer for video usage"""
usage_locations = serializers.ListField(
child=serializers.CharField()
)


class VideoUploadSerializer(StrictSerializer):
"""
Strict Serializer for video upload urls.
Expand Down
12 changes: 12 additions & 0 deletions cms/djangoapps/contentstore/rest_api/v1/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
CourseGradingView,
CourseRerunView,
CourseSettingsView,
CourseVideosView,
HomePageView,
ProctoredExamSettingsView,
ProctoringErrorsView,
Expand All @@ -19,6 +20,7 @@
videos,
transcripts,
HelpUrlsView,
VideoUsageView
)

app_name = 'v1'
Expand All @@ -31,6 +33,16 @@
HomePageView.as_view(),
name="home"
),
re_path(
fr'^videos/{COURSE_ID_PATTERN}$',
CourseVideosView.as_view(),
name="course_videos"
),
re_path(
fr'^videos/{COURSE_ID_PATTERN}/{VIDEO_ID_PATTERN}/usage$',
VideoUsageView.as_view(),
name="video_usage"
),
re_path(
fr'^proctored_exam_settings/{COURSE_ID_PATTERN}$',
ProctoredExamSettingsView.as_view(),
Expand Down
4 changes: 3 additions & 1 deletion cms/djangoapps/contentstore/rest_api/v1/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
from .xblock import XblockView, XblockCreateView
from .assets import AssetsCreateRetrieveView, AssetsUpdateDestroyView
from .videos import (
CourseVideosView,
VideosUploadsView,
VideosCreateUploadView,
VideoImagesView,
VideoEncodingsDownloadView,
VideoFeaturesView
VideoFeaturesView,
VideoUsageView,
)
from .help_urls import HelpUrlsView
128 changes: 128 additions & 0 deletions cms/djangoapps/contentstore/rest_api/v1/views/tests/test_videos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""
Unit tests for course settings views.
"""
import ddt
from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from edx_toggles.toggles import WaffleSwitch
from edx_toggles.toggles.testutils import override_waffle_switch
from edxval.api import (
get_3rd_party_transcription_plans,
get_transcript_credentials_state_for_org,
get_transcript_preferences,
)
from mock import patch
from rest_framework import status

from cms.djangoapps.contentstore.video_storage_handlers import get_all_transcript_languages
from cms.djangoapps.contentstore.tests.utils import CourseTestCase
from cms.djangoapps.contentstore.utils import reverse_course_url

from ...mixins import PermissionAccessMixin


@ddt.ddt
class CourseVideosViewTest(CourseTestCase, PermissionAccessMixin):
"""
Tests for CourseVideosView.
"""

def setUp(self):
super().setUp()
self.url = reverse(
"cms.djangoapps.contentstore:v1:course_videos",
kwargs={"course_id": self.course.id},
)

def test_course_videos_response(self):
"""Check successful response content"""
response = self.client.get(self.url)
expected_response = {
"image_upload_url": reverse_course_url("video_images_handler", str(self.course.id)),
"video_handler_url": reverse_course_url("videos_handler", str(self.course.id)),
"encodings_download_url": reverse_course_url("video_encodings_download", str(self.course.id)),
"default_video_image_url": staticfiles_storage.url(settings.VIDEO_IMAGE_DEFAULT_FILENAME),
"previous_uploads": [],
"concurrent_upload_limit": settings.VIDEO_UPLOAD_PIPELINE.get("CONCURRENT_UPLOAD_LIMIT", 0),
"video_supported_file_formats": [".mp4", ".mov"],
"video_upload_max_file_size": "5",
"video_image_settings": {
"video_image_upload_enabled": False,
"max_size": settings.VIDEO_IMAGE_SETTINGS["VIDEO_IMAGE_MAX_BYTES"],
"min_size": settings.VIDEO_IMAGE_SETTINGS["VIDEO_IMAGE_MIN_BYTES"],
"max_width": settings.VIDEO_IMAGE_MAX_WIDTH,
"max_height": settings.VIDEO_IMAGE_MAX_HEIGHT,
"supported_file_formats": settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS
},
"is_video_transcript_enabled": False,
"active_transcript_preferences": None,
"transcript_credentials": None,
"transcript_available_languages": get_all_transcript_languages(),
"video_transcript_settings": {
"transcript_download_handler_url": reverse('transcript_download_handler'),
"transcript_upload_handler_url": reverse('transcript_upload_handler'),
"transcript_delete_handler_url": reverse_course_url("transcript_delete_handler", str(self.course.id)),
"trancript_download_file_format": "srt",
"transcript_preferences_handler_url": None,
"transcript_credentials_handler_url": None,
"transcription_plans": None
},
"pagination_context": {}
}

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(expected_response, response.data)

@override_waffle_switch(WaffleSwitch( # lint-amnesty, pylint: disable=toggle-missing-annotation
'videos.video_image_upload_enabled', __name__
), True)
def test_video_image_upload_enabled(self):
"""
Make sure if the feature flag is enabled we have updated the dict keys in response.
"""
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn("video_image_settings", response.data)

imageSettings = response.data["video_image_settings"]
self.assertIn("video_image_upload_enabled", imageSettings)
self.assertTrue(imageSettings["video_image_upload_enabled"])

def test_VideoTranscriptEnabledFlag_enabled(self):
"""
Make sure if the feature flags are enabled we have updated the dict keys in response.
"""
with patch('openedx.core.djangoapps.video_config.models.VideoTranscriptEnabledFlag.feature_enabled') as feature:
feature.return_value = True
response = self.client.get(self.url)
self.assertIn("is_video_transcript_enabled", response.data)
self.assertTrue(response.data["is_video_transcript_enabled"])

expect_active_preferences = get_transcript_preferences(str(self.course.id))
self.assertIn("active_transcript_preferences", response.data)
self.assertEqual(expect_active_preferences, response.data["active_transcript_preferences"])

expected_credentials = get_transcript_credentials_state_for_org(self.course.id.org)
self.assertIn("transcript_credentials", response.data)
self.assertDictEqual(expected_credentials, response.data["transcript_credentials"])

transcript_settings = response.data["video_transcript_settings"]

expected_plans = get_3rd_party_transcription_plans()
self.assertIn("transcription_plans", transcript_settings)
self.assertDictEqual(expected_plans, transcript_settings["transcription_plans"])

expected_preference_handler = reverse_course_url(
'transcript_preferences_handler',
str(self.course.id)
)
self.assertIn("transcript_preferences_handler_url", transcript_settings)
self.assertEqual(expected_preference_handler, transcript_settings["transcript_preferences_handler_url"])

expected_credentials_handler = reverse_course_url(
'transcript_credentials_handler',
str(self.course.id)
)
self.assertIn("transcript_credentials_handler_url", transcript_settings)
self.assertEqual(expected_credentials_handler, transcript_settings["transcript_credentials_handler_url"])
Loading

0 comments on commit 8cfd04f

Please sign in to comment.